From bbef00605192f33a5c4973791a09a1deb80c5e03 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 20 Jan 2023 21:01:13 +0000 Subject: [PATCH] Simplify free descriptor set accounting and update ratios Slightly reduces descriptor usage in Breath of The Wild --- .../cpp/skyline/gpu/descriptor_allocator.cpp | 34 +++++++++++-------- .../cpp/skyline/gpu/descriptor_allocator.h | 2 +- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/descriptor_allocator.cpp b/app/src/main/cpp/skyline/gpu/descriptor_allocator.cpp index 9eee1cb4..d5c5bd56 100644 --- a/app/src/main/cpp/skyline/gpu/descriptor_allocator.cpp +++ b/app/src/main/cpp/skyline/gpu/descriptor_allocator.cpp @@ -16,29 +16,34 @@ namespace skyline::gpu { void DescriptorAllocator::AllocateDescriptorPool() { namespace maxwell3d = soc::gm20b::engine::maxwell3d::type; // We use Maxwell3D as reference for base descriptor counts - using DescriptorSizes = std::array; + using DescriptorSizes = std::array; + constexpr DescriptorSizes BaseDescriptorSizes{ vk::DescriptorPoolSize{ - .descriptorCount = maxwell3d::ShaderStageConstantBufferCount, + .descriptorCount = 512, .type = vk::DescriptorType::eUniformBuffer, }, vk::DescriptorPoolSize{ - .descriptorCount = maxwell3d::ShaderStageCount * 5, + .descriptorCount = 64, .type = vk::DescriptorType::eStorageBuffer, }, vk::DescriptorPoolSize{ - .descriptorCount = maxwell3d::ShaderStageCount * 5, + .descriptorCount = 256, .type = vk::DescriptorType::eCombinedImageSampler, }, vk::DescriptorPoolSize{ - .descriptorCount = maxwell3d::ShaderStageCount, + .descriptorCount = 16, .type = vk::DescriptorType::eStorageImage, }, vk::DescriptorPoolSize{ - .descriptorCount = maxwell3d::ColorTargetCount, - .type = vk::DescriptorType::eInputAttachment, + .descriptorCount = 4, + .type = vk::DescriptorType::eUniformTexelBuffer, }, - }; //!< A best approximate ratio of descriptors of each type that may be utilized, the total amount will grow in these ratios + vk::DescriptorPoolSize{ + .descriptorCount = 4, + .type = vk::DescriptorType::eStorageTexelBuffer, + } //!< Approximated descriptor counts based off empirical testing, the total amount will grow in these ratios + }; DescriptorSizes descriptorSizes{BaseDescriptorSizes}; for (auto &descriptorSize : descriptorSizes) @@ -49,6 +54,8 @@ namespace skyline::gpu { .pPoolSizes = descriptorSizes.data(), .poolSizeCount = descriptorSizes.size(), }); + + pool->freeSetCount = descriptorSetCount; } vk::ResultValue DescriptorAllocator::AllocateVkDescriptorSet(vk::DescriptorSetLayout layout) { @@ -60,6 +67,9 @@ namespace skyline::gpu { vk::DescriptorSet descriptorSet{}; auto result{(*gpu.vkDevice).allocateDescriptorSets(&allocateInfo, &descriptorSet, *gpu.vkDevice.getDispatcher())}; + if (pool->freeSetCount > 0) + pool->freeSetCount--; + return vk::createResultValue(result, descriptorSet, __builtin_FUNCTION(), { vk::Result::eSuccess, vk::Result::eErrorOutOfPoolMemory, @@ -67,9 +77,7 @@ namespace skyline::gpu { }); } - DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} { - pool->freeSetCount--; - } + DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} {} DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(DescriptorAllocator::ActiveDescriptorSet &&other) noexcept { pool = std::move(other.pool); @@ -77,10 +85,8 @@ namespace skyline::gpu { } DescriptorAllocator::ActiveDescriptorSet::~ActiveDescriptorSet() { - if (slot) { + if (slot) slot->active.clear(std::memory_order_release); - pool->freeSetCount++; - } } DescriptorAllocator::DescriptorAllocator(GPU &gpu) : gpu{gpu} { diff --git a/app/src/main/cpp/skyline/gpu/descriptor_allocator.h b/app/src/main/cpp/skyline/gpu/descriptor_allocator.h index 0ce287c6..244223f2 100644 --- a/app/src/main/cpp/skyline/gpu/descriptor_allocator.h +++ b/app/src/main/cpp/skyline/gpu/descriptor_allocator.h @@ -36,7 +36,7 @@ namespace skyline::gpu { * @brief A lockable VkDescriptorPool for maintaining external synchronization requirements */ struct DescriptorPool : public vk::raii::DescriptorPool { - std::atomic freeSetCount{}; //!< The amount of sets free to allocate from this pool + size_t freeSetCount{}; //!< The amount of sets free to allocate from this pool std::unordered_map> layoutSlots; //!< A map of pools based on the layout of the descriptor sets DescriptorPool(vk::raii::Device const &device, vk::DescriptorPoolCreateInfo const &createInfo);