diff --git a/config/Sources.cmake b/config/Sources.cmake index d20fa08abd63880f66fb998e5ef3b682db4c4825..cb73f57c2ca7278765ef0c8d01989c09a445c7b5 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -55,6 +55,7 @@ set(vkcv_sources ${vkcv_source}/vkcv/Framebuffer.cpp ${vkcv_include}/vkcv/Event.hpp + ${vkcv_source}/vkcv/DescriptorManager.hpp ${vkcv_source}/vkcv/DescriptorManager.cpp diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index ec1a239eb2ff37e7672bd6492083ff796e759746..e2fc5c587247a915f5bca345f8077f33ee5d8977 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -61,7 +61,9 @@ namespace vkcv std::unique_ptr<PassManager> m_PassManager; std::unique_ptr<PipelineManager> m_PipelineManager; + std::unique_ptr<DescriptorManager> m_DescriptorManager; std::unique_ptr<BufferManager> m_BufferManager; + CommandResources m_CommandResources; SyncResources m_SyncResources; uint32_t m_currentSwapchainImageIndex; @@ -173,6 +175,7 @@ namespace vkcv * @param setDescriptions * @return */ + [[nodiscard]] ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> &descriptorSets); /** diff --git a/include/vkcv/DescriptorConfig.hpp b/include/vkcv/DescriptorConfig.hpp index 60175a87b8d88578a9e4c7ce006fb47d4cffe9e0..8116259757fe623f97a2814991b226ee27efca50 100644 --- a/include/vkcv/DescriptorConfig.hpp +++ b/include/vkcv/DescriptorConfig.hpp @@ -9,6 +9,7 @@ namespace vkcv enum class DescriptorType { UNIFORM_BUFFER, + STORAGE_BUFFER, SAMPLER, IMAGE }; @@ -23,15 +24,12 @@ namespace vkcv struct DescriptorBinding { DescriptorBinding() = delete; - DescriptorBinding( - uint32_t p_bindingID, - DescriptorType p_descriptorType, - uint32_t p_descriptorCount, - ShaderStage p_shaderStage + DescriptorType descriptorType, + uint32_t descriptorCount, + ShaderStage shaderStage ) noexcept; - uint32_t bindingID; DescriptorType descriptorType; uint32_t descriptorCount; ShaderStage shaderStage; @@ -45,12 +43,8 @@ namespace vkcv struct DescriptorSet { DescriptorSet() = delete; - - DescriptorSet( - std::vector<DescriptorBinding> p_bindings, - uint32_t p_setCount) noexcept; + explicit DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept; std::vector<DescriptorBinding> bindings; - uint32_t setCount; }; } diff --git a/include/vkcv/DescriptorSet.hpp b/include/vkcv/DescriptorSet.hpp deleted file mode 100644 index 969f3558f7ec2842f26920c0a8c59be86f5d6fc2..0000000000000000000000000000000000000000 --- a/include/vkcv/DescriptorSet.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include <vulkan/vulkan.hpp> - -namespace vkcv { - - class DescriptorSet - { - - public: - DescriptorSet::DescriptorSet(); - void createDescriptorSets(vk::Device device); - private: - //std::vector<vk::DescriptorPoolSize> descriptorPoolSizes; - //std::vector<vk::DescriptorSetLayoutBinding> descriptorSetLayoutBinding; - //vk::DescriptorSetLayout descriptorSetLayout; - //vk::DescriptorPool descriptorPool; - }; -} \ No newline at end of file diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index e65818874992637dc6fb09667ffdd288318217e3..07da9506c5546985d4852e5d7d87ecbbcfe5e788 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -95,26 +95,23 @@ int main(int argc, const char** argv) { return EXIT_FAILURE; } -//---------CREATION OF RESOURCES/DESCRIPTORS------------------ //just an example - //creates 3 descriptor sets with one descriptor each + //creates 20 descriptor sets, each containing bindings for 50 uniform buffers, images, and samplers std::vector<vkcv::DescriptorSet> sets; - vkcv::DescriptorType typeA = vkcv::DescriptorType::UNIFORM_BUFFER; - vkcv::DescriptorType typeB = vkcv::DescriptorType::IMAGE; - vkcv::DescriptorType typeC = vkcv::DescriptorType::SAMPLER; - std::vector<vkcv::DescriptorType> types = { typeA, typeB, typeC }; - for (uint32_t i = 0; i < types.size(); i++) + + for (uint32_t i = 0; i < 20; i++) { - vkcv::DescriptorBinding bind(i, types[i], static_cast<uint32_t>(1), vkcv::ShaderStage::VERTEX); + vkcv::DescriptorBinding uniformBufBinding(vkcv::DescriptorType::UNIFORM_BUFFER, 50, vkcv::ShaderStage::VERTEX); + vkcv::DescriptorBinding storageBufBinding(vkcv::DescriptorType::STORAGE_BUFFER, 50, vkcv::ShaderStage::VERTEX); + vkcv::DescriptorBinding imageBinding(vkcv::DescriptorType::IMAGE, 50, vkcv::ShaderStage::VERTEX); + vkcv::DescriptorBinding samplerBinding(vkcv::DescriptorType::SAMPLER, 50, vkcv::ShaderStage::VERTEX); - std::vector<vkcv::DescriptorBinding> bindings = { bind }; - vkcv::DescriptorSet set(bindings, static_cast<uint32_t>(1)); + vkcv::DescriptorSet set({uniformBufBinding, storageBufBinding, imageBinding, samplerBinding}); sets.push_back(set); + auto resourceHandle = core.createResourceDescription(sets); + std::cout << "Resource " << resourceHandle.id << " created." << std::endl; } - core.createResourceDescription(sets); - -//------------END CREATION OF RESOURCES/DESCRIPTORS------------------ /* * BufferHandle triangleVertices = core.createBuffer(vertices); diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 01aea7c5625ef6f39b8000201dafd3ae88bd836c..fa53b4faa666134bde9230863f78c96e648c9037 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -93,6 +93,7 @@ namespace vkcv m_swapchainImageViews(imageViews), m_PassManager{std::make_unique<PassManager>(m_Context.m_Device)}, m_PipelineManager{std::make_unique<PipelineManager>(m_Context.m_Device)}, + m_DescriptorManager(std::make_unique<DescriptorManager>(m_Context.m_Device)), m_BufferManager{std::unique_ptr<BufferManager>(new BufferManager())}, m_CommandResources(commandResources), m_SyncResources(syncResources) @@ -253,13 +254,8 @@ namespace vkcv } } - ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) { - // TODO: - // call DescriptorManager's createResourceDescription - // let it do the actual work! No vulkan stuff here. - DescriptorManager descriptorManager = DescriptorManager(m_Context.getDevice()); - return descriptorManager.createResourceDescription(descriptorSets); + return m_DescriptorManager->createResourceDescription(descriptorSets); } } diff --git a/src/vkcv/DescriptorConfig.cpp b/src/vkcv/DescriptorConfig.cpp index de42fe22eb073a78490a85c0eb7f23e421e566a4..f437ab6833edca09f58499b6d74307606bba8999 100644 --- a/src/vkcv/DescriptorConfig.cpp +++ b/src/vkcv/DescriptorConfig.cpp @@ -1,25 +1,20 @@ #include "vkcv/DescriptorConfig.hpp" +#include <utility> + namespace vkcv { DescriptorBinding::DescriptorBinding( - uint32_t p_bindingID, - DescriptorType p_descriptorType, - uint32_t p_descriptorCount, - ShaderStage p_shaderStage + DescriptorType descriptorType, + uint32_t descriptorCount, + ShaderStage shaderStage ) noexcept : - bindingID{ p_bindingID }, - descriptorType{ p_descriptorType }, - descriptorCount{ p_descriptorCount }, - shaderStage{ p_shaderStage } + descriptorType{descriptorType}, + descriptorCount{descriptorCount}, + shaderStage{shaderStage} {}; - DescriptorSet::DescriptorSet( - std::vector<DescriptorBinding> p_bindings, - uint32_t p_setCount - ) noexcept : - bindings{ p_bindings }, - setCount{ p_setCount } + DescriptorSet::DescriptorSet(std::vector<DescriptorBinding> bindings) noexcept : + bindings{std::move(bindings)} {}; - -} \ No newline at end of file +} diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index 8226c2785eeb7bbcc34de9c55f750cb83d5875b9..bcebb142af2f29c23e77185112cbb83a827e41ba 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -1,88 +1,124 @@ #include "DescriptorManager.hpp" -#include <vkcv/ShaderProgram.hpp> - 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 }, m_NextDescriptorSetID{ 1 } + m_Device{ device }, m_NextResourceDescriptionID{ 1 } { - m_DescriptorTypes = { DescriptorType::UNIFORM_BUFFER, DescriptorType::SAMPLER, DescriptorType::IMAGE }; - uint32_t sizesPerType = 1000; - uint32_t maxSetsPerPool = 1000; + /** + * Allocate a set size for the initial pool, namely 1000 units of each descriptor type below. + */ + const std::vector<vk::DescriptorPoolSize> poolSizes = {vk::DescriptorPoolSize(vk::DescriptorType::eSampler, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eSampledImage, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1000), + vk::DescriptorPoolSize(vk::DescriptorType::eStorageBuffer, 1000)}; + + vk::DescriptorPoolCreateInfo poolInfo({}, + 1000, + static_cast<uint32_t>(poolSizes.size()), + poolSizes.data()); + + if(m_Device.createDescriptorPool(&poolInfo, nullptr, &m_Pool) != vk::Result::eSuccess) + { + std::cout << "FAILED TO ALLOCATED DESCRIPTOR POOL." << std::endl; + m_Pool = nullptr; + }; + } - std::vector<vk::DescriptorPoolSize> descriptorPoolSizes; - for (int i = 0; i < m_DescriptorTypes.size(); i++) { - vk::DescriptorType type = convertDescriptorTypeFlag(m_DescriptorTypes[i]); - vk::DescriptorPoolSize poolSize(type, sizesPerType); - descriptorPoolSizes.push_back(poolSize); + DescriptorManager::~DescriptorManager() noexcept + { + for(const auto &resource : m_ResourceDescriptions) + { + for(const auto &layout : resource.descriptorSetLayouts) + m_Device.destroyDescriptorSetLayout(layout); } - vk::DescriptorPoolCreateInfo poolInfo({}, maxSetsPerPool, descriptorPoolSizes); - m_Pool = m_Device.createDescriptorPool(poolInfo, nullptr); + m_Device.destroy(m_Pool); } - ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSet> &p_descriptorSets) + ResourcesHandle DescriptorManager::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets) { - ResourceDescription resource{}; + std::vector<vk::DescriptorSet> vk_sets; + std::vector<vk::DescriptorSetLayout> vk_setLayouts; + + for (const auto &set : descriptorSets) { + std::vector<vk::DescriptorSetLayoutBinding> setBindings = {}; - for (int i = 0; i < p_descriptorSets.size(); i++) { - DescriptorSet set = p_descriptorSets[i]; - std::vector<vk::DescriptorSetLayoutBinding> setBindings; - for (int j = 0; j < set.bindings.size(); j++) { - //creates each binding of the set - DescriptorBinding binding = set.bindings[j]; - vk::DescriptorType type = convertDescriptorTypeFlag(binding.descriptorType); - vk::ShaderStageFlagBits stage = convertShaderStageFlag(binding.shaderStage); - vk::DescriptorSetLayoutBinding descriptorSetLayoutBinding(binding.bindingID, type, binding.descriptorCount, stage); + //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); } - //creates the descriptor set layouts - vk::DescriptorSetLayoutCreateInfo descriptorSetLayoutInfo({}, setBindings); - vk::DescriptorSetLayout allocLayout = m_Device.createDescriptorSetLayout(descriptorSetLayoutInfo, nullptr); - std::vector<vk::DescriptorSetLayout> allocLayouts(set.setCount, allocLayout); - //binds the layout to the pool - vk::DescriptorSetAllocateInfo allocInfo(m_Pool, allocLayout); - - //creates and allocates the set(s) based on the layout - vk::DescriptorSet allocSet; - std::vector<vk::DescriptorSet> allocSets(set.setCount, allocSet); - m_Device.allocateDescriptorSets(&allocInfo, allocSets.data()); - //inserts the descriptor sets and layouts into the resources (also considers copies of the same sets) - resource.descriptorSetLayouts.insert(resource.descriptorSetLayouts.begin(), allocLayouts.begin(), allocLayouts.end()); - resource.descriptorSets.insert(resource.descriptorSets.end(), allocSets.begin(), allocSets.end()); + //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{0}; + }; + vk_setLayouts.push_back(layout); } - m_ResourceDescriptions.push_back(resource); - return ResourcesHandle{m_NextDescriptorSetID++}; + //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_Pool, vk_sets.size(), vk_setLayouts.data()); + auto result = m_Device.allocateDescriptorSets(&allocInfo, vk_sets.data()); + 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); + + return ResourcesHandle{0}; + }; + + m_ResourceDescriptions.emplace_back(vk_sets, vk_setLayouts); + return ResourcesHandle{m_NextResourceDescriptionID++}; } vk::DescriptorType DescriptorManager::convertDescriptorTypeFlag(DescriptorType type) { switch (type) { - case DescriptorType::UNIFORM_BUFFER: - return vk::DescriptorType::eUniformBuffer; - case DescriptorType::SAMPLER: - return vk::DescriptorType::eSampler; - case DescriptorType::IMAGE: - return vk::DescriptorType::eSampledImage; + case DescriptorType::UNIFORM_BUFFER: + return vk::DescriptorType::eUniformBuffer; + case DescriptorType::STORAGE_BUFFER: + return vk::DescriptorType::eStorageBuffer; + case DescriptorType::SAMPLER: + return vk::DescriptorType::eSampler; + case DescriptorType::IMAGE: + return vk::DescriptorType::eSampledImage; + default: + return vk::DescriptorType::eUniformBuffer; } } vk::ShaderStageFlagBits DescriptorManager::convertShaderStageFlag(ShaderStage stage) { switch (stage) { - case ShaderStage::VERTEX: - return vk::ShaderStageFlagBits::eVertex; - case ShaderStage::FRAGMENT: - return vk::ShaderStageFlagBits::eFragment; - case ShaderStage::TESS_CONTROL: - return vk::ShaderStageFlagBits::eTessellationControl; - case ShaderStage::TESS_EVAL: - return vk::ShaderStageFlagBits::eTessellationControl; - case ShaderStage::GEOMETRY: - return vk::ShaderStageFlagBits::eGeometry; - case ShaderStage::COMPUTE: - return vk::ShaderStageFlagBits::eCompute; + case ShaderStage::VERTEX: + return vk::ShaderStageFlagBits::eVertex; + case ShaderStage::FRAGMENT: + return vk::ShaderStageFlagBits::eFragment; + case ShaderStage::TESS_CONTROL: + return vk::ShaderStageFlagBits::eTessellationControl; + case ShaderStage::TESS_EVAL: + return vk::ShaderStageFlagBits::eTessellationEvaluation; + case ShaderStage::GEOMETRY: + return vk::ShaderStageFlagBits::eGeometry; + case ShaderStage::COMPUTE: + return vk::ShaderStageFlagBits::eCompute; + default: + return vk::ShaderStageFlagBits::eAll; } } diff --git a/src/vkcv/DescriptorManager.hpp b/src/vkcv/DescriptorManager.hpp index cb8a0f6597c9a0f13ee52fd94d6f635539f07055..744f557051bee3a6524abcf16822c3faa9c78576 100644 --- a/src/vkcv/DescriptorManager.hpp +++ b/src/vkcv/DescriptorManager.hpp @@ -9,7 +9,7 @@ namespace vkcv { public: explicit DescriptorManager(vk::Device device) noexcept; - ~DescriptorManager() = default; + ~DescriptorManager() noexcept; /** * Creates all vk::DescriptorSets and allocates them from the pool. @@ -18,12 +18,12 @@ namespace vkcv * @param[in] vector of filled vkcv::DescriptorSet structs * @return index into that objects a resource handle */ - ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> & p_descriptorSets); + ResourcesHandle createResourceDescription(const std::vector<DescriptorSet> & descriptorSets); private: vk::Device m_Device; vk::DescriptorPool m_Pool; - uint64_t m_NextDescriptorSetID; + /** * Container for all resources requested by the user in one call of createResourceDescription. @@ -31,6 +31,9 @@ namespace vkcv */ 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; }; @@ -39,24 +42,20 @@ namespace vkcv * Contains all the resource descriptions that were requested by the user in calls of createResourceDescription. */ std::vector<ResourceDescription> m_ResourceDescriptions; - - /** - * Contains all the allowed vkcv::DescriptorTypes that were also pre-defined in the DescriptorConfig class. - * Allowed types are defined in the constructor of DescriptorManager. - */ - std::vector<DescriptorType> m_DescriptorTypes; + // Counter for the vector above + uint64_t m_NextResourceDescriptionID; /** * Converts the flags of the descriptor types from VulkanCV (vkcv) to Vulkan (vk). * @param[in] vkcv flag of the DescriptorType (see DescriptorConfig.hpp) * @return vk flag of the DescriptorType */ - vk::DescriptorType convertDescriptorTypeFlag(DescriptorType type); + static vk::DescriptorType convertDescriptorTypeFlag(DescriptorType type); /** * Converts the flags of the shader stages from VulkanCV (vkcv) to Vulkan (vk). * @param[in] vkcv flag of the ShaderStage (see ShaderProgram.hpp) * @return vk flag of the ShaderStage */ - vk::ShaderStageFlagBits convertShaderStageFlag(ShaderStage stage); + static vk::ShaderStageFlagBits convertShaderStageFlag(ShaderStage stage); }; } \ No newline at end of file