From fbbe502188beafaf104f013f430985b70bee77f2 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Fri, 4 Jun 2021 22:22:42 +0200
Subject: [PATCH] [#66] Cleaned up descriptor set usage

---
 include/vkcv/Core.hpp                |  22 +++---
 include/vkcv/DescriptorConfig.hpp    |  28 ++++----
 include/vkcv/Handles.hpp             |   2 +-
 projects/cmd_sync_test/src/main.cpp  |  20 ++----
 projects/first_mesh/src/main.cpp     |   6 +-
 projects/first_triangle/src/main.cpp |   2 +-
 src/vkcv/Core.cpp                    |  35 ++++-----
 src/vkcv/DescriptorConfig.cpp        |  25 +++----
 src/vkcv/DescriptorManager.cpp       | 103 ++++++++++++---------------
 src/vkcv/DescriptorManager.hpp       |  34 ++-------
 10 files changed, 118 insertions(+), 159 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index c11cdf32..e7d09881 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -25,6 +25,7 @@
 
 namespace vkcv
 {
+
 	struct VertexBufferBinding {
 		vk::DeviceSize	offset;
 		BufferHandle	buffer;
@@ -215,10 +216,10 @@ namespace vkcv
          *   @return
          */
         [[nodiscard]]
-        ResourcesHandle createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets);
-		void writeResourceDescription(ResourcesHandle handle, size_t setIndex, const DescriptorWrites& writes);
+        DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &bindings);
+		void writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites& writes);
 
-		vk::DescriptorSetLayout getDescriptorSetLayout(ResourcesHandle handle, size_t setIndex);
+		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
 		/**
 		 * @brief start recording command buffers and increment frame index
@@ -229,14 +230,13 @@ namespace vkcv
 		 * @brief render a beautiful triangle
 		*/
 		void renderMesh(
-			const PassHandle						renderpassHandle, 
-			const PipelineHandle					pipelineHandle,
-			const size_t							pushConstantSize, 
-			const void*								pushConstantData, 
-			const Mesh								&mesh,
-			const vkcv::ResourcesHandle				resourceHandle,
-			const size_t							resourceDescriptorSetIndex,
-			const std::vector<ImageHandle>			&renderTargets);
+			const PassHandle                        renderpassHandle, 
+			const PipelineHandle                    pipelineHandle,
+			const size_t                            pushConstantSize, 
+			const void*                             pushConstantData, 
+			const Mesh                              &mesh,
+			const std::vector<DescriptorSetUsage>   &descriptorSets,
+			const std::vector<ImageHandle>	        &renderTargets);
 
 		/**
 		 * @brief end recording and present image
diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp
index 161273db..15083e8c 100644
--- a/include/vkcv/DescriptorConfig.hpp
+++ b/include/vkcv/DescriptorConfig.hpp
@@ -1,8 +1,23 @@
 #pragma once
 #include <vkcv/ShaderProgram.hpp>
+#include <vkcv/Handles.hpp>
+#include <vulkan/vulkan.hpp>
 
 namespace vkcv
 {
+    struct DescriptorSet
+    {
+        vk::DescriptorSet       vulkanHandle;
+        vk::DescriptorSetLayout layout;
+    };
+
+    struct DescriptorSetUsage {
+        DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle handle) noexcept;
+
+        const uint32_t              setLocation;
+        const DescriptorSetHandle   handle;
+    };
+
     /*
     * All the types of descriptors (resources) that can be retrieved by the shaders
     */
@@ -24,7 +39,6 @@ namespace vkcv
     */
     struct DescriptorBinding
     {
-        DescriptorBinding() = delete;
         DescriptorBinding(
             DescriptorType descriptorType,
             uint32_t descriptorCount,
@@ -35,16 +49,4 @@ namespace vkcv
         uint32_t descriptorCount;
         ShaderStage shaderStage;
     };
-
-    /*
-    * One descriptor set struct that contains all the necessary information for the actual creation.
-    * @param[in] a number of bindings that were created beforehand
-    * @param[in] the number of (identical) sets that should be created from the attached bindings
-    */
-    struct DescriptorSetConfig
-    {
-        explicit DescriptorSetConfig(std::vector<DescriptorBinding> bindings) noexcept;
-
-        std::vector<DescriptorBinding> bindings;
-    };
 }
diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp
index bd806308..f2a0da0a 100644
--- a/include/vkcv/Handles.hpp
+++ b/include/vkcv/Handles.hpp
@@ -79,7 +79,7 @@ namespace vkcv
 		using Handle::Handle;
 	};
 	
-	class ResourcesHandle : public Handle {
+	class DescriptorSetHandle : public Handle {
 		friend class DescriptorManager;
 	private:
 		using Handle::Handle;
diff --git a/projects/cmd_sync_test/src/main.cpp b/projects/cmd_sync_test/src/main.cpp
index 64c08943..01eec2fc 100644
--- a/projects/cmd_sync_test/src/main.cpp
+++ b/projects/cmd_sync_test/src/main.cpp
@@ -108,17 +108,10 @@ int main(int argc, const char** argv) {
 		return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type);
 	});
 
-	vkcv::DescriptorSetConfig setConfig({
+	std::vector<vkcv::DescriptorBinding> descriptorBindings = {
 		vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED,	1, vkcv::ShaderStage::FRAGMENT),
-		vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER,			1, vkcv::ShaderStage::FRAGMENT)
-	});
-	vkcv::ResourcesHandle set = core.createResourceDescription({ setConfig });
-
-	//only exemplary code for testing
-	for (int i = 0; i < 1001; i++) {
-		vkcv::ResourcesHandle furtherSets = core.createResourceDescription({ setConfig });
-	}
-	//end of exemplary code
+		vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER,			1, vkcv::ShaderStage::FRAGMENT)};
+	vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
 
 	const vkcv::PipelineConfig trianglePipelineDefinition(
 		triangleShaderProgram, 
@@ -126,7 +119,7 @@ int main(int argc, const char** argv) {
 		windowHeight,
 		trianglePass,
 		mesh.vertexGroups[0].vertexBuffer.attributes,
-		{ core.getDescriptorSetLayout(set, 0) },
+		{ core.getDescriptorSet(descriptorSet).layout },
 		true);
 	vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
 	
@@ -148,7 +141,7 @@ int main(int argc, const char** argv) {
 	vkcv::DescriptorWrites setWrites;
 	setWrites.sampledImageWrites	= { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
 	setWrites.samplerWrites			= { vkcv::SamplerDescriptorWrite(1, sampler) };
-	core.writeResourceDescription(set, 0, setWrites);
+	core.writeResourceDescription(descriptorSet, 0, setWrites);
 
 	vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle();
 
@@ -174,8 +167,7 @@ int main(int argc, const char** argv) {
 			sizeof(mvp),
 			&mvp,
 			boxMesh,
-			set,
-			0,
+			{ vkcv::DescriptorSetUsage(0, descriptorSet) },
 			{ swapchainInput, depthBuffer });
 
 		core.endFrame();
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index 44cb9c74..bc832b91 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -104,11 +104,11 @@ int main(int argc, const char** argv) {
 		vkcv::DescriptorBinding(vkcv::DescriptorType::IMAGE_SAMPLED,	1, vkcv::ShaderStage::FRAGMENT),
 		vkcv::DescriptorBinding(vkcv::DescriptorType::SAMPLER,			1, vkcv::ShaderStage::FRAGMENT)
 	});
-	vkcv::ResourcesHandle set = core.createResourceDescription({ setConfig });
+	vkcv::DescriptorSetHandle set = core.createDescriptorSet({ setConfig });
 
 	//only exemplary code for testing
 	for (int i = 0; i < 1001; i++) {
-		vkcv::ResourcesHandle furtherSets = core.createResourceDescription({ setConfig });
+		vkcv::DescriptorSetHandle furtherSets = core.createDescriptorSet({ setConfig });
 	}
 	//end of exemplary code
 
@@ -118,7 +118,7 @@ int main(int argc, const char** argv) {
         UINT32_MAX,
 		trianglePass,
 		mesh.vertexGroups[0].vertexBuffer.attributes,
-		{ core.getDescriptorSetLayout(set, 0) },
+		{ core.getDescriptorSet(set, 0) },
 		true);
 	vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
 	
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 41a35c78..24aaa9ef 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -155,7 +155,7 @@ int main(int argc, const char** argv) {
 			vertexBufferBindings,
 			triangleIndexBuffer.getHandle(),
 			3,
-			vkcv::ResourcesHandle(),
+			vkcv::DescriptorSetHandle(),
 			0,
 			{swapchainImageHandle});
 	    
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index d72f87d6..472f3766 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -142,14 +142,13 @@ namespace vkcv
 	}
 
 	void Core::renderMesh(
-		const PassHandle				renderpassHandle, 
-		const PipelineHandle			pipelineHandle, 
-		const size_t					pushConstantSize, 
-		const void						*pushConstantData,
-		const Mesh						&mesh,
-		const vkcv::ResourcesHandle		resourceHandle,
-		const size_t					resourceDescriptorSetIndex,
-		const std::vector<ImageHandle>&	renderTargets) {
+		const PassHandle                        renderpassHandle, 
+		const PipelineHandle                    pipelineHandle, 
+		const size_t                            pushConstantSize, 
+		const void                              *pushConstantData,
+		const Mesh                              &mesh,
+        const std::vector<DescriptorSetUsage>   &descriptorSets,
+		const std::vector<ImageHandle>          &renderTargets) {
 
 		if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) {
 			return;
@@ -262,9 +261,13 @@ namespace vkcv
                 cmdBuffer.bindVertexBuffers(i, (vertexBuffer), (vertexBinding.offset));
             }
 
-            if (resourceHandle) {
-                const vk::DescriptorSet descriptorSet = m_DescriptorManager->getDescriptorSet(resourceHandle, resourceDescriptorSetIndex);
-                cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, descriptorSet, nullptr);
+            for (const auto &descriptorUsage : descriptorSets) {
+                cmdBuffer.bindDescriptorSets(
+                    vk::PipelineBindPoint::eGraphics, 
+                    pipelineLayout, 
+                    descriptorUsage.setLocation, 
+                    m_DescriptorManager->getDescriptorSet(descriptorUsage.handle).vulkanHandle,
+                    nullptr);
             }
 
             const vk::Buffer indexBuffer = m_BufferManager->getBuffer(mesh.indexBuffer);
@@ -346,12 +349,12 @@ namespace vkcv
     	return Image::create(m_ImageManager.get(), format, width, height, depth);
 	}
 
-    ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets)
+    DescriptorSetHandle Core::createDescriptorSet(const std::vector<DescriptorBinding>& bindings)
     {
-        return m_DescriptorManager->createResourceDescription(descriptorSets);
+        return m_DescriptorManager->createDescriptorSet(bindings);
     }
 
-	void Core::writeResourceDescription(ResourcesHandle handle, size_t setIndex, const DescriptorWrites &writes) {
+	void Core::writeResourceDescription(DescriptorSetHandle handle, size_t setIndex, const DescriptorWrites &writes) {
 		m_DescriptorManager->writeResourceDescription(
 			handle, 
 			setIndex, 
@@ -361,8 +364,8 @@ namespace vkcv
 			*m_SamplerManager);
 	}
 
-	vk::DescriptorSetLayout Core::getDescriptorSetLayout(ResourcesHandle handle, size_t setIndex) {
-		return m_DescriptorManager->getDescriptorSetLayout(handle, setIndex);
+	DescriptorSet Core::getDescriptorSet(const DescriptorSetHandle handle) const {
+		return m_DescriptorManager->getDescriptorSet(handle);
 	}
 
     std::vector<vk::ImageView> Core::createImageViews( Context &context, SwapChain& swapChain){
diff --git a/src/vkcv/DescriptorConfig.cpp b/src/vkcv/DescriptorConfig.cpp
index c4f6e326..122d29fe 100644
--- a/src/vkcv/DescriptorConfig.cpp
+++ b/src/vkcv/DescriptorConfig.cpp
@@ -1,20 +1,17 @@
 #include "vkcv/DescriptorConfig.hpp"
 
-#include <utility>
-
 namespace vkcv {
 
-    DescriptorBinding::DescriptorBinding(
-        DescriptorType descriptorType,
-        uint32_t descriptorCount,
-        ShaderStage shaderStage
-    ) noexcept :
-        descriptorType{descriptorType},
-        descriptorCount{descriptorCount},
-        shaderStage{shaderStage}
-    {};
+    DescriptorSetUsage::DescriptorSetUsage(uint32_t setLocation, DescriptorSetHandle handle) noexcept 
+    : setLocation(setLocation), handle(handle) {}
 
-    DescriptorSetConfig::DescriptorSetConfig(std::vector<DescriptorBinding> bindings) noexcept :
-        bindings{std::move(bindings)}
-    {};
+	DescriptorBinding::DescriptorBinding(
+		DescriptorType descriptorType,
+		uint32_t descriptorCount,
+		ShaderStage shaderStage) noexcept
+		:
+		descriptorType(descriptorType),
+		descriptorCount(descriptorCount),
+		shaderStage(shaderStage) {}
+	
 }
diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp
index 2ecb23bd..a2efecbe 100644
--- a/src/vkcv/DescriptorManager.cpp
+++ b/src/vkcv/DescriptorManager.cpp
@@ -2,11 +2,6 @@
 
 namespace vkcv
 {
-    DescriptorManager::ResourceDescription::ResourceDescription(std::vector<vk::DescriptorSet> sets,
-                                                                std::vector<vk::DescriptorSetLayout> layouts) noexcept :
-    descriptorSets{std::move(sets)},
-    descriptorSetLayouts{std::move(layouts)}
-    {}
     DescriptorManager::DescriptorManager(vk::Device device) noexcept:
         m_Device{ device }
     {
@@ -29,67 +24,63 @@ namespace vkcv
 
     DescriptorManager::~DescriptorManager() noexcept
     {
-        for (uint64_t id = 0; id < m_ResourceDescriptions.size(); id++) {
-			destroyResourceDescriptionById(id);
+        for (uint64_t id = 0; id < m_DescriptorSets.size(); id++) {
+			destroyDescriptorSetById(id);
         }
+		m_DescriptorSets.clear();
 		for (const auto &pool : m_Pools) {
 			m_Device.destroy(pool);
 		}
     }
 
-    ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSetConfig> &descriptorSets)
+    DescriptorSetHandle DescriptorManager::createDescriptorSet(const std::vector<DescriptorBinding>& bindings)
     {
-        std::vector<vk::DescriptorSet> vk_sets;
-        std::vector<vk::DescriptorSetLayout> vk_setLayouts;
+        std::vector<vk::DescriptorSetLayoutBinding> setBindings = {};
 
-        for (const auto &set : descriptorSets) {
-            std::vector<vk::DescriptorSetLayoutBinding> setBindings = {};
+        //create each set's binding
+        for (uint32_t i = 0; i < bindings.size(); i++) {
+            vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(
+                i,
+                convertDescriptorTypeFlag(bindings[i].descriptorType),
+                bindings[i].descriptorCount,
+                convertShaderStageFlag(bindings[i].shaderStage));
+            setBindings.push_back(descriptorSetLayoutBinding);
+        }
 
-            //create each set's binding
-            for (uint32_t j = 0; j < set.bindings.size(); j++) {
-                vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(
-                        j,
-                        convertDescriptorTypeFlag(set.bindings[j].descriptorType),
-                        set.bindings[j].descriptorCount,
-                        convertShaderStageFlag(set.bindings[j].shaderStage));
-                setBindings.push_back(descriptorSetLayoutBinding);
-            }
+        DescriptorSet set;
 
-            //create the descriptor set's layout from the bindings gathered above
-            vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings);
-            vk::DescriptorSetLayout layout = nullptr;
-            if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &layout) != vk::Result::eSuccess)
-            {
-                std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl;
-                return ResourcesHandle();
-            };
-            vk_setLayouts.push_back(layout);
-        }
-        //create and allocate the set(s) based on the layouts that have been gathered above
-        vk_sets.resize(vk_setLayouts.size());
-        vk::DescriptorSetAllocateInfo allocInfo(m_Pools.back(), vk_sets.size(), vk_setLayouts.data());
-        auto result = m_Device.allocateDescriptorSets(&allocInfo, vk_sets.data());
+        //create the descriptor set's layout from the bindings gathered above
+        vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings);
+        if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &set.layout) != vk::Result::eSuccess)
+        {
+            std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl;
+            return DescriptorSetHandle();
+        };
+        
+        //create and allocate the set based on the layout that have been gathered above
+        vk::DescriptorSetAllocateInfo allocInfo(m_Pools.back(), 1, &set.layout);
+        auto result = m_Device.allocateDescriptorSets(&allocInfo, &set.vulkanHandle);
         if(result != vk::Result::eSuccess)
         {
 			//create a new descriptor pool if the previous one ran out of memory
 			if (result == vk::Result::eErrorOutOfPoolMemory) {
 				allocateDescriptorPool();
 				allocInfo.setDescriptorPool(m_Pools.back());
-				result = m_Device.allocateDescriptorSets(&allocInfo, vk_sets.data());
+				result = m_Device.allocateDescriptorSets(&allocInfo, &set.vulkanHandle);
 			}
 			if (result != vk::Result::eSuccess) {
 				std::cout << "FAILED TO ALLOCATE DESCRIPTOR SET" << std::endl;
 				std::cout << vk::to_string(result) << std::endl;
-				for (const auto& layout : vk_setLayouts)
-					m_Device.destroy(layout);
+				m_Device.destroy(set.layout);
 
-				return ResourcesHandle();
+				return DescriptorSetHandle();
 			}
         };
 
-        const uint64_t id = m_ResourceDescriptions.size();
-        m_ResourceDescriptions.emplace_back(vk_sets, vk_setLayouts);
-        return ResourcesHandle(id, [&](uint64_t id) { destroyResourceDescriptionById(id); });
+        const uint64_t id = m_DescriptorSets.size();
+
+        m_DescriptorSets.push_back(set);
+        return DescriptorSetHandle(id, [&](uint64_t id) { destroyDescriptorSetById(id); });
     }
     
     struct WriteDescriptorSetInfo {
@@ -100,14 +91,14 @@ namespace vkcv
     };
 
 	void DescriptorManager::writeResourceDescription(
-		const ResourcesHandle	&handle,
+		const DescriptorSetHandle	&handle,
 		size_t					setIndex,
 		const DescriptorWrites	&writes,
 		const ImageManager		&imageManager, 
 		const BufferManager		&bufferManager,
 		const SamplerManager	&samplerManager) {
 
-		vk::DescriptorSet set = m_ResourceDescriptions[handle.getId()].descriptorSets[setIndex];
+		vk::DescriptorSet set = m_DescriptorSets[handle.getId()].vulkanHandle;
 
 		std::vector<vk::DescriptorImageInfo> imageInfos;
 		std::vector<vk::DescriptorBufferInfo> bufferInfos;
@@ -230,12 +221,8 @@ namespace vkcv
 		m_Device.updateDescriptorSets(vulkanWrites, nullptr);
 	}
 
-	vk::DescriptorSet DescriptorManager::getDescriptorSet(const ResourcesHandle &handle, size_t index) const {
-		return m_ResourceDescriptions[handle.getId()].descriptorSets[index];
-	}
-
-	vk::DescriptorSetLayout DescriptorManager::getDescriptorSetLayout(const ResourcesHandle &handle, size_t index) const {
-		return m_ResourceDescriptions[handle.getId()].descriptorSetLayouts[index];
+	DescriptorSet DescriptorManager::getDescriptorSet(const DescriptorSetHandle handle) const {
+		return m_DescriptorSets[handle.getId()];
 	}
 
     vk::DescriptorType DescriptorManager::convertDescriptorTypeFlag(DescriptorType type) {
@@ -277,18 +264,18 @@ namespace vkcv
         }
     }
     
-    void DescriptorManager::destroyResourceDescriptionById(uint64_t id) {
-		if (id >= m_ResourceDescriptions.size()) {
+    void DescriptorManager::destroyDescriptorSetById(uint64_t id) {
+		if (id >= m_DescriptorSets.size()) {
+			std::cerr << "Error: DescriptorManager::destroyResourceDescriptionById invalid id" << std::endl;
 			return;
 		}
 		
-		auto& resourceDescription = m_ResourceDescriptions[id];
-	
-		for(const auto &layout : resourceDescription.descriptorSetLayouts) {
-			m_Device.destroyDescriptorSetLayout(layout);
+		auto& set = m_DescriptorSets[id];
+		if (set.layout) {
+			m_Device.destroyDescriptorSetLayout(set.layout);
+			set.layout = nullptr;
 		}
-	
-		resourceDescription.descriptorSetLayouts.clear();
+		// FIXME: descriptor set itself not destroyed
 	}
 
 	vk::DescriptorPool DescriptorManager::allocateDescriptorPool() {
diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp
index 22042c70..d8607b93 100644
--- a/src/vkcv/DescriptorManager.hpp
+++ b/src/vkcv/DescriptorManager.hpp
@@ -21,17 +21,10 @@ namespace vkcv
 	    explicit DescriptorManager(vk::Device device) noexcept;
 	    ~DescriptorManager() noexcept;
 
-		/**
-		* Creates all vk::DescriptorSets and allocates them from the pool. 
-		* DescriptorSets are put inside a ResourceDescription struct. 
-		* Structs are then put into m_ResourceDescriptions.
-		* @param[in] vector of filled vkcv::DescriptorSet structs
-		* @return index into that objects a resource handle
-		*/
-        ResourcesHandle createResourceDescription(const std::vector<DescriptorSetConfig> & descriptorSets);
+        DescriptorSetHandle createDescriptorSet(const std::vector<DescriptorBinding> &descriptorBindings);
 
 		void writeResourceDescription(
-			const ResourcesHandle	&handle,
+			const DescriptorSetHandle	&handle,
 			size_t					setIndex,
 			const DescriptorWrites  &writes,
 			const ImageManager      &imageManager,
@@ -39,34 +32,19 @@ namespace vkcv
 			const SamplerManager    &samplerManager);
 
 		[[nodiscard]]
-		vk::DescriptorSet		getDescriptorSet(const ResourcesHandle &handle, size_t index) const;
-		[[nodiscard]]
-		vk::DescriptorSetLayout getDescriptorSetLayout(const ResourcesHandle &handle, size_t index) const;
+		DescriptorSet getDescriptorSet(const DescriptorSetHandle handle) const;
 
 	private:
-		vk::Device			m_Device;
+		vk::Device m_Device;
 		std::vector<vk::DescriptorPool>	m_Pools;
 		std::vector<vk::DescriptorPoolSize> m_PoolSizes;
 		vk::DescriptorPoolCreateInfo m_PoolInfo;
 
 
-		/**
-		* Container for all resources requested by the user in one call of createResourceDescription.
-		* Includes descriptor sets and the respective descriptor set layouts.
-		*/
-        struct ResourceDescription
-        {
-            ResourceDescription() = delete;
-            ResourceDescription(std::vector<vk::DescriptorSet> sets, std::vector<vk::DescriptorSetLayout> layouts) noexcept;
-
-            std::vector<vk::DescriptorSet> descriptorSets;
-            std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
-        };
-
 		/**
 		* Contains all the resource descriptions that were requested by the user in calls of createResourceDescription.
 		*/
-        std::vector<ResourceDescription> m_ResourceDescriptions;
+        std::vector<DescriptorSet> m_DescriptorSets;
 		
 		/**
 		* Converts the flags of the descriptor types from VulkanCV (vkcv) to Vulkan (vk).
@@ -85,7 +63,7 @@ namespace vkcv
 		* Destroys a specific resource description
 		* @param[in] the handle id of the respective resource description
 		*/
-		void destroyResourceDescriptionById(uint64_t id);
+		void destroyDescriptorSetById(uint64_t id);
 
 		/**
 		* creates a descriptor pool based on the poolSizes and poolInfo defined in the constructor
-- 
GitLab