Simplify free descriptor set accounting and update ratios

Slightly reduces descriptor usage in Breath of The Wild
This commit is contained in:
Billy Laws 2023-01-20 21:01:13 +00:00
parent 5e862cf5f7
commit bbef006051
2 changed files with 21 additions and 15 deletions

View File

@ -16,29 +16,34 @@ namespace skyline::gpu {
void DescriptorAllocator::AllocateDescriptorPool() { void DescriptorAllocator::AllocateDescriptorPool() {
namespace maxwell3d = soc::gm20b::engine::maxwell3d::type; // We use Maxwell3D as reference for base descriptor counts namespace maxwell3d = soc::gm20b::engine::maxwell3d::type; // We use Maxwell3D as reference for base descriptor counts
using DescriptorSizes = std::array<vk::DescriptorPoolSize, 5>; using DescriptorSizes = std::array<vk::DescriptorPoolSize, 6>;
constexpr DescriptorSizes BaseDescriptorSizes{ constexpr DescriptorSizes BaseDescriptorSizes{
vk::DescriptorPoolSize{ vk::DescriptorPoolSize{
.descriptorCount = maxwell3d::ShaderStageConstantBufferCount, .descriptorCount = 512,
.type = vk::DescriptorType::eUniformBuffer, .type = vk::DescriptorType::eUniformBuffer,
}, },
vk::DescriptorPoolSize{ vk::DescriptorPoolSize{
.descriptorCount = maxwell3d::ShaderStageCount * 5, .descriptorCount = 64,
.type = vk::DescriptorType::eStorageBuffer, .type = vk::DescriptorType::eStorageBuffer,
}, },
vk::DescriptorPoolSize{ vk::DescriptorPoolSize{
.descriptorCount = maxwell3d::ShaderStageCount * 5, .descriptorCount = 256,
.type = vk::DescriptorType::eCombinedImageSampler, .type = vk::DescriptorType::eCombinedImageSampler,
}, },
vk::DescriptorPoolSize{ vk::DescriptorPoolSize{
.descriptorCount = maxwell3d::ShaderStageCount, .descriptorCount = 16,
.type = vk::DescriptorType::eStorageImage, .type = vk::DescriptorType::eStorageImage,
}, },
vk::DescriptorPoolSize{ vk::DescriptorPoolSize{
.descriptorCount = maxwell3d::ColorTargetCount, .descriptorCount = 4,
.type = vk::DescriptorType::eInputAttachment, .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}; DescriptorSizes descriptorSizes{BaseDescriptorSizes};
for (auto &descriptorSize : descriptorSizes) for (auto &descriptorSize : descriptorSizes)
@ -49,6 +54,8 @@ namespace skyline::gpu {
.pPoolSizes = descriptorSizes.data(), .pPoolSizes = descriptorSizes.data(),
.poolSizeCount = descriptorSizes.size(), .poolSizeCount = descriptorSizes.size(),
}); });
pool->freeSetCount = descriptorSetCount;
} }
vk::ResultValue<vk::DescriptorSet> DescriptorAllocator::AllocateVkDescriptorSet(vk::DescriptorSetLayout layout) { vk::ResultValue<vk::DescriptorSet> DescriptorAllocator::AllocateVkDescriptorSet(vk::DescriptorSetLayout layout) {
@ -60,6 +67,9 @@ namespace skyline::gpu {
vk::DescriptorSet descriptorSet{}; vk::DescriptorSet descriptorSet{};
auto result{(*gpu.vkDevice).allocateDescriptorSets(&allocateInfo, &descriptorSet, *gpu.vkDevice.getDispatcher())}; auto result{(*gpu.vkDevice).allocateDescriptorSets(&allocateInfo, &descriptorSet, *gpu.vkDevice.getDispatcher())};
if (pool->freeSetCount > 0)
pool->freeSetCount--;
return vk::createResultValue(result, descriptorSet, __builtin_FUNCTION(), { return vk::createResultValue(result, descriptorSet, __builtin_FUNCTION(), {
vk::Result::eSuccess, vk::Result::eSuccess,
vk::Result::eErrorOutOfPoolMemory, vk::Result::eErrorOutOfPoolMemory,
@ -67,9 +77,7 @@ namespace skyline::gpu {
}); });
} }
DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} { DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(std::shared_ptr<DescriptorPool> pPool, DescriptorSetSlot *slot) : pool{std::move(pPool)}, slot{slot} {}
pool->freeSetCount--;
}
DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(DescriptorAllocator::ActiveDescriptorSet &&other) noexcept { DescriptorAllocator::ActiveDescriptorSet::ActiveDescriptorSet(DescriptorAllocator::ActiveDescriptorSet &&other) noexcept {
pool = std::move(other.pool); pool = std::move(other.pool);
@ -77,10 +85,8 @@ namespace skyline::gpu {
} }
DescriptorAllocator::ActiveDescriptorSet::~ActiveDescriptorSet() { DescriptorAllocator::ActiveDescriptorSet::~ActiveDescriptorSet() {
if (slot) { if (slot)
slot->active.clear(std::memory_order_release); slot->active.clear(std::memory_order_release);
pool->freeSetCount++;
}
} }
DescriptorAllocator::DescriptorAllocator(GPU &gpu) : gpu{gpu} { DescriptorAllocator::DescriptorAllocator(GPU &gpu) : gpu{gpu} {

View File

@ -36,7 +36,7 @@ namespace skyline::gpu {
* @brief A lockable VkDescriptorPool for maintaining external synchronization requirements * @brief A lockable VkDescriptorPool for maintaining external synchronization requirements
*/ */
struct DescriptorPool : public vk::raii::DescriptorPool { struct DescriptorPool : public vk::raii::DescriptorPool {
std::atomic<u64> 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<vk::DescriptorSetLayout, std::list<DescriptorSetSlot>> layoutSlots; //!< A map of pools based on the layout of the descriptor sets std::unordered_map<vk::DescriptorSetLayout, std::list<DescriptorSetSlot>> layoutSlots; //!< A map of pools based on the layout of the descriptor sets
DescriptorPool(vk::raii::Device const &device, vk::DescriptorPoolCreateInfo const &createInfo); DescriptorPool(vk::raii::Device const &device, vk::DescriptorPoolCreateInfo const &createInfo);