diff --git a/include/core/descriptorset.hpp b/include/core/descriptorset.hpp index 339ea54..89c33f7 100644 --- a/include/core/descriptorset.hpp +++ b/include/core/descriptorset.hpp @@ -17,6 +17,8 @@ namespace Vulkan::Core { + class DescriptorSetUpdateBuilder; + /// /// C++ wrapper class for a Vulkan descriptor set. /// @@ -36,16 +38,18 @@ namespace Vulkan::Core { DescriptorSet(const Device& device, DescriptorPool pool, const ShaderModule& shaderModule); - using ResourcePair = std::pair>; + using ResourceList = std::variant< + std::pair&>, + std::pair&>, + std::pair&> + >; /// /// Update the descriptor set with resources. /// /// @param device Vulkan device - /// @param resources Resources to update the descriptor set with /// - void update(const Device& device, - const std::vector>& resources) const; + [[nodiscard]] DescriptorSetUpdateBuilder update(const Device& device) const; /// /// Bind a descriptor set to a command buffer. @@ -68,6 +72,37 @@ namespace Vulkan::Core { std::shared_ptr descriptorSet; }; + /// + /// Builder class for updating a descriptor set. + /// + class DescriptorSetUpdateBuilder { + friend class DescriptorSet; + public: + /// Add a resource to the descriptor set update. + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Image& image); + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Sampler& sampler); + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const Buffer& buffer); + + /// Add a list of resources to the descriptor set update. + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector& images) { + for (const auto& image : images) this->add(type, image); return *this; } + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector& samplers) { + for (const auto& sampler : samplers) this->add(type, sampler); return *this; } + DescriptorSetUpdateBuilder& add(VkDescriptorType type, const std::vector& buffers) { + for (const auto& buffer : buffers) this->add(type, buffer); return *this; } + + /// Finish building the descriptor set update. + void build() const; + private: + const DescriptorSet* descriptorSet; + const Device* device; + + DescriptorSetUpdateBuilder(const DescriptorSet& descriptorSet, const Device& device) + : descriptorSet(&descriptorSet), device(&device) {} + + std::vector entries; + }; + } #endif // DESCRIPTORSET_HPP diff --git a/src/core/descriptorset.cpp b/src/core/descriptorset.cpp index 36b6ae6..de752c0 100644 --- a/src/core/descriptorset.cpp +++ b/src/core/descriptorset.cpp @@ -27,47 +27,8 @@ DescriptorSet::DescriptorSet(const Device& device, ); } -void DescriptorSet::update(const Device& device, - const std::vector>& resources) const { - std::vector writeDescriptorSets; - uint32_t bindingIndex = 0; - for (const auto& list : resources) { - for (const auto& [type, resource] : list) { - VkWriteDescriptorSet writeDesc{ - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = this->handle(), - .dstBinding = bindingIndex++, - .descriptorCount = 1, - .descriptorType = type, - }; - - if (std::holds_alternative(resource)) { - const VkDescriptorImageInfo imageInfo{ - .imageView = std::get(resource).getView(), - .imageLayout = VK_IMAGE_LAYOUT_GENERAL - }; - writeDesc.pImageInfo = &imageInfo; - } else if (std::holds_alternative(resource)) { - const VkDescriptorImageInfo imageInfo{ - .sampler = std::get(resource).handle() - }; - writeDesc.pImageInfo = &imageInfo; - } else if (std::holds_alternative(resource)) { - const auto& buffer = std::get(resource); - const VkDescriptorBufferInfo bufferInfo{ - .buffer = buffer.handle(), - .range = buffer.getSize() - }; - writeDesc.pBufferInfo = &bufferInfo; - } - - writeDescriptorSets.push_back(writeDesc); - } - } - - vkUpdateDescriptorSets(device.handle(), - static_cast(writeDescriptorSets.size()), - writeDescriptorSets.data(), 0, nullptr); +DescriptorSetUpdateBuilder DescriptorSet::update(const Device& device) const { + return { *this, device }; } void DescriptorSet::bind(const CommandBuffer& commandBuffer, const Pipeline& pipeline) const { @@ -76,3 +37,67 @@ void DescriptorSet::bind(const CommandBuffer& commandBuffer, const Pipeline& pip VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.getLayout(), 0, 1, &descriptorSetHandle, 0, nullptr); } + +// updater class + +DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Image& image) { + this->entries.push_back({ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = this->descriptorSet->handle(), + .dstBinding = static_cast(this->entries.size()), + .descriptorCount = 1, + .descriptorType = type, + .pImageInfo = new VkDescriptorImageInfo { + .imageView = image.getView(), + .imageLayout = VK_IMAGE_LAYOUT_GENERAL + }, + .pBufferInfo = nullptr + }); + return *this; +} + +DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Sampler& sampler) { + this->entries.push_back({ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = this->descriptorSet->handle(), + .dstBinding = static_cast(this->entries.size()), + .descriptorCount = 1, + .descriptorType = type, + .pImageInfo = new VkDescriptorImageInfo { + .sampler = sampler.handle(), + }, + .pBufferInfo = nullptr + }); + return *this; +} + +DescriptorSetUpdateBuilder& DescriptorSetUpdateBuilder::add(VkDescriptorType type, const Buffer& buffer) { + this->entries.push_back({ + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = this->descriptorSet->handle(), + .dstBinding = static_cast(this->entries.size()), + .descriptorCount = 1, + .descriptorType = type, + .pImageInfo = nullptr, + .pBufferInfo = new VkDescriptorBufferInfo { + .buffer = buffer.handle(), + .range = buffer.getSize() + } + }); + return *this; +} + +void DescriptorSetUpdateBuilder::build() const { + if (this->entries.empty()) return; + + vkUpdateDescriptorSets(this->device->handle(), + static_cast(this->entries.size()), + this->entries.data(), 0, nullptr); + + // NOLINTBEGIN + for (const auto& entry : this->entries) { + delete entry.pImageInfo; + delete entry.pBufferInfo; + } + // NOLINTEND +} diff --git a/src/main.cpp b/src/main.cpp index c4cfa31..b3df478 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,6 @@ #include "instance.hpp" #include "utils/memorybarriers.hpp" -#include #include #include #include @@ -75,23 +74,12 @@ int main() { // load descriptor set const Core::DescriptorSet descriptorSet(device, descriptorPool, computeShader); - descriptorSet.update( - device, - { - {{ VK_DESCRIPTOR_TYPE_SAMPLER, sampler }}, - {{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, inputImages[0] }}, - { - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[0] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[1] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[2] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[3] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[4] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[5] }, - { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages[6] } - }, - {{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer }} - } - ); + descriptorSet.update(device) + .add(VK_DESCRIPTOR_TYPE_SAMPLER, sampler) + .add(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, inputImages) + .add(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, outputImages) + .add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer) + .build(); // start pass Core::Fence fence(device);