From 6992b0d8e16c84df93203e82853d80e96cf7de6b Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Thu, 6 Oct 2022 01:35:17 +0200 Subject: VideoBackends:Vulkan: Allocate descriptor pools as needed --- .../VideoBackends/Vulkan/CommandBufferManager.cpp | 132 ++++++++++++++------- 1 file changed, 89 insertions(+), 43 deletions(-) (limited to 'Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp') diff --git a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp index 8f6bfc2929..246e0ad213 100644 --- a/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp +++ b/Source/Core/VideoBackends/Vulkan/CommandBufferManager.cpp @@ -95,34 +95,6 @@ bool CommandBufferManager::CreateCommandBuffers() } } - for (VkDescriptorPool& descriptor_pool : m_descriptor_pools) - { - // TODO: A better way to choose the number of descriptors. - const std::array pool_sizes{{ - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 500000}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 500000}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 16}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 16384}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 16384}, - }}; - - const VkDescriptorPoolCreateInfo pool_create_info = { - VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - nullptr, - 0, - 100000, // tweak this - static_cast(pool_sizes.size()), - pool_sizes.data(), - }; - - res = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &descriptor_pool); - if (res != VK_SUCCESS) - { - LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: "); - return false; - } - } - res = vkCreateSemaphore(device, &semaphore_create_info, nullptr, &m_present_semaphore); if (res != VK_SUCCESS) { @@ -160,29 +132,85 @@ void CommandBufferManager::DestroyCommandBuffers() vkDestroyFence(device, resources.fence, nullptr); } - for (VkDescriptorPool descriptor_pool : m_descriptor_pools) + for (FrameResources& resources : m_frame_resources) { - if (descriptor_pool != VK_NULL_HANDLE) + for (VkDescriptorPool descriptor_pool : resources.descriptor_pools) + { vkDestroyDescriptorPool(device, descriptor_pool, nullptr); + } } vkDestroySemaphore(device, m_present_semaphore, nullptr); } -VkDescriptorSet CommandBufferManager::AllocateDescriptorSet(VkDescriptorSetLayout set_layout) +VkDescriptorPool CommandBufferManager::CreateDescriptorPool(u32 max_descriptor_sets) { - VkDescriptorSetAllocateInfo allocate_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - nullptr, GetCurrentDescriptorPool(), 1, &set_layout}; + /* + * Worst case descriptor counts according to the descriptor layout created in ObjectCache.cpp: + * UNIFORM_BUFFER_DYNAMIC: 3 + * COMBINED_IMAGE_SAMPLER: 18 + * STORAGE_BUFFER: 2 + * UNIFORM_TEXEL_BUFFER: 3 + * STORAGE_IMAGE: 1 + */ + const std::array pool_sizes{{ + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, max_descriptor_sets * 3}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, max_descriptor_sets * 18}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, max_descriptor_sets * 2}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, max_descriptor_sets * 3}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, max_descriptor_sets * 1}, + }}; + + const VkDescriptorPoolCreateInfo pool_create_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr, 0, max_descriptor_sets, + static_cast(pool_sizes.size()), pool_sizes.data(), + }; - VkDescriptorSet descriptor_set; - VkResult res = - vkAllocateDescriptorSets(g_vulkan_context->GetDevice(), &allocate_info, &descriptor_set); + VkDevice device = g_vulkan_context->GetDevice(); + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + VkResult res = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &descriptor_pool); if (res != VK_SUCCESS) { - // Failing to allocate a descriptor set is not a fatal error, we can - // recover by moving to the next command buffer. + LOG_VULKAN_ERROR(res, "vkCreateDescriptorPool failed: "); return VK_NULL_HANDLE; } + return descriptor_pool; +} + +VkDescriptorSet CommandBufferManager::AllocateDescriptorSet(VkDescriptorSetLayout set_layout) +{ + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + FrameResources& resources = GetCurrentFrameResources(); + + if (!resources.descriptor_pools.empty()) [[likely]] + { + VkDescriptorSetAllocateInfo allocate_info = { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, nullptr, + resources.descriptor_pools[resources.current_descriptor_pool_index], 1, &set_layout}; + + VkResult res = + vkAllocateDescriptorSets(g_vulkan_context->GetDevice(), &allocate_info, &descriptor_set); + if (res != VK_SUCCESS && + resources.descriptor_pools.size() > resources.current_descriptor_pool_index + 1) + { + // Mark the next descriptor set as active and try again. + resources.current_descriptor_pool_index++; + descriptor_set = AllocateDescriptorSet(set_layout); + } + } + + if (descriptor_set == VK_NULL_HANDLE) [[unlikely]] + { + VkDescriptorPool descriptor_pool = CreateDescriptorPool(DESCRIPTOR_SETS_PER_POOL); + m_descriptor_set_count += DESCRIPTOR_SETS_PER_POOL; + if (descriptor_pool == VK_NULL_HANDLE) [[unlikely]] + return VK_NULL_HANDLE; + + resources.descriptor_pools.push_back(descriptor_pool); + resources.current_descriptor_pool_index = + static_cast(resources.descriptor_pools.size()) - 1; + descriptor_set = AllocateDescriptorSet(set_layout); + } return descriptor_set; } @@ -348,11 +376,29 @@ void CommandBufferManager::SubmitCommandBuffer(bool submit_on_worker_thread, cmd_buffer_index = (cmd_buffer_index + 1) % NUM_COMMAND_BUFFERS; } - // Reset the descriptor pool - VkResult res = - vkResetDescriptorPool(g_vulkan_context->GetDevice(), GetCurrentDescriptorPool(), 0); - if (res != VK_SUCCESS) - LOG_VULKAN_ERROR(res, "vkResetDescriptorPool failed: "); + // Reset the descriptor pools + FrameResources& frame_resources = GetCurrentFrameResources(); + + if (frame_resources.descriptor_pools.size() == 1) [[likely]] + { + VkResult res = vkResetDescriptorPool(g_vulkan_context->GetDevice(), + frame_resources.descriptor_pools[0], 0); + if (res != VK_SUCCESS) + LOG_VULKAN_ERROR(res, "vkResetDescriptorPool failed: "); + } + else [[unlikely]] + { + for (VkDescriptorPool descriptor_pool : frame_resources.descriptor_pools) + { + vkDestroyDescriptorPool(g_vulkan_context->GetDevice(), descriptor_pool, nullptr); + } + frame_resources.descriptor_pools.clear(); + VkDescriptorPool descriptor_pool = CreateDescriptorPool(m_descriptor_set_count); + if (descriptor_pool != VK_NULL_HANDLE) [[likely]] + frame_resources.descriptor_pools.push_back(descriptor_pool); + } + + frame_resources.current_descriptor_pool_index = 0; } // Switch to next cmdbuffer. -- cgit v1.2.3