From 8e370c2cf10bc56d1b3a812bc22797e954168f05 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 5 Jun 2026 03:32:03 +0300 Subject: [PATCH] rsx/vk: Implement auto-scaling of descriptor pool sizes --- rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp | 2 +- rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp | 62 +++++++++++++++++++----- rpcs3/Emu/RSX/VK/vkutils/descriptors.h | 21 ++++++-- 3 files changed, 68 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp index ba7e4add41..48874f55d0 100644 --- a/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp +++ b/rpcs3/Emu/RSX/VK/VKProgramPipeline.cpp @@ -696,7 +696,7 @@ namespace vk void descriptor_table_t::create_descriptor_pool() { m_descriptor_pool = std::make_unique(); - m_descriptor_pool->create(*vk::g_render_device, m_descriptor_pool_sizes); + m_descriptor_pool->create(*vk::g_render_device, m_descriptor_pool_sizes, 16u, 4096u); } void descriptor_table_t::validate() const diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp index 4152e4b83a..666934dc49 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.cpp @@ -110,18 +110,15 @@ namespace vk } } - void descriptor_pool::create(const vk::render_device& dev, const rsx::simple_array& pool_sizes, u32 max_sets) + void descriptor_pool::create(const vk::render_device& dev, const rsx::simple_array& pool_sizes, u32 min_sets, u32 max_sets) { - ensure(max_sets > 16); + m_autoscaling_config.min_pool_size = std::max(min_sets, 16u); + m_autoscaling_config.max_pool_size = std::max(min_sets, max_sets); + + ensure(m_autoscaling_config.max_pool_size >= 16u); m_create_info_pool_sizes = pool_sizes; - for (auto& size : m_create_info_pool_sizes) - { - ensure(size.descriptorCount < 128); // Sanity check. Remove before commit. - size.descriptorCount *= max_sets; - } - m_create_info.flags = dev.get_descriptor_update_after_bind_support() ? VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT : 0; m_create_info.maxSets = max_sets; m_create_info.poolSizeCount = m_create_info_pool_sizes.size(); @@ -186,7 +183,7 @@ namespace vk if (use_cache) { - const auto alloc_size = std::min(m_create_info.maxSets - m_current_subpool_offset, max_cache_size); + const auto alloc_size = std::min(max_sets() - m_current_subpool_offset, max_cache_size); m_allocation_request_cache.resize(alloc_size); for (auto& layout_ : m_allocation_request_cache) { @@ -243,8 +240,8 @@ namespace vk } } - VkDescriptorPool subpool = VK_NULL_HANDLE; - if (VkResult result = vkCreateDescriptorPool(*m_owner, &m_create_info, nullptr, &subpool)) + const auto [result, subpool] = new_subpool(); + if (result != VK_SUCCESS) { if (retries-- && (result == VK_ERROR_FRAGMENTATION_EXT)) { @@ -263,6 +260,7 @@ namespace vk m_device_subpools.push_back( { .handle = subpool, + .size = m_autoscaling_config.current_size, .busy = VK_FALSE }); @@ -275,6 +273,48 @@ namespace vk m_current_pool_handle = m_device_subpools[m_current_subpool_index].handle; } + std::pair descriptor_pool::new_subpool() + { + // Try autoscaling + u32 set_count = m_autoscaling_config.current_size; + if (set_count < m_autoscaling_config.min_pool_size) + { + set_count = m_autoscaling_config.min_pool_size; + } + else if (set_count < m_autoscaling_config.max_pool_size) + { + // Scale up + set_count = std::min(m_autoscaling_config.max_pool_size, set_count * 2u); + } + + // Configure request using current pool size + auto descriptor_pool_sizes = m_create_info_pool_sizes.map([set_count](const VkDescriptorPoolSize& pool_size_info) + { + auto ret = pool_size_info; + ret.descriptorCount *= set_count; + return ret; + }); + + m_create_info.maxSets = set_count; + m_create_info.poolSizeCount = descriptor_pool_sizes.size(); + m_create_info.pPoolSizes = descriptor_pool_sizes.data(); + + VkDescriptorPool subpool = VK_NULL_HANDLE; + VkResult result = vkCreateDescriptorPool(*m_owner, &m_create_info, nullptr, &subpool); + + if (result == VK_SUCCESS) + { + // Commit autoscaling + m_autoscaling_config.current_size = set_count; + } + + // Cleanup + m_create_info.pPoolSizes = nullptr; + m_create_info.poolSizeCount = 0; + + return { result, subpool }; + } + descriptor_set::descriptor_set(VkDescriptorSet set) { flush(); diff --git a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h index 93ac8345e0..3fb0948862 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/descriptors.h +++ b/rpcs3/Emu/RSX/VK/vkutils/descriptors.h @@ -39,28 +39,39 @@ namespace vk descriptor_pool() = default; ~descriptor_pool() = default; - void create(const vk::render_device& dev, const rsx::simple_array& pool_sizes, u32 max_sets = 1024); + void create(const vk::render_device& dev, const rsx::simple_array& pool_sizes, u32 min_sets = 1024, u32 max_sets = 1024); void destroy(); VkDescriptorSet allocate(VkDescriptorSetLayout layout, VkBool32 use_cache = VK_TRUE); operator VkDescriptorPool() { return m_current_pool_handle; } FORCE_INLINE bool valid() const { return !m_device_subpools.empty(); } - FORCE_INLINE u32 max_sets() const { return m_create_info.maxSets; } + FORCE_INLINE u32 max_sets() const { return m_current_subpool_index >= m_device_subpools.size() ? 0u : m_device_subpools[m_current_subpool_index].size; } private: - FORCE_INLINE bool can_allocate(u32 required_count, u32 already_used_count = 0) const { return (required_count + already_used_count) <= m_create_info.maxSets; }; + FORCE_INLINE bool can_allocate(u32 required_count, u32 already_used_count = 0) const { return (required_count + already_used_count) <= max_sets(); }; void reset(u32 subpool_id, VkDescriptorPoolResetFlags flags); void next_subpool(); + std::pair new_subpool(); + struct logical_subpool_t { - VkDescriptorPool handle; - VkBool32 busy; + VkDescriptorPool handle = VK_NULL_HANDLE; + u32 size = 0; + VkBool32 busy = VK_FALSE; + }; + + struct autoscaling_config_t + { + u32 min_pool_size = 0; + u32 max_pool_size = 0; + u32 current_size = 0; }; const vk::render_device* m_owner = nullptr; VkDescriptorPoolCreateInfo m_create_info = {}; + autoscaling_config_t m_autoscaling_config = {}; rsx::simple_array m_create_info_pool_sizes; rsx::simple_array m_device_subpools;