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