From be453697f094102f07c657171417add374245d28 Mon Sep 17 00:00:00 2001 From: Slendi Date: Thu, 11 Dec 2025 11:09:07 +0200 Subject: [PATCH] More abstraction... Signed-off-by: Slendi --- meson.build | 2 + src/DescriptorAllocatorGrowable.cpp | 113 ++++++++++++++++++++++++++++ src/DescriptorAllocatorGrowable.h | 38 ++++++++++ src/DescriptorWriter.cpp | 70 +++++++++++++++++ src/DescriptorWriter.h | 24 ++++++ src/Types.h | 2 + src/VulkanRenderer.cpp | 19 ++--- 7 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 src/DescriptorAllocatorGrowable.cpp create mode 100644 src/DescriptorAllocatorGrowable.h create mode 100644 src/DescriptorWriter.cpp create mode 100644 src/DescriptorWriter.h diff --git a/meson.build b/meson.build index 68e05c2..be22895 100644 --- a/meson.build +++ b/meson.build @@ -110,7 +110,9 @@ exe = executable('vr-compositor', 'src/DescriptorLayoutBuilder.cpp', 'src/DescriptorAllocator.cpp', 'src/GraphicsPipelineBuilder.cpp', + 'src/DescriptorAllocatorGrowable.cpp', 'src/Loader.cpp', + 'src/DescriptorWriter.cpp', 'src/VulkanRenderer.cpp', 'src/Application.cpp', ], diff --git a/src/DescriptorAllocatorGrowable.cpp b/src/DescriptorAllocatorGrowable.cpp new file mode 100644 index 0000000..8ed0085 --- /dev/null +++ b/src/DescriptorAllocatorGrowable.cpp @@ -0,0 +1,113 @@ +#include "DescriptorAllocatorGrowable.h" + +#include "Logger.h" +#include "Util.h" + +namespace Lunar { + +auto DescriptorAllocatorGrowable::init(VkDevice dev, uint32_t max_sets, + std::span pool_ratios) -> void +{ + m_ratios.clear(); + + m_ratios.insert(m_ratios.begin(), pool_ratios.begin(), pool_ratios.end()); + + auto const new_pool = create_pool(dev, max_sets, pool_ratios); + + m_sets_per_pool = static_cast(max_sets * 1.5); + if (m_sets_per_pool > 4092) + m_sets_per_pool = 4092; + + m_ready_pools.emplace_back(new_pool); +} + +auto DescriptorAllocatorGrowable::clear_pools(VkDevice dev) -> void +{ + for (auto const p : m_ready_pools) + vkResetDescriptorPool(dev, p, 0); + for (auto const p : m_full_pools) { + vkResetDescriptorPool(dev, p, 0); + m_ready_pools.emplace_back(p); + } + m_full_pools.clear(); +} + +auto DescriptorAllocatorGrowable::destroy_pools(VkDevice dev) -> void +{ + for (auto const p : m_ready_pools) { + vkDestroyDescriptorPool(dev, p, nullptr); + } + m_ready_pools.clear(); + for (auto const p : m_full_pools) { + vkDestroyDescriptorPool(dev, p, nullptr); + } + m_full_pools.clear(); +} + +auto DescriptorAllocatorGrowable::allocate(Logger &logger, VkDevice dev, + VkDescriptorSetLayout layout, void *p_next) -> VkDescriptorSet +{ + auto pool_to_use = get_pool(dev); + + VkDescriptorSetAllocateInfo alloci {}; + alloci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloci.pNext = p_next; + alloci.descriptorPool = pool_to_use; + alloci.descriptorSetCount = 1; + alloci.pSetLayouts = &layout; + + VkDescriptorSet ds; + auto const res = vkAllocateDescriptorSets(dev, &alloci, &ds); + if (res == VK_ERROR_OUT_OF_POOL_MEMORY || res == VK_ERROR_FRAGMENTED_POOL) { + m_full_pools.emplace_back(pool_to_use); + pool_to_use = get_pool(dev); + alloci.descriptorPool = pool_to_use; + VK_CHECK(logger, vkAllocateDescriptorSets(dev, &alloci, &ds)); + } + + m_ready_pools.emplace_back(pool_to_use); + return ds; +} + +auto DescriptorAllocatorGrowable::get_pool(VkDevice dev) -> VkDescriptorPool +{ + VkDescriptorPool new_pool; + + if (m_ready_pools.empty()) { + new_pool = create_pool(dev, m_sets_per_pool, m_ratios); + + m_sets_per_pool = static_cast(m_sets_per_pool * 1.5); + if (m_sets_per_pool > 4092) + m_sets_per_pool = 4092; + } else { + new_pool = m_ready_pools.back(); + m_ready_pools.pop_back(); + } + + return new_pool; +} + +auto DescriptorAllocatorGrowable::create_pool(VkDevice dev, uint32_t set_count, + std::span pool_ratios) -> VkDescriptorPool +{ + std::vector pool_sizes; + for (auto const ratio : pool_ratios) { + pool_sizes.emplace_back(VkDescriptorPoolSize { + .type = ratio.type, + .descriptorCount = static_cast(ratio.ratio * set_count), + }); + } + + VkDescriptorPoolCreateInfo pool_ci {}; + pool_ci.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_ci.flags = 0; + pool_ci.maxSets = set_count; + pool_ci.poolSizeCount = static_cast(pool_sizes.size()); + pool_ci.pPoolSizes = pool_sizes.data(); + + VkDescriptorPool new_pool; + vkCreateDescriptorPool(dev, &pool_ci, nullptr, &new_pool); + return new_pool; +} + +} // namespace Lunar diff --git a/src/DescriptorAllocatorGrowable.h b/src/DescriptorAllocatorGrowable.h new file mode 100644 index 0000000..b93591a --- /dev/null +++ b/src/DescriptorAllocatorGrowable.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include + +#include "Logger.h" + +namespace Lunar { + +struct DescriptorAllocatorGrowable { + struct PoolSizeRatio { + VkDescriptorType type; + float ratio; + }; + + auto init(VkDevice dev, uint32_t max_sets, + std::span pool_ratios) -> void; + + auto clear_pools(VkDevice dev) -> void; + auto destroy_pools(VkDevice dev) -> void; + + auto allocate(Logger &logger, VkDevice dev, VkDescriptorSetLayout layout, + void *p_next = nullptr) -> VkDescriptorSet; + +private: + auto get_pool(VkDevice dev) -> VkDescriptorPool; + auto create_pool(VkDevice dev, uint32_t set_count, + std::span pool_ratios) -> VkDescriptorPool; + + std::vector m_ratios; + std::vector m_full_pools; + std::vector m_ready_pools; + uint32_t m_sets_per_pool; +}; + +} // namespace Lunar diff --git a/src/DescriptorWriter.cpp b/src/DescriptorWriter.cpp new file mode 100644 index 0000000..2ae006f --- /dev/null +++ b/src/DescriptorWriter.cpp @@ -0,0 +1,70 @@ +#include "DescriptorWriter.h" + +namespace Lunar { + +auto DescriptorWriter::write_image(int binding, VkImageView image_view, + VkSampler sampler, VkImageLayout layout, VkDescriptorType type) + -> DescriptorWriter & +{ + auto const &info = image_infos.emplace_back(VkDescriptorImageInfo { + .sampler = sampler, + .imageView = image_view, + .imageLayout = layout, + }); + + VkWriteDescriptorSet write {}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.pNext = nullptr; + write.dstBinding = binding; + write.dstSet = VK_NULL_HANDLE; + write.descriptorCount = 1; + write.descriptorType = type; + write.pImageInfo = &info; + + writes.emplace_back(write); + + return *this; +} + +auto DescriptorWriter::write_buffer(int binding, VkBuffer buffer, size_t size, + size_t offset, VkDescriptorType type) -> DescriptorWriter & +{ + auto const &info = buffer_infos.emplace_back(VkDescriptorBufferInfo { + .buffer = buffer, + .offset = offset, + .range = size, + }); + + VkWriteDescriptorSet write {}; + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.pNext = nullptr; + write.dstBinding = binding; + write.dstSet = VK_NULL_HANDLE; + write.descriptorCount = 1; + write.descriptorType = type; + write.pBufferInfo = &info; + + writes.emplace_back(write); + + return *this; +} + +auto DescriptorWriter::clear() -> DescriptorWriter & +{ + image_infos.clear(); + writes.clear(); + buffer_infos.clear(); + + return *this; +} + +auto DescriptorWriter::update_set(VkDevice dev, VkDescriptorSet set) -> void +{ + for (auto &write : writes) { + write.dstSet = set; + } + vkUpdateDescriptorSets( + dev, static_cast(writes.size()), writes.data(), 0, nullptr); +} + +} // namespace Lunar diff --git a/src/DescriptorWriter.h b/src/DescriptorWriter.h new file mode 100644 index 0000000..0af8188 --- /dev/null +++ b/src/DescriptorWriter.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include + +namespace Lunar { + +struct DescriptorWriter { + std::deque image_infos; + std::deque buffer_infos; + std::vector writes; + + auto write_image(int binding, VkImageView image_view, VkSampler sampler, + VkImageLayout layout, VkDescriptorType type) -> DescriptorWriter &; + auto write_buffer(int binding, VkBuffer buffer, size_t size, size_t offset, + VkDescriptorType type) -> DescriptorWriter &; + + auto clear() -> DescriptorWriter &; + auto update_set(VkDevice dev, VkDescriptorSet set) -> void; +}; + +} // namespace Lunar diff --git a/src/Types.h b/src/Types.h index 9170c70..23a90f5 100644 --- a/src/Types.h +++ b/src/Types.h @@ -5,6 +5,7 @@ #include #include "DeletionQueue.h" +#include "DescriptorAllocatorGrowable.h" namespace Lunar { @@ -29,6 +30,7 @@ struct FrameData { VkFence render_fence; DeletionQueue deletion_queue; + DescriptorAllocatorGrowable frame_descriptors; }; struct Vertex { diff --git a/src/VulkanRenderer.cpp b/src/VulkanRenderer.cpp index 6e9e845..ba07040 100644 --- a/src/VulkanRenderer.cpp +++ b/src/VulkanRenderer.cpp @@ -14,6 +14,7 @@ #include #include "DescriptorLayoutBuilder.h" +#include "DescriptorWriter.h" #include "GraphicsPipelineBuilder.h" #include "Util.h" @@ -940,20 +941,10 @@ auto VulkanRenderer::destroy_depth_image() -> void auto VulkanRenderer::update_draw_image_descriptor() -> void { - VkDescriptorImageInfo img_info {}; - img_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - img_info.imageView = m_vk.draw_image.image_view; - - VkWriteDescriptorSet draw_img_write {}; - draw_img_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - draw_img_write.pNext = nullptr; - draw_img_write.dstBinding = 0; - draw_img_write.dstSet = m_vk.draw_image_descriptors; - draw_img_write.descriptorCount = 1; - draw_img_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - draw_img_write.pImageInfo = &img_info; - - vkUpdateDescriptorSets(m_vkb.dev, 1, &draw_img_write, 0, nullptr); + DescriptorWriter() + .write_image(0, m_vk.draw_image.image_view, VK_NULL_HANDLE, + VK_IMAGE_LAYOUT_GENERAL, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) + .update_set(m_vkb.dev, m_vk.draw_image_descriptors); } auto VulkanRenderer::destroy_draw_image() -> void