From cd8bbcb19340c1c9584d8cb6c81ec38f209106b0 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Mon, 23 May 2022 13:53:40 +0200
Subject: [PATCH] Changed descriptor writes to use class

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 config/Sources.cmake                          |   3 +
 include/vkcv/DescriptorWrites.hpp             |  97 +++++++----
 .../src/vkcv/effects/BloomAndFlaresEffect.cpp |  69 ++++----
 .../material/src/vkcv/material/Material.cpp   |   4 +-
 .../src/vkcv/upscaling/FSRUpscaling.cpp       |  20 +--
 .../src/vkcv/upscaling/NISUpscaling.cpp       |  12 +-
 projects/bindless_textures/src/main.cpp       |  18 +-
 projects/first_mesh/src/main.cpp              |   4 +-
 projects/first_triangle/src/main.cpp          |   2 -
 projects/head_demo/src/main.cpp               |   4 +-
 projects/indirect_dispatch/src/App.cpp        |  13 +-
 projects/indirect_dispatch/src/MotionBlur.cpp | 154 +++++++++---------
 projects/indirect_draw/src/main.cpp           |  40 ++---
 projects/mesh_shader/src/main.cpp             |  25 +--
 projects/particle_simulation/src/main.cpp     |  17 +-
 projects/path_tracer/src/main.cpp             |  50 +++---
 projects/rtx_ambient_occlusion/src/main.cpp   |   2 +-
 projects/saf_r/src/main.cpp                   |  10 +-
 projects/sph/src/main.cpp                     |  23 +--
 projects/voxelization/src/ShadowMapping.cpp   |  18 +-
 projects/voxelization/src/Voxelization.cpp    |  40 ++---
 projects/voxelization/src/main.cpp            |  72 ++++----
 projects/wobble_bobble/src/main.cpp           |  30 ++--
 src/vkcv/DescriptorManager.cpp                |  10 +-
 src/vkcv/DescriptorWrites.cpp                 |  75 +++++++++
 25 files changed, 462 insertions(+), 350 deletions(-)
 create mode 100644 src/vkcv/DescriptorWrites.cpp

diff --git a/config/Sources.cmake b/config/Sources.cmake
index d74c407b..98dc2bc3 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -86,6 +86,9 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/DescriptorConfig.hpp
 		${vkcv_source}/vkcv/DescriptorConfig.cpp
 		
+		${vkcv_include}/vkcv/DescriptorWrites.hpp
+		${vkcv_source}/vkcv/DescriptorWrites.cpp
+		
 		${vkcv_source}/vkcv/SamplerManager.hpp
 		${vkcv_source}/vkcv/SamplerManager.cpp
 
diff --git a/include/vkcv/DescriptorWrites.hpp b/include/vkcv/DescriptorWrites.hpp
index eef0f18c..bb7f2591 100644
--- a/include/vkcv/DescriptorWrites.hpp
+++ b/include/vkcv/DescriptorWrites.hpp
@@ -12,52 +12,85 @@
 namespace vkcv {
 	
 	struct SampledImageDescriptorWrite {
-		inline SampledImageDescriptorWrite(uint32_t binding, ImageHandle image, uint32_t mipLevel = 0, bool useGeneralLayout = false, uint32_t arrayIndex = 0)
-		: binding(binding), image(image), mipLevel(mipLevel), useGeneralLayout(useGeneralLayout), arrayIndex(arrayIndex) {};
-		uint32_t	binding;
-		ImageHandle	image;
-		uint32_t    mipLevel;
-		bool        useGeneralLayout;
-		uint32_t    arrayIndex;
+		uint32_t binding;
+		ImageHandle image;
+		uint32_t mipLevel;
+		bool useGeneralLayout;
+		uint32_t arrayIndex;
 	};
 
 	struct StorageImageDescriptorWrite {
-		inline StorageImageDescriptorWrite(uint32_t binding, ImageHandle image, uint32_t mipLevel = 0) 
-			: binding(binding), image(image), mipLevel(mipLevel) {};
-		uint32_t	binding;
-		ImageHandle	image;
-		uint32_t	mipLevel;
+		uint32_t binding;
+		ImageHandle image;
+		uint32_t mipLevel;
 	};
 
 	struct BufferDescriptorWrite {
-		inline BufferDescriptorWrite(uint32_t binding, BufferHandle buffer, bool dynamic = false,
-									 uint32_t offset = 0, uint32_t size = 0) :
-		binding(binding), buffer(buffer), dynamic(dynamic), offset(offset), size(size) {};
-		uint32_t		binding;
-		BufferHandle	buffer;
-		bool 			dynamic;
-		uint32_t 		offset;
-		uint32_t 		size;
+		uint32_t binding;
+		BufferHandle buffer;
+		bool dynamic;
+		uint32_t offset;
+		uint32_t size;
 	};
 
 	struct SamplerDescriptorWrite {
-		inline SamplerDescriptorWrite(uint32_t binding, SamplerHandle sampler) : binding(binding), sampler(sampler) {};
-		uint32_t		binding;
-		SamplerHandle	sampler;
+		uint32_t binding;
+		SamplerHandle sampler;
 	};
 	
 	struct AccelerationDescriptorWrite {
-	    inline AccelerationDescriptorWrite(uint32_t binding) : binding(binding) {};
-	    uint32_t    binding;
+	    uint32_t binding;
 	};
 
-	struct DescriptorWrites {
-		std::vector<SampledImageDescriptorWrite>		sampledImageWrites;
-		std::vector<StorageImageDescriptorWrite>		storageImageWrites;
-		std::vector<BufferDescriptorWrite>	    		uniformBufferWrites;
-		std::vector<BufferDescriptorWrite>	    		storageBufferWrites;
-		std::vector<SamplerDescriptorWrite>			    samplerWrites;
-		std::vector<AccelerationDescriptorWrite>        accelerationWrites;
+	class DescriptorWrites {
+	private:
+		std::vector<SampledImageDescriptorWrite> m_sampledImageWrites;
+		std::vector<StorageImageDescriptorWrite> m_storageImageWrites;
+		std::vector<BufferDescriptorWrite> m_uniformBufferWrites;
+		std::vector<BufferDescriptorWrite> m_storageBufferWrites;
+		std::vector<SamplerDescriptorWrite> m_samplerWrites;
+		std::vector<AccelerationDescriptorWrite> m_accelerationWrites;
+		
+	public:
+		DescriptorWrites& writeSampledImage(uint32_t binding,
+											ImageHandle image,
+											uint32_t mipLevel = 0,
+											bool useGeneralLayout = false,
+											uint32_t arrayIndex = 0);
+		
+		DescriptorWrites& writeStorageImage(uint32_t binding,
+											ImageHandle image,
+											uint32_t mipLevel = 0);
+		
+		DescriptorWrites& writeUniformBuffer(uint32_t binding,
+											 BufferHandle buffer,
+											 bool dynamic = false,
+											 uint32_t offset = 0,
+											 uint32_t size = 0);
+		
+		DescriptorWrites& writeStorageBuffer(uint32_t binding,
+											 BufferHandle buffer,
+											 bool dynamic = false,
+											 uint32_t offset = 0,
+											 uint32_t size = 0);
+		
+		DescriptorWrites& writeSampler(uint32_t binding,
+									   SamplerHandle sampler);
+		
+		DescriptorWrites& writeAcceleration(uint32_t binding);
+		
+		const std::vector<SampledImageDescriptorWrite>& getSampledImageWrites() const;
+		
+		const std::vector<StorageImageDescriptorWrite>& getStorageImageWrites() const;
+		
+		const std::vector<BufferDescriptorWrite>& getUniformBufferWrites() const;
+		
+		const std::vector<BufferDescriptorWrite>& getStorageBufferWrites() const;
+		
+		const std::vector<SamplerDescriptorWrite>& getSamplerWrites() const;
+		
+		const std::vector<AccelerationDescriptorWrite>& getAccelerationWrites() const;
+		
 	};
 	
 }
\ No newline at end of file
diff --git a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
index 78456da2..c8e51fe9 100644
--- a/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
+++ b/modules/effects/src/vkcv/effects/BloomAndFlaresEffect.cpp
@@ -272,13 +272,13 @@ namespace vkcv::effects {
 			DescriptorWrites mipDownsampleWrites;
 			
 			if (mipLevel > 0) {
-				mipDownsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, sample, mipLevel - 1, true)};
+				mipDownsampleWrites.writeSampledImage(0, sample, mipLevel - 1, true);
 			} else {
-				mipDownsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, input)};
+				mipDownsampleWrites.writeSampledImage(0, input);
 			}
 			
-			mipDownsampleWrites.samplerWrites      = {SamplerDescriptorWrite(1, m_linearSampler)};
-			mipDownsampleWrites.storageImageWrites = {StorageImageDescriptorWrite(2, sample, mipLevel) };
+			mipDownsampleWrites.writeSampler(1, m_linearSampler);
+			mipDownsampleWrites.writeStorageImage(2, sample, mipLevel);
 			
 			m_core.writeDescriptorSet(mipDescriptorSets[mipLevel], mipDownsampleWrites);
 			
@@ -325,9 +325,9 @@ namespace vkcv::effects {
 		for(uint32_t mipLevel = mipDescriptorSets.size(); mipLevel > 0; mipLevel--) {
 			// mip descriptor writes
 			DescriptorWrites mipUpsampleWrites;
-			mipUpsampleWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, sample, mipLevel, true)};
-			mipUpsampleWrites.samplerWrites      = {SamplerDescriptorWrite(1, m_linearSampler)};
-			mipUpsampleWrites.storageImageWrites = {StorageImageDescriptorWrite(2, sample, mipLevel - 1) };
+			mipUpsampleWrites.writeSampledImage(0, sample, mipLevel, true);
+			mipUpsampleWrites.writeSampler(1, m_linearSampler);
+			mipUpsampleWrites.writeStorageImage(2, sample, mipLevel - 1);
 			
 			m_core.writeDescriptorSet(mipDescriptorSets[mipLevel - 1], mipUpsampleWrites);
 			
@@ -370,9 +370,9 @@ namespace vkcv::effects {
 		const uint32_t flaresHeight = m_core.getImageHeight(m_flaresImage);
 		
 		DescriptorWrites lensFlaresWrites;
-		lensFlaresWrites.sampledImageWrites = {SampledImageDescriptorWrite(0, m_blurImage, 0)};
-		lensFlaresWrites.samplerWrites = {SamplerDescriptorWrite(1, m_linearSampler)};
-		lensFlaresWrites.storageImageWrites = {StorageImageDescriptorWrite(2, m_flaresImage, mipLevel)};
+		lensFlaresWrites.writeSampledImage(0, m_blurImage, 0);
+		lensFlaresWrites.writeSampler(1, m_linearSampler);
+		lensFlaresWrites.writeStorageImage(2, m_flaresImage, mipLevel);
 		
 		m_core.writeDescriptorSet(m_lensFlaresDescriptorSet, lensFlaresWrites);
 		
@@ -415,34 +415,33 @@ namespace vkcv::effects {
 		vkcv::DescriptorWrites compositeWrites;
 		
 		if (m_advanced) {
-			compositeWrites.sampledImageWrites = {
-					SampledImageDescriptorWrite(0, m_blurImage),
-					SampledImageDescriptorWrite(1, m_flaresImage),
-					SampledImageDescriptorWrite(4, m_radialLut),
-					SampledImageDescriptorWrite(6, m_lensDirt)
-			};
+			compositeWrites.writeSampledImage(
+					0, m_blurImage
+			).writeSampledImage(
+					1, m_flaresImage
+			).writeSampledImage(
+					4, m_radialLut
+			).writeSampledImage(
+					6, m_lensDirt
+			);
 			
-			compositeWrites.samplerWrites = {
-					SamplerDescriptorWrite(2, m_linearSampler),
-					SamplerDescriptorWrite(5, m_radialLutSampler)
-			};
+			compositeWrites.writeSampler(
+					2, m_linearSampler
+			).writeSampler(
+					5, m_radialLutSampler
+			);
 			
-			compositeWrites.storageImageWrites = {
-					StorageImageDescriptorWrite(3, output)
-			};
+			compositeWrites.writeStorageImage(3, output);
 		} else {
-			compositeWrites.sampledImageWrites = {
-					SampledImageDescriptorWrite(0, m_blurImage),
-					SampledImageDescriptorWrite(1, m_flaresImage)
-			};
+			compositeWrites.writeSampledImage(
+					0, m_blurImage
+			).writeSampledImage(
+					1, m_flaresImage
+			);
 			
-			compositeWrites.samplerWrites = {
-					SamplerDescriptorWrite(2, m_linearSampler)
-			};
+			compositeWrites.writeSampler(2, m_linearSampler);
 			
-			compositeWrites.storageImageWrites = {
-					StorageImageDescriptorWrite(3, output)
-			};
+			compositeWrites.writeStorageImage(3, output);
 		}
 		
 		m_core.writeDescriptorSet(m_compositeDescriptorSet, compositeWrites);
@@ -477,11 +476,11 @@ namespace vkcv::effects {
 				0.0f, 1.0f, 1.0f, 1.0f
 		});
 		
-		const uint32_t halfWidth = static_cast<uint32_t>(std::ceil(
+		const auto halfWidth = static_cast<uint32_t>(std::ceil(
 				static_cast<float>(m_core.getImageWidth(output)) * 0.5f
 		));
 		
-		const uint32_t halfHeight = static_cast<uint32_t>(std::ceil(
+		const auto halfHeight = static_cast<uint32_t>(std::ceil(
 				static_cast<float>(m_core.getImageHeight(output)) * 0.5f
 		));
 		
diff --git a/modules/material/src/vkcv/material/Material.cpp b/modules/material/src/vkcv/material/Material.cpp
index bd26733b..2bd18e83 100644
--- a/modules/material/src/vkcv/material/Material.cpp
+++ b/modules/material/src/vkcv/material/Material.cpp
@@ -201,8 +201,8 @@ namespace vkcv::material {
 		vkcv::DescriptorWrites setWrites;
 		
 		for (size_t i = 0; i < material.m_Textures.size(); i++) {
-			setWrites.sampledImageWrites.emplace_back(i * 2, material.m_Textures[i].m_Image);
-			setWrites.samplerWrites.emplace_back(i * 2 + 1, material.m_Textures[i].m_Sampler);
+			setWrites.writeSampledImage(i * 2, material.m_Textures[i].m_Image);
+			setWrites.writeSampler(i * 2 + 1, material.m_Textures[i].m_Sampler);
 		}
 		
 		core.writeDescriptorSet(material.m_DescriptorSet, setWrites);
diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
index 5a2c9641..a2009440 100644
--- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp
@@ -240,11 +240,11 @@ namespace vkcv::upscaling {
 
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_easuConstants.getHandle(),true
 			);
 			
-			writes.samplerWrites.emplace_back(3, m_sampler);
+			writes.writeSampler(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 		}
@@ -261,11 +261,11 @@ namespace vkcv::upscaling {
 			}});
 
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_rcasConstants.getHandle(),true
 			);
 			
-			writes.samplerWrites.emplace_back(3, m_sampler);
+			writes.writeSampler(3, m_sampler);
 			
 			m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
 		}
@@ -329,15 +329,15 @@ namespace vkcv::upscaling {
 		if (rcasEnabled) {
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, input);
-				writes.storageImageWrites.emplace_back(2, m_intermediateImage);
+				writes.writeSampledImage(1, input);
+				writes.writeStorageImage(2, m_intermediateImage);
 				
 				m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 			}
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, m_intermediateImage);
-				writes.storageImageWrites.emplace_back(2, output);
+				writes.writeSampledImage(1, m_intermediateImage);
+				writes.writeStorageImage(2, output);
 				
 				m_core.writeDescriptorSet(m_rcasDescriptorSet, writes);
 			}
@@ -374,8 +374,8 @@ namespace vkcv::upscaling {
 		} else {
 			{
 				DescriptorWrites writes;
-				writes.sampledImageWrites.emplace_back(1, input);
-				writes.storageImageWrites.emplace_back(2, output);
+				writes.writeSampledImage(1, input);
+				writes.writeStorageImage(2, output);
 				
 				m_core.writeDescriptorSet(m_easuDescriptorSet, writes);
 			}
diff --git a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
index 998d7f83..2fd8e23f 100644
--- a/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
+++ b/modules/upscaling/src/vkcv/upscaling/NISUpscaling.cpp
@@ -186,13 +186,13 @@ namespace vkcv::upscaling {
 			
 			
 			DescriptorWrites writes;
-			writes.uniformBufferWrites.emplace_back(
+			writes.writeUniformBuffer(
 					0, m_scalerConstants.getHandle(), true
 			);
 			
-			writes.samplerWrites.emplace_back(1, m_sampler);
-			writes.sampledImageWrites.emplace_back(4, m_coefScaleImage);
-			writes.sampledImageWrites.emplace_back(5, m_coefUsmImage);
+			writes.writeSampler(1, m_sampler);
+			writes.writeSampledImage(4, m_coefScaleImage);
+			writes.writeSampledImage(5, m_coefUsmImage);
 			
 			m_core.writeDescriptorSet(m_scalerDescriptorSet, writes);
 		}
@@ -242,8 +242,8 @@ namespace vkcv::upscaling {
 		
 		{
 			DescriptorWrites writes;
-			writes.sampledImageWrites.emplace_back(2, input);
-			writes.storageImageWrites.emplace_back(3, output);
+			writes.writeSampledImage(2, input);
+			writes.writeStorageImage(3, output);
 			
 			m_core.writeDescriptorSet(m_scalerDescriptorSet, writes);
 		}
diff --git a/projects/bindless_textures/src/main.cpp b/projects/bindless_textures/src/main.cpp
index f8fa8db9..b6d20341 100644
--- a/projects/bindless_textures/src/main.cpp
+++ b/projects/bindless_textures/src/main.cpp
@@ -188,18 +188,20 @@ int main(int argc, const char** argv) {
 		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
 
 	vkcv::DescriptorWrites setWrites;
-	std::vector<vkcv::SampledImageDescriptorWrite> texturesArrayWrites;
+	
 	for(uint32_t i = 0; i < 6; i++)
 	{
-	    texturesArrayWrites.push_back(vkcv::SampledImageDescriptorWrite(1,
-                                                                        texturesArray[i].getHandle(),
-                                                                        0,
-                                                                        false,
-                                                                        i));
+		
+		setWrites.writeSampledImage(
+				1,
+				texturesArray[i].getHandle(),
+				0,
+				false,
+				i
+		);
 	}
 
-	setWrites.sampledImageWrites	= texturesArrayWrites;
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(0, sampler) };
+	setWrites.writeSampler(0, sampler);
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index c8da98ab..1fdea636 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -140,8 +140,8 @@ int main(int argc, const char** argv) {
 		vkcv::VertexBufferBinding(static_cast<vk::DeviceSize>(attributes[2].offset), vertexBuffer.getVulkanHandle()) };
 
 	vkcv::DescriptorWrites setWrites;
-	setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
-	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
+	setWrites.writeSampledImage(0, texture.getHandle());
+	setWrites.writeSampler(1, sampler);
 
 	core.writeDescriptorSet(descriptorSet, setWrites);
 	
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 3bdefe3a..3d1331ed 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -51,8 +51,6 @@ int main(int argc, const char** argv) {
 		{vkcv::ShaderStage::VERTEX, "shaders/shader.vert"},
 		{ vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" }
 	}, nullptr);
-	
-	const auto swapchainExtent = core.getSwapchain(windowHandle).getExtent();
 
 	const vkcv::GraphicsPipelineConfig trianglePipelineDefinition {
 		triangleShaderProgram,
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 3eeec03a..d6a67e63 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -113,9 +113,7 @@ int main(int argc, const char** argv) {
 	clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 	
 	vkcv::DescriptorWrites clipWrites;
-	clipWrites.uniformBufferWrites = {
-			vkcv::BufferDescriptorWrite(0, clipBuffer.getHandle())
-	};
+	clipWrites.writeUniformBuffer(0, clipBuffer.getHandle());
 	
 	core.writeDescriptorSet(clipDescriptorSet, clipWrites);
 	
diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp
index cc897e68..e6885b8e 100644
--- a/projects/indirect_dispatch/src/App.cpp
+++ b/projects/indirect_dispatch/src/App.cpp
@@ -73,8 +73,8 @@ bool App::initialize() {
 	m_cameraManager.getCamera(cameraIndex).setNearFar(0.1f, 30.f);
 	
 	vkcv::DescriptorWrites meshPassDescriptorWrites;
-	meshPassDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, m_gridTexture) };
-	meshPassDescriptorWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
+	meshPassDescriptorWrites.writeSampledImage(0, m_gridTexture);
+	meshPassDescriptorWrites.writeSampler(1, m_linearSampler);
 	m_core.writeDescriptorSet(m_meshPass.descriptorSet, meshPassDescriptorWrites);
 
 	return true;
@@ -317,12 +317,9 @@ void App::run() {
 
 		// gamma correction
 		vkcv::DescriptorWrites gammaCorrectionDescriptorWrites;
-		gammaCorrectionDescriptorWrites.sampledImageWrites = {
-			vkcv::SampledImageDescriptorWrite(0, motionBlurOutput) };
-		gammaCorrectionDescriptorWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, m_linearSampler) };
-		gammaCorrectionDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(2, swapchainInput) };
+		gammaCorrectionDescriptorWrites.writeSampledImage(0, motionBlurOutput);
+		gammaCorrectionDescriptorWrites.writeSampler(1, m_linearSampler);
+		gammaCorrectionDescriptorWrites.writeStorageImage(2, swapchainInput);
 
 		m_core.writeDescriptorSet(m_gammaCorrectionPass.descriptorSet, gammaCorrectionDescriptorWrites);
 
diff --git a/projects/indirect_dispatch/src/MotionBlur.cpp b/projects/indirect_dispatch/src/MotionBlur.cpp
index 30116c84..c9345684 100644
--- a/projects/indirect_dispatch/src/MotionBlur.cpp
+++ b/projects/indirect_dispatch/src/MotionBlur.cpp
@@ -75,14 +75,16 @@ bool MotionBlur::initialize(vkcv::Core* corePtr, const uint32_t targetWidth, con
 		true).getHandle();
 
 	vkcv::DescriptorWrites tileResetDescriptorWrites;
-	tileResetDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, m_fullPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(1, m_copyPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(2, m_fastPathWorkTileBuffer) };
+	tileResetDescriptorWrites.writeStorageBuffer(
+			0, m_fullPathWorkTileBuffer
+	).writeStorageBuffer(
+			1, m_copyPathWorkTileBuffer
+	).writeStorageBuffer(
+			2, m_fastPathWorkTileBuffer
+	);
 
 	m_core->writeDescriptorSet(m_tileResetPass.descriptorSet, tileResetDescriptorWrites);
 
-
 	m_renderTargets = MotionBlurSetup::createRenderTargets(targetWidth, targetHeight, *m_core);
 
 	m_nearestSampler = m_core->createSampler(
@@ -129,15 +131,20 @@ vkcv::ImageHandle MotionBlur::render(
 
 	// work tile classification
 	vkcv::DescriptorWrites tileClassificationDescriptorWrites;
-	tileClassificationDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, m_renderTargets.motionMaxNeighbourhood),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMinNeighbourhood) };
-	tileClassificationDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	tileClassificationDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, m_fullPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(4, m_copyPathWorkTileBuffer),
-		vkcv::BufferDescriptorWrite(5, m_fastPathWorkTileBuffer) };
+	tileClassificationDescriptorWrites.writeSampledImage(
+			0, m_renderTargets.motionMaxNeighbourhood
+	).writeSampledImage(
+			1, m_renderTargets.motionMinNeighbourhood
+	);
+	
+	tileClassificationDescriptorWrites.writeSampler(2, m_nearestSampler);
+	tileClassificationDescriptorWrites.writeStorageBuffer(
+			3, m_fullPathWorkTileBuffer
+	).writeStorageBuffer(
+			4, m_copyPathWorkTileBuffer
+	).writeStorageBuffer(
+			5, m_fastPathWorkTileBuffer
+	);
 
 	m_core->writeDescriptorSet(m_tileClassificationPass.descriptorSet, tileClassificationDescriptorWrites);
 
@@ -174,44 +181,41 @@ vkcv::ImageHandle MotionBlur::render(
 	m_core->recordBufferMemoryBarrier(cmdStream, m_fastPathWorkTileBuffer);
 
 	vkcv::DescriptorWrites motionBlurDescriptorWrites;
-	motionBlurDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer),
-		vkcv::SampledImageDescriptorWrite(1, depthBuffer),
-		vkcv::SampledImageDescriptorWrite(2, motionBufferFullRes),
-		vkcv::SampledImageDescriptorWrite(3, m_renderTargets.motionMaxNeighbourhood) };
-	motionBlurDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(4, m_nearestSampler) };
-	motionBlurDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(5, m_renderTargets.outputColor) };
-	motionBlurDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(6, m_fullPathWorkTileBuffer)};
+	motionBlurDescriptorWrites.writeSampledImage(
+			0, colorBuffer
+	).writeSampledImage(
+			1, depthBuffer
+	).writeSampledImage(
+			2, motionBufferFullRes
+	).writeSampledImage(
+			3, m_renderTargets.motionMaxNeighbourhood
+	);
+	
+	motionBlurDescriptorWrites.writeSampler(4, m_nearestSampler);
+	motionBlurDescriptorWrites.writeStorageImage(5, m_renderTargets.outputColor);
+	motionBlurDescriptorWrites.writeStorageBuffer(6, m_fullPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_motionBlurPass.descriptorSet, motionBlurDescriptorWrites);
 
-
 	vkcv::DescriptorWrites colorCopyDescriptorWrites;
-	colorCopyDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-	colorCopyDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	colorCopyDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor) };
-	colorCopyDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, m_copyPathWorkTileBuffer) };
+	colorCopyDescriptorWrites.writeSampledImage(0, colorBuffer);
+	colorCopyDescriptorWrites.writeSampler(1, m_nearestSampler);
+	colorCopyDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
+	colorCopyDescriptorWrites.writeStorageBuffer(3, m_copyPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_colorCopyPass.descriptorSet, colorCopyDescriptorWrites);
 
 
 	vkcv::DescriptorWrites fastPathDescriptorWrites;
-	fastPathDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, colorBuffer),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMaxNeighbourhood) };
-	fastPathDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	fastPathDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.outputColor) };
-	fastPathDescriptorWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(4, m_fastPathWorkTileBuffer) };
+	fastPathDescriptorWrites.writeSampledImage(
+			0, colorBuffer
+	).writeSampledImage(
+			1, m_renderTargets.motionMaxNeighbourhood
+	);
+	
+	fastPathDescriptorWrites.writeSampler(2, m_nearestSampler);
+	fastPathDescriptorWrites.writeStorageImage(3, m_renderTargets.outputColor);
+	fastPathDescriptorWrites.writeStorageBuffer(4, m_fastPathWorkTileBuffer);
 
 	m_core->writeDescriptorSet(m_motionBlurFastPathPass.descriptorSet, fastPathDescriptorWrites);
 
@@ -279,16 +283,17 @@ vkcv::ImageHandle MotionBlur::render(
 	else if (mode == eMotionBlurMode::TileVisualisation) {
 
 		vkcv::DescriptorWrites visualisationDescriptorWrites;
-		visualisationDescriptorWrites.sampledImageWrites = { 
-			vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-		visualisationDescriptorWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-		visualisationDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor)};
-		visualisationDescriptorWrites.storageBufferWrites = {
-			vkcv::BufferDescriptorWrite(3, m_fullPathWorkTileBuffer),
-			vkcv::BufferDescriptorWrite(4, m_copyPathWorkTileBuffer),
-			vkcv::BufferDescriptorWrite(5, m_fastPathWorkTileBuffer) };
+		visualisationDescriptorWrites.writeSampledImage(0, colorBuffer);
+		visualisationDescriptorWrites.writeSampler(1, m_nearestSampler);
+		visualisationDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
+		
+		visualisationDescriptorWrites.writeStorageBuffer(
+				3, m_fullPathWorkTileBuffer
+		).writeStorageBuffer(
+				4, m_copyPathWorkTileBuffer
+		).writeStorageBuffer(
+				5, m_fastPathWorkTileBuffer
+		);
 
 		m_core->writeDescriptorSet(m_tileVisualisationPass.descriptorSet, visualisationDescriptorWrites);
 
@@ -345,12 +350,9 @@ vkcv::ImageHandle MotionBlur::renderMotionVectorVisualisation(
 	}
 
 	vkcv::DescriptorWrites motionVectorVisualisationDescriptorWrites;
-	motionVectorVisualisationDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, visualisationInput) };
-	motionVectorVisualisationDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	motionVectorVisualisationDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.outputColor) };
+	motionVectorVisualisationDescriptorWrites.writeSampledImage(0, visualisationInput);
+	motionVectorVisualisationDescriptorWrites.writeSampler(1, m_nearestSampler);
+	motionVectorVisualisationDescriptorWrites.writeStorageImage(2, m_renderTargets.outputColor);
 
 	m_core->writeDescriptorSet(
 		m_motionVectorVisualisationPass.descriptorSet,
@@ -383,13 +385,13 @@ void MotionBlur::computeMotionTiles(
 
 	// motion vector min max tiles
 	vkcv::DescriptorWrites motionVectorMaxTilesDescriptorWrites;
-	motionVectorMaxTilesDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, motionBufferFullRes) };
-	motionVectorMaxTilesDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(1, m_nearestSampler) };
-	motionVectorMaxTilesDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(2, m_renderTargets.motionMax),
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.motionMin) };
+	motionVectorMaxTilesDescriptorWrites.writeSampledImage(0, motionBufferFullRes);
+	motionVectorMaxTilesDescriptorWrites.writeSampler(1, m_nearestSampler);
+	motionVectorMaxTilesDescriptorWrites.writeStorageImage(
+			2, m_renderTargets.motionMax
+	).writeStorageImage(
+			3, m_renderTargets.motionMin
+	);
 
 	m_core->writeDescriptorSet(m_motionVectorMinMaxPass.descriptorSet, motionVectorMaxTilesDescriptorWrites);
 
@@ -411,14 +413,18 @@ void MotionBlur::computeMotionTiles(
 
 	// motion vector min max neighbourhood
 	vkcv::DescriptorWrites motionVectorMaxNeighbourhoodDescriptorWrites;
-	motionVectorMaxNeighbourhoodDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(0, m_renderTargets.motionMax),
-		vkcv::SampledImageDescriptorWrite(1, m_renderTargets.motionMin) };
-	motionVectorMaxNeighbourhoodDescriptorWrites.samplerWrites = {
-		vkcv::SamplerDescriptorWrite(2, m_nearestSampler) };
-	motionVectorMaxNeighbourhoodDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, m_renderTargets.motionMaxNeighbourhood),
-		vkcv::StorageImageDescriptorWrite(4, m_renderTargets.motionMinNeighbourhood) };
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeSampledImage(
+			0, m_renderTargets.motionMax
+	).writeSampledImage(
+			1, m_renderTargets.motionMin
+	);
+	
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeSampler(2, m_nearestSampler);
+	motionVectorMaxNeighbourhoodDescriptorWrites.writeStorageImage(
+			3, m_renderTargets.motionMaxNeighbourhood
+	).writeStorageImage(
+			4, m_renderTargets.motionMinNeighbourhood
+	);
 
 	m_core->writeDescriptorSet(m_motionVectorMinMaxNeighbourhoodPass.descriptorSet, motionVectorMaxNeighbourhoodDescriptorWrites);
 
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index 2a213a2a..7bcf4cef 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -444,18 +444,17 @@ int main(int argc, const char** argv) {
             vkcv::SamplerMipmapMode::LINEAR,
             vkcv::SamplerAddressMode::REPEAT
     );
-
+	
+	vkcv::DescriptorWrites setWrites;
+	
     std::vector<vkcv::SampledImageDescriptorWrite> textureArrayWrites;
     for(uint32_t i = 0; i < compiledMaterial.baseColor.size(); i++)
     {
-        vkcv::SampledImageDescriptorWrite baseColorWrite(2, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
-        textureArrayWrites.push_back(baseColorWrite);
+		setWrites.writeSampledImage(2, compiledMaterial.baseColor[i].getHandle(), 0, false, i);
     }
-
-    vkcv::DescriptorWrites setWrites;
-    setWrites.sampledImageWrites	= textureArrayWrites;
-    setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(0, standardSampler) };
-	setWrites.storageBufferWrites   = { vkcv::BufferDescriptorWrite(1, modelBuffer.getHandle())};
+    
+    setWrites.writeSampler(0, standardSampler);
+	setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
 	const vkcv::GraphicsPipelineConfig sponzaPipelineConfig {
@@ -481,29 +480,10 @@ int main(int argc, const char** argv) {
             vkcv::BufferType::UNIFORM,
             1);
 
-    //Plane dummyPlane{};
-    //dummyPlane.pointOnPlane = glm::vec3(0.0f);
-    //dummyPlane.padding0 = 0.0f;
-    //dummyPlane.normal = glm::vec3(0.0f);
-    //dummyPlane.padding1 = 0.0f;
-
-    //CameraPlanes dummyCameraPlane{};
-    //dummyCameraPlane.planes[0] = dummyPlane;
-    //dummyCameraPlane.planes[1] = dummyPlane;
-    //dummyCameraPlane.planes[2] = dummyPlane;
-    //dummyCameraPlane.planes[3] = dummyPlane;
-    //dummyCameraPlane.planes[4] = dummyPlane;
-    //dummyCameraPlane.planes[5] = dummyPlane;
-
-    //cameraPlaneBuffer.fill(&dummyCameraPlane);
-
-    vkcv::BufferDescriptorWrite cameraPlaneWrite(0, cameraPlaneBuffer.getHandle());
-    vkcv::BufferDescriptorWrite drawCommandsWrite(1, indirectBuffer.getHandle());
-    vkcv::BufferDescriptorWrite boundingBoxWrite(2, boundingBoxBuffer.getHandle());
-
     vkcv::DescriptorWrites cullingWrites;
-    cullingWrites.storageBufferWrites = {drawCommandsWrite, boundingBoxWrite};
-    cullingWrites.uniformBufferWrites = {cameraPlaneWrite};
+	cullingWrites.writeStorageBuffer(1, indirectBuffer.getHandle());
+	cullingWrites.writeStorageBuffer(2, boundingBoxBuffer.getHandle());
+    cullingWrites.writeUniformBuffer(0, cameraPlaneBuffer.getHandle());
     core.writeDescriptorSet(cullingDescSet, cullingWrites);
 
 
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
index afaec1a8..cebcab24 100644
--- a/projects/mesh_shader/src/main.cpp
+++ b/projects/mesh_shader/src/main.cpp
@@ -218,7 +218,7 @@ int main(int argc, const char** argv) {
 	vkcv::Buffer<ObjectMatrices> matrixBuffer = core.createBuffer<ObjectMatrices>(vkcv::BufferType::STORAGE, objectCount);
 
 	vkcv::DescriptorWrites vertexShaderDescriptorWrites;
-	vertexShaderDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, matrixBuffer.getHandle()) };
+	vertexShaderDescriptorWrites.writeStorageBuffer(0, matrixBuffer.getHandle());
 	core.writeDescriptorSet(vertexShaderDescriptorSet, vertexShaderDescriptorWrites);
 
 	vkcv::GraphicsPipelineHandle bunnyPipeline = core.createGraphicsPipeline(bunnyPipelineDefinition);
@@ -271,16 +271,19 @@ int main(int argc, const char** argv) {
 	vkcv::Buffer<CameraPlanes> cameraPlaneBuffer = core.createBuffer<CameraPlanes>(vkcv::BufferType::UNIFORM, 1);
 
 	vkcv::DescriptorWrites meshShaderWrites;
-	meshShaderWrites.storageBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, meshShaderVertexBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(1, meshShaderIndexBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(2, meshletBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(4, matrixBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(5, meshletBuffer.getHandle()),
-	};
-	meshShaderWrites.uniformBufferWrites = {
-		vkcv::BufferDescriptorWrite(3, cameraPlaneBuffer.getHandle()),
-	};
+	meshShaderWrites.writeStorageBuffer(
+			0, meshShaderVertexBuffer.getHandle()
+	).writeStorageBuffer(
+			1, meshShaderIndexBuffer.getHandle()
+	).writeStorageBuffer(
+			2, meshletBuffer.getHandle()
+	).writeStorageBuffer(
+			4, matrixBuffer.getHandle()
+	).writeStorageBuffer(
+			5, meshletBuffer.getHandle()
+	);
+	
+	meshShaderWrites.writeUniformBuffer(3, cameraPlaneBuffer.getHandle());
 
     core.writeDescriptorSet( meshShaderDescriptorSet, meshShaderWrites);
 
diff --git a/projects/particle_simulation/src/main.cpp b/projects/particle_simulation/src/main.cpp
index f1490e6f..eaaed424 100644
--- a/projects/particle_simulation/src/main.cpp
+++ b/projects/particle_simulation/src/main.cpp
@@ -161,13 +161,12 @@ int main(int argc, const char **argv) {
     particleBuffer.fill(particleSystem.getParticles());
 
     vkcv::DescriptorWrites setWrites;
-    setWrites.uniformBufferWrites = {vkcv::BufferDescriptorWrite(0,color.getHandle()),
-                                     vkcv::BufferDescriptorWrite(1,position.getHandle())};
-    setWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(2,particleBuffer.getHandle())};
+    setWrites.writeUniformBuffer(0, color.getHandle()).writeUniformBuffer(1, position.getHandle());
+    setWrites.writeStorageBuffer(2, particleBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
     vkcv::DescriptorWrites computeWrites;
-    computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,particleBuffer.getHandle())};
+    computeWrites.writeStorageBuffer(0, particleBuffer.getHandle());
     core.writeDescriptorSet(computeDescriptorSet, computeWrites);
 
     if (!particlePipeline || !computePipeline)
@@ -308,10 +307,12 @@ int main(int argc, const char **argv) {
         core.prepareImageForStorage(cmdStream, swapchainInput);
 
         vkcv::DescriptorWrites tonemappingDescriptorWrites;
-        tonemappingDescriptorWrites.storageImageWrites = {
-            vkcv::StorageImageDescriptorWrite(0, colorBuffer),
-            vkcv::StorageImageDescriptorWrite(1, swapchainInput)
-        };
+        tonemappingDescriptorWrites.writeStorageImage(
+				0, colorBuffer
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
         core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites);
 
         uint32_t tonemappingDispatchCount[3];
diff --git a/projects/path_tracer/src/main.cpp b/projects/path_tracer/src/main.cpp
index b76244b0..670986ff 100644
--- a/projects/path_tracer/src/main.cpp
+++ b/projects/path_tracer/src/main.cpp
@@ -108,10 +108,7 @@ int main(int argc, const char** argv) {
 	});
 
 	vkcv::DescriptorWrites imageCombineDescriptorWrites;
-	imageCombineDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(0, outputImage),
-		vkcv::StorageImageDescriptorWrite(1, meanImage)
-	};
+	imageCombineDescriptorWrites.writeStorageImage(0, outputImage).writeStorageImage(1, meanImage);
 	core.writeDescriptorSet(imageCombineDescriptorSet, imageCombineDescriptorWrites);
 
 	// image present shader
@@ -145,9 +142,7 @@ int main(int argc, const char** argv) {
 	});
 
 	vkcv::DescriptorWrites imageClearDescriptorWrites;
-	imageClearDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(0, meanImage)
-	};
+	imageClearDescriptorWrites.writeStorageImage(0, meanImage);
 	core.writeDescriptorSet(imageClearDescriptorSet, imageClearDescriptorWrites);
 
 	// buffers
@@ -194,12 +189,15 @@ int main(int argc, const char** argv) {
 		materialSettings.size());
 
 	vkcv::DescriptorWrites traceDescriptorWrites;
-	traceDescriptorWrites.storageBufferWrites = { 
-		vkcv::BufferDescriptorWrite(0, sphereBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(1, planeBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(2, materialBuffer.getHandle())};
-	traceDescriptorWrites.storageImageWrites = {
-		vkcv::StorageImageDescriptorWrite(3, outputImage)};
+	traceDescriptorWrites.writeStorageBuffer(
+			0, sphereBuffer.getHandle()
+	).writeStorageBuffer(
+			1, planeBuffer.getHandle()
+	).writeStorageBuffer(
+			2, materialBuffer.getHandle()
+	);
+	
+	traceDescriptorWrites.writeStorageImage(3, outputImage);
 	core.writeDescriptorSet(traceDescriptorSet, traceDescriptorWrites);
 
 	vkcv::ComputePipelineHandle tracePipeline = core.createComputePipeline({
@@ -272,21 +270,20 @@ int main(int argc, const char** argv) {
 				true).getHandle();
 
 			// update descriptor sets
-			traceDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(3, outputImage) };
+			traceDescriptorWrites.writeStorageImage(3, outputImage);
 			core.writeDescriptorSet(traceDescriptorSet, traceDescriptorWrites);
 
 			vkcv::DescriptorWrites imageCombineDescriptorWrites;
-			imageCombineDescriptorWrites.storageImageWrites = {
-				vkcv::StorageImageDescriptorWrite(0, outputImage),
-				vkcv::StorageImageDescriptorWrite(1, meanImage)
-			};
+			imageCombineDescriptorWrites.writeStorageImage(
+					0, outputImage
+			).writeStorageImage(
+					1, meanImage
+			);
+			
 			core.writeDescriptorSet(imageCombineDescriptorSet, imageCombineDescriptorWrites);
 
 			vkcv::DescriptorWrites imageClearDescriptorWrites;
-			imageClearDescriptorWrites.storageImageWrites = {
-				vkcv::StorageImageDescriptorWrite(0, meanImage)
-			};
+			imageClearDescriptorWrites.writeStorageImage(0, meanImage);
 			core.writeDescriptorSet(imageClearDescriptorSet, imageClearDescriptorWrites);
 
 			widthPrevious  = swapchainWidth;
@@ -397,9 +394,12 @@ int main(int argc, const char** argv) {
 		const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
 
 		vkcv::DescriptorWrites presentDescriptorWrites;
-		presentDescriptorWrites.storageImageWrites = {
-			vkcv::StorageImageDescriptorWrite(0, meanImage),
-			vkcv::StorageImageDescriptorWrite(1, swapchainInput) };
+		presentDescriptorWrites.writeStorageImage(
+				0, meanImage
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
 		core.writeDescriptorSet(presentDescriptorSet, presentDescriptorWrites);
 
 		core.prepareImageForStorage(cmdStream, swapchainInput);
diff --git a/projects/rtx_ambient_occlusion/src/main.cpp b/projects/rtx_ambient_occlusion/src/main.cpp
index becd80c4..0276f05d 100644
--- a/projects/rtx_ambient_occlusion/src/main.cpp
+++ b/projects/rtx_ambient_occlusion/src/main.cpp
@@ -135,7 +135,7 @@ int main(int argc, const char** argv) {
 
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
-		rtxWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(0, swapchainInput) };
+		rtxWrites.writeStorageImage(0, swapchainInput);
 		core.writeDescriptorSet(rtxShaderDescriptorSet, rtxWrites);
 
 		core.prepareImageForStorage(cmdStream, swapchainInput);
diff --git a/projects/saf_r/src/main.cpp b/projects/saf_r/src/main.cpp
index 85420cfd..e6738de6 100644
--- a/projects/saf_r/src/main.cpp
+++ b/projects/saf_r/src/main.cpp
@@ -145,8 +145,12 @@ int main(int argc, const char** argv) {
 	sphereBuffer.fill(spheres);
 
 	vkcv::DescriptorWrites computeWrites;
-	computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,lightsBuffer.getHandle()),
-                                          vkcv::BufferDescriptorWrite(1,sphereBuffer.getHandle())};
+	computeWrites.writeStorageBuffer(
+			0, lightsBuffer.getHandle()
+	).writeStorageBuffer(
+			1, sphereBuffer.getHandle()
+	);
+	
     core.writeDescriptorSet(computeDescriptorSet, computeWrites);
 
 	auto safrIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
@@ -253,7 +257,7 @@ int main(int argc, const char** argv) {
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
 
 		//configure the outImage for compute shader (render into the swapchain image)
-        computeWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, swapchainInput)};
+        computeWrites.writeStorageImage(2, swapchainInput);
         core.writeDescriptorSet(computeDescriptorSet, computeWrites);
         core.prepareImageForStorage (cmdStream, swapchainInput);
 
diff --git a/projects/sph/src/main.cpp b/projects/sph/src/main.cpp
index e7a1c894..34a0e7cf 100644
--- a/projects/sph/src/main.cpp
+++ b/projects/sph/src/main.cpp
@@ -180,15 +180,16 @@ int main(int argc, const char **argv) {
 	particleBuffer2.fill(particles);
 
     vkcv::DescriptorWrites setWrites;
-    setWrites.uniformBufferWrites = {vkcv::BufferDescriptorWrite(0,color.getHandle()),
-                                     vkcv::BufferDescriptorWrite(1,position.getHandle())};
-    setWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(2,particleBuffer1.getHandle()),
-									  vkcv::BufferDescriptorWrite(3,particleBuffer2.getHandle())};
+    setWrites.writeUniformBuffer(0, color.getHandle()).writeUniformBuffer(1, position.getHandle());
+    setWrites.writeStorageBuffer(2, particleBuffer1.getHandle()).writeStorageBuffer(3, particleBuffer2.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
     vkcv::DescriptorWrites computeWrites;
-    computeWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0,particleBuffer1.getHandle()),
-										  vkcv::BufferDescriptorWrite(1,particleBuffer2.getHandle())};
+    computeWrites.writeStorageBuffer(
+			0, particleBuffer1.getHandle()
+	).writeStorageBuffer(
+			1, particleBuffer2.getHandle()
+	);
     
     core.writeDescriptorSet(pressureDescriptorSet, computeWrites);
 	core.writeDescriptorSet(forceDescriptorSet, computeWrites);
@@ -404,10 +405,12 @@ int main(int argc, const char **argv) {
         core.prepareImageForStorage(cmdStream, swapchainInput);
 
         vkcv::DescriptorWrites tonemappingDescriptorWrites;
-        tonemappingDescriptorWrites.storageImageWrites = {
-            vkcv::StorageImageDescriptorWrite(0, colorBuffer),
-            vkcv::StorageImageDescriptorWrite(1, swapchainInput)
-        };
+        tonemappingDescriptorWrites.writeStorageImage(
+				0, colorBuffer
+		).writeStorageImage(
+				1, swapchainInput
+		);
+		
         core.writeDescriptorSet(tonemappingDescriptor, tonemappingDescriptorWrites);
 
         uint32_t tonemappingDispatchCount[3];
diff --git a/projects/voxelization/src/ShadowMapping.cpp b/projects/voxelization/src/ShadowMapping.cpp
index 5ae7eb60..53a11ceb 100644
--- a/projects/voxelization/src/ShadowMapping.cpp
+++ b/projects/voxelization/src/ShadowMapping.cpp
@@ -195,9 +195,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
     m_depthToMomentsPipe = corePtr->createComputePipeline({ depthToMomentsShader, { m_depthToMomentsDescriptorSetLayout }});
 
 	vkcv::DescriptorWrites depthToMomentDescriptorWrites;
-	depthToMomentDescriptorWrites.sampledImageWrites    = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapDepth.getHandle()) };
-	depthToMomentDescriptorWrites.samplerWrites         = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	depthToMomentDescriptorWrites.storageImageWrites    = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	depthToMomentDescriptorWrites.writeSampledImage(0, m_shadowMapDepth.getHandle());
+	depthToMomentDescriptorWrites.writeSampler(1, m_shadowSampler);
+	depthToMomentDescriptorWrites.writeStorageImage(2, m_shadowMap.getHandle());
 	corePtr->writeDescriptorSet(m_depthToMomentsDescriptorSet, depthToMomentDescriptorWrites);
 
 	// shadow blur X
@@ -207,9 +207,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
 	m_shadowBlurXPipe                       = corePtr->createComputePipeline({ shadowBlurXShader, { m_shadowBlurXDescriptorSetLayout }});
 
 	vkcv::DescriptorWrites shadowBlurXDescriptorWrites;
-	shadowBlurXDescriptorWrites.sampledImageWrites   = { vkcv::SampledImageDescriptorWrite(0, m_shadowMap.getHandle()) };
-	shadowBlurXDescriptorWrites.samplerWrites        = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	shadowBlurXDescriptorWrites.storageImageWrites   = { vkcv::StorageImageDescriptorWrite(2, m_shadowMapIntermediate.getHandle()) };
+	shadowBlurXDescriptorWrites.writeSampledImage(0, m_shadowMap.getHandle());
+	shadowBlurXDescriptorWrites.writeSampler(1, m_shadowSampler);
+	shadowBlurXDescriptorWrites.writeStorageImage(2, m_shadowMapIntermediate.getHandle());
 	corePtr->writeDescriptorSet(m_shadowBlurXDescriptorSet, shadowBlurXDescriptorWrites);
 
 	// shadow blur Y
@@ -219,9 +219,9 @@ ShadowMapping::ShadowMapping(vkcv::Core* corePtr, const vkcv::VertexLayout& vert
     m_shadowBlurYPipe                       = corePtr->createComputePipeline({ shadowBlurYShader, { m_shadowBlurYDescriptorSetLayout }});
 
     vkcv::DescriptorWrites shadowBlurYDescriptorWrites;
-	shadowBlurYDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, m_shadowMapIntermediate.getHandle()) };
-	shadowBlurYDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, m_shadowSampler) };
-	shadowBlurYDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, m_shadowMap.getHandle()) };
+	shadowBlurYDescriptorWrites.writeSampledImage(0, m_shadowMapIntermediate.getHandle());
+	shadowBlurYDescriptorWrites.writeSampler(1, m_shadowSampler);
+	shadowBlurYDescriptorWrites.writeStorageImage(2, m_shadowMap.getHandle());
 	corePtr->writeDescriptorSet(m_shadowBlurYDescriptorSet, shadowBlurYDescriptorWrites);
 }
 
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index faa03d38..60a3a1c8 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -117,14 +117,16 @@ Voxelization::Voxelization(
 	m_voxelizationPipe = m_corePtr->createGraphicsPipeline(voxelizationPipeConfig);
 
 	vkcv::DescriptorWrites voxelizationDescriptorWrites;
-	voxelizationDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	voxelizationDescriptorWrites.uniformBufferWrites = { 
-		vkcv::BufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(3, lightInfoBuffer)
-	};
-	voxelizationDescriptorWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(4, shadowMap) };
-	voxelizationDescriptorWrites.samplerWrites      = { vkcv::SamplerDescriptorWrite(5, shadowSampler) };
-	voxelizationDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(2, m_voxelImageIntermediate.getHandle()) };
+	voxelizationDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	voxelizationDescriptorWrites.writeUniformBuffer(
+			1, m_voxelInfoBuffer.getHandle()
+	).writeUniformBuffer(
+			3, lightInfoBuffer
+	);
+	
+	voxelizationDescriptorWrites.writeSampledImage(4, shadowMap);
+	voxelizationDescriptorWrites.writeSampler(5, shadowSampler);
+	voxelizationDescriptorWrites.writeStorageImage(2, m_voxelImageIntermediate.getHandle());
 	m_corePtr->writeDescriptorSet(m_voxelizationDescriptorSet, voxelizationDescriptorWrites);
 
 	vkcv::ShaderProgram voxelVisualisationShader = loadVoxelVisualisationShader();
@@ -180,7 +182,7 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites resetVoxelWrites;
-	resetVoxelWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
+	resetVoxelWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_voxelResetDescriptorSet, resetVoxelWrites);
 
 	// buffer to image
@@ -194,8 +196,8 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites bufferToImageDescriptorWrites;
-	bufferToImageDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	bufferToImageDescriptorWrites.storageImageWrites = { vkcv::StorageImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) };
+	bufferToImageDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	bufferToImageDescriptorWrites.writeStorageImage(1, m_voxelImageIntermediate.getHandle());
 	m_corePtr->writeDescriptorSet(m_bufferToImageDescriptorSet, bufferToImageDescriptorWrites);
 
 	// secondary bounce
@@ -209,11 +211,11 @@ Voxelization::Voxelization(
 	});
 
 	vkcv::DescriptorWrites secondaryBounceDescriptorWrites;
-	secondaryBounceDescriptorWrites.storageBufferWrites = { vkcv::BufferDescriptorWrite(0, m_voxelBuffer.getHandle()) };
-	secondaryBounceDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(1, m_voxelImageIntermediate.getHandle()) };
-	secondaryBounceDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(2, voxelSampler) };
-	secondaryBounceDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(3, m_voxelImage.getHandle()) };
-	secondaryBounceDescriptorWrites.uniformBufferWrites = { vkcv::BufferDescriptorWrite(4, m_voxelInfoBuffer.getHandle()) };
+	secondaryBounceDescriptorWrites.writeStorageBuffer(0, m_voxelBuffer.getHandle());
+	secondaryBounceDescriptorWrites.writeSampledImage(1, m_voxelImageIntermediate.getHandle());
+	secondaryBounceDescriptorWrites.writeSampler(2, voxelSampler);
+	secondaryBounceDescriptorWrites.writeStorageImage(3, m_voxelImage.getHandle());
+	secondaryBounceDescriptorWrites.writeUniformBuffer(4, m_voxelInfoBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_secondaryBounceDescriptorSet, secondaryBounceDescriptorWrites);
 }
 
@@ -345,10 +347,8 @@ void Voxelization::renderVoxelVisualisation(
 
 	// write descriptor set
 	vkcv::DescriptorWrites voxelVisualisationDescriptorWrite;
-	voxelVisualisationDescriptorWrite.storageImageWrites =
-	{ vkcv::StorageImageDescriptorWrite(0, m_voxelImage.getHandle(), mipLevel) };
-	voxelVisualisationDescriptorWrite.uniformBufferWrites =
-	{ vkcv::BufferDescriptorWrite(1, m_voxelInfoBuffer.getHandle()) };
+	voxelVisualisationDescriptorWrite.writeStorageImage(0, m_voxelImage.getHandle(), mipLevel);
+	voxelVisualisationDescriptorWrite.writeUniformBuffer(1, m_voxelInfoBuffer.getHandle());
 	m_corePtr->writeDescriptorSet(m_visualisationDescriptorSet, voxelVisualisationDescriptorWrite);
 
 	uint32_t drawVoxelCount = voxelCount / exp2(mipLevel);
diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp
index f01b87a7..6bafbbd4 100644
--- a/projects/voxelization/src/main.cpp
+++ b/projects/voxelization/src/main.cpp
@@ -288,14 +288,15 @@ int main(int argc, const char** argv) {
 		const vkcv::ImageHandle specularHandle = sceneImages.back().getHandle();
 
 		vkcv::DescriptorWrites setWrites;
-		setWrites.sampledImageWrites = {
-			vkcv::SampledImageDescriptorWrite(0, albedoHandle),
-			vkcv::SampledImageDescriptorWrite(2, normalHandle),
-			vkcv::SampledImageDescriptorWrite(3, specularHandle)
-		};
-		setWrites.samplerWrites = {
-			vkcv::SamplerDescriptorWrite(1, colorSampler),
-		};
+		setWrites.writeSampledImage(
+				0, albedoHandle
+		).writeSampledImage(
+				2, normalHandle
+		).writeSampledImage(
+				3, specularHandle
+		);
+		
+		setWrites.writeSampler(1, colorSampler);
 		core.writeDescriptorSet(materialDescriptorSets.back(), setWrites);
 	}
 
@@ -570,17 +571,28 @@ int main(int argc, const char** argv) {
 
 	// write forward pass descriptor set
 	vkcv::DescriptorWrites forwardDescriptorWrites;
-	forwardDescriptorWrites.uniformBufferWrites = {
-		vkcv::BufferDescriptorWrite(0, shadowMapping.getLightInfoBuffer()),
-		vkcv::BufferDescriptorWrite(3, cameraPosBuffer.getHandle()),
-		vkcv::BufferDescriptorWrite(6, voxelization.getVoxelInfoBufferHandle()),
-		vkcv::BufferDescriptorWrite(7, volumetricSettingsBuffer.getHandle())};
-	forwardDescriptorWrites.sampledImageWrites = {
-		vkcv::SampledImageDescriptorWrite(1, shadowMapping.getShadowMap()),
-		vkcv::SampledImageDescriptorWrite(4, voxelization.getVoxelImageHandle()) };
-	forwardDescriptorWrites.samplerWrites = { 
-		vkcv::SamplerDescriptorWrite(2, shadowMapping.getShadowSampler()),
-		vkcv::SamplerDescriptorWrite(5, voxelSampler) };
+	forwardDescriptorWrites.writeUniformBuffer(
+			0, shadowMapping.getLightInfoBuffer()
+	).writeUniformBuffer(
+			3, cameraPosBuffer.getHandle()
+	).writeUniformBuffer(
+			6, voxelization.getVoxelInfoBufferHandle()
+	).writeUniformBuffer(
+			7, volumetricSettingsBuffer.getHandle()
+	);
+	
+	forwardDescriptorWrites.writeSampledImage(
+			1, shadowMapping.getShadowMap()
+	).writeSampledImage(
+			4, voxelization.getVoxelImageHandle()
+	);
+	
+	forwardDescriptorWrites.writeSampler(
+			2, shadowMapping.getShadowSampler()
+	).writeSampler(
+			5, voxelSampler
+	);
+	
 	core.writeDescriptorSet(forwardShadingDescriptorSet, forwardDescriptorWrites);
 
 	vkcv::upscaling::FSRUpscaling upscaling (core);
@@ -661,9 +673,7 @@ int main(int argc, const char** argv) {
 			
 			for (size_t i = 0; i < scene.materials.size(); i++) {
 				vkcv::DescriptorWrites setWrites;
-				setWrites.samplerWrites = {
-						vkcv::SamplerDescriptorWrite(1, colorSampler),
-				};
+				setWrites.writeSampler(1, colorSampler);
 				core.writeDescriptorSet(materialDescriptorSets[i], setWrites);
 			}
 			
@@ -709,25 +719,25 @@ int main(int argc, const char** argv) {
 
 		// update descriptor sets which use swapchain image
 		vkcv::DescriptorWrites tonemappingDescriptorWrites;
-		tonemappingDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, resolvedColorBuffer) };
-		tonemappingDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, colorSampler) };
-		tonemappingDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, swapBuffer) };
+		tonemappingDescriptorWrites.writeSampledImage(0, resolvedColorBuffer);
+		tonemappingDescriptorWrites.writeSampler(1, colorSampler);
+		tonemappingDescriptorWrites.writeStorageImage(2, swapBuffer);
 
 		core.writeDescriptorSet(tonemappingDescriptorSet, tonemappingDescriptorWrites);
 		
 		// update descriptor sets which use swapchain image
 		vkcv::DescriptorWrites postEffectsDescriptorWrites;
-		postEffectsDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, swapBuffer2) };
-		postEffectsDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, colorSampler) };
-		postEffectsDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, swapchainInput) };
+		postEffectsDescriptorWrites.writeSampledImage(0, swapBuffer2);
+		postEffectsDescriptorWrites.writeSampler(1, colorSampler);
+		postEffectsDescriptorWrites.writeStorageImage(2, swapchainInput);
 		
 		core.writeDescriptorSet(postEffectsDescriptorSet, postEffectsDescriptorWrites);
 
 		// update resolve descriptor, color images could be changed
 		vkcv::DescriptorWrites resolveDescriptorWrites;
-		resolveDescriptorWrites.sampledImageWrites  = { vkcv::SampledImageDescriptorWrite(0, colorBuffer) };
-		resolveDescriptorWrites.samplerWrites       = { vkcv::SamplerDescriptorWrite(1, resolveSampler) };
-		resolveDescriptorWrites.storageImageWrites  = { vkcv::StorageImageDescriptorWrite(2, resolvedColorBuffer) };
+		resolveDescriptorWrites.writeSampledImage(0, colorBuffer);
+		resolveDescriptorWrites.writeSampler(1, resolveSampler);
+		resolveDescriptorWrites.writeStorageImage(2, resolvedColorBuffer);
 		core.writeDescriptorSet(resolveDescriptorSet, resolveDescriptorWrites);
 
 		start = end;
diff --git a/projects/wobble_bobble/src/main.cpp b/projects/wobble_bobble/src/main.cpp
index 96c367f2..989e6cff 100644
--- a/projects/wobble_bobble/src/main.cpp
+++ b/projects/wobble_bobble/src/main.cpp
@@ -369,14 +369,14 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(initParticleWeightsSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
 		core.writeDescriptorSet(initParticleWeightsSets[1], writes);
 	}
 	
@@ -389,19 +389,19 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(transformParticlesToGridSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle()));
+		writes.writeUniformBuffer(0, simulation.getHandle());
 		core.writeDescriptorSet(transformParticlesToGridSets[1], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageImageWrites.push_back(vkcv::StorageImageDescriptorWrite(0, grid.getHandle()));
+		writes.writeStorageImage(0, grid.getHandle());
 		core.writeDescriptorSet(transformParticlesToGridSets[2], writes);
 	}
 	
@@ -414,20 +414,20 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(updateParticleVelocitiesSets[0], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, simulation.getHandle()));
+		writes.writeUniformBuffer(0, simulation.getHandle());
 		core.writeDescriptorSet(updateParticleVelocitiesSets[1], writes);
 	}
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
 		core.writeDescriptorSet(updateParticleVelocitiesSets[2], writes);
 	}
 	
@@ -499,9 +499,9 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.sampledImageWrites.push_back(vkcv::SampledImageDescriptorWrite(0, grid.getHandle()));
-		writes.samplerWrites.push_back(vkcv::SamplerDescriptorWrite(1, gridSampler));
-		writes.uniformBufferWrites.push_back(vkcv::BufferDescriptorWrite(2, simulation.getHandle()));
+		writes.writeSampledImage(0, grid.getHandle());
+		writes.writeSampler(1, gridSampler);
+		writes.writeUniformBuffer(2, simulation.getHandle());
 		core.writeDescriptorSet(gfxSetGrid, writes);
 	}
 	
@@ -513,7 +513,7 @@ int main(int argc, const char **argv) {
 	
 	{
 		vkcv::DescriptorWrites writes;
-		writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+		writes.writeStorageBuffer(0, particlesHandle);
 		core.writeDescriptorSet(gfxSetParticles, writes);
 	}
 	
@@ -883,7 +883,7 @@ int main(int argc, const char **argv) {
 			);
 			
 			vkcv::DescriptorWrites writes;
-			writes.storageBufferWrites.push_back(vkcv::BufferDescriptorWrite(0, particlesHandle));
+			writes.writeStorageBuffer(0, particlesHandle);
 			
 			core.writeDescriptorSet(initParticleWeightsSets[0], writes);
 			core.writeDescriptorSet(transformParticlesToGridSets[0], writes);
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index c04ddb47..526bea60 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -176,7 +176,7 @@ namespace vkcv
 		
 		std::vector<WriteDescriptorSetInfo> writeInfos;
 
-		for (const auto& write : writes.sampledImageWrites)
+		for (const auto& write : writes.getSampledImageWrites())
 		{
 		    vk::ImageLayout layout = write.useGeneralLayout ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;
 			const vk::DescriptorImageInfo imageInfo(
@@ -198,7 +198,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.storageImageWrites) {
+		for (const auto& write : writes.getStorageImageWrites()) {
 			const vk::DescriptorImageInfo imageInfo(
 				nullptr,
 				imageManager.getVulkanImageView(write.image, write.mipLevel),
@@ -218,7 +218,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.uniformBufferWrites) {
+		for (const auto& write : writes.getUniformBufferWrites()) {
 			const size_t size = bufferManager.getBufferSize(write.buffer);
 			const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size);
 			
@@ -245,7 +245,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.storageBufferWrites) {
+		for (const auto& write : writes.getStorageBufferWrites()) {
 			const size_t size = bufferManager.getBufferSize(write.buffer);
 			const uint32_t offset = std::clamp<uint32_t>(write.offset, 0, size);
 			
@@ -272,7 +272,7 @@ namespace vkcv
 			writeInfos.push_back(vulkanWrite);
 		}
 
-		for (const auto& write : writes.samplerWrites) {
+		for (const auto& write : writes.getSamplerWrites()) {
 			const vk::Sampler& sampler = samplerManager.getVulkanSampler(write.sampler);
 			
 			const vk::DescriptorImageInfo imageInfo(
diff --git a/src/vkcv/DescriptorWrites.cpp b/src/vkcv/DescriptorWrites.cpp
new file mode 100644
index 00000000..2dbf1b25
--- /dev/null
+++ b/src/vkcv/DescriptorWrites.cpp
@@ -0,0 +1,75 @@
+
+#include "vkcv/DescriptorWrites.hpp"
+
+namespace vkcv {
+	
+	DescriptorWrites &DescriptorWrites::writeSampledImage(uint32_t binding,
+														  ImageHandle image,
+														  uint32_t mipLevel,
+														  bool useGeneralLayout,
+														  uint32_t arrayIndex) {
+		m_sampledImageWrites.emplace_back(binding, image, mipLevel, useGeneralLayout, arrayIndex);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeStorageImage(uint32_t binding,
+														  ImageHandle image,
+														  uint32_t mipLevel) {
+		m_storageImageWrites.emplace_back(binding, image, mipLevel);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeUniformBuffer(uint32_t binding,
+														   BufferHandle buffer,
+														   bool dynamic,
+														   uint32_t offset,
+														   uint32_t size) {
+		m_uniformBufferWrites.emplace_back(binding, buffer, dynamic, offset, size);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeStorageBuffer(uint32_t binding,
+														   BufferHandle buffer,
+														   bool dynamic,
+														   uint32_t offset,
+														   uint32_t size) {
+		m_storageBufferWrites.emplace_back(binding, buffer, dynamic, offset, size);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeSampler(uint32_t binding,
+													 SamplerHandle sampler) {
+		m_samplerWrites.emplace_back(binding, sampler);
+		return *this;
+	}
+	
+	DescriptorWrites &DescriptorWrites::writeAcceleration(uint32_t binding) {
+		m_accelerationWrites.emplace_back(binding);
+		return *this;
+	}
+	
+	const std::vector<SampledImageDescriptorWrite> &DescriptorWrites::getSampledImageWrites() const {
+		return m_sampledImageWrites;
+	}
+	
+	const std::vector<StorageImageDescriptorWrite> &DescriptorWrites::getStorageImageWrites() const {
+		return m_storageImageWrites;
+	}
+	
+	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getUniformBufferWrites() const {
+		return m_uniformBufferWrites;
+	}
+	
+	const std::vector<BufferDescriptorWrite> &DescriptorWrites::getStorageBufferWrites() const {
+		return m_storageBufferWrites;
+	}
+	
+	const std::vector<SamplerDescriptorWrite> &DescriptorWrites::getSamplerWrites() const {
+		return m_samplerWrites;
+	}
+	
+	const std::vector<AccelerationDescriptorWrite> &DescriptorWrites::getAccelerationWrites() const {
+		return m_accelerationWrites;
+	}
+	
+}
-- 
GitLab