rsx/vk: Implement auto-scaling of descriptor pool sizes
This commit is contained in:
@@ -696,7 +696,7 @@ namespace vk
|
|||||||
void descriptor_table_t::create_descriptor_pool()
|
void descriptor_table_t::create_descriptor_pool()
|
||||||
{
|
{
|
||||||
m_descriptor_pool = std::make_unique<descriptor_pool>();
|
m_descriptor_pool = std::make_unique<descriptor_pool>();
|
||||||
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
|
void descriptor_table_t::validate() const
|
||||||
|
|||||||
@@ -110,18 +110,15 @@ namespace vk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void descriptor_pool::create(const vk::render_device& dev, const rsx::simple_array<VkDescriptorPoolSize>& pool_sizes, u32 max_sets)
|
void descriptor_pool::create(const vk::render_device& dev, const rsx::simple_array<VkDescriptorPoolSize>& 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;
|
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.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.maxSets = max_sets;
|
||||||
m_create_info.poolSizeCount = m_create_info_pool_sizes.size();
|
m_create_info.poolSizeCount = m_create_info_pool_sizes.size();
|
||||||
@@ -186,7 +183,7 @@ namespace vk
|
|||||||
|
|
||||||
if (use_cache)
|
if (use_cache)
|
||||||
{
|
{
|
||||||
const auto alloc_size = std::min<u32>(m_create_info.maxSets - m_current_subpool_offset, max_cache_size);
|
const auto alloc_size = std::min<u32>(max_sets() - m_current_subpool_offset, max_cache_size);
|
||||||
m_allocation_request_cache.resize(alloc_size);
|
m_allocation_request_cache.resize(alloc_size);
|
||||||
for (auto& layout_ : m_allocation_request_cache)
|
for (auto& layout_ : m_allocation_request_cache)
|
||||||
{
|
{
|
||||||
@@ -243,8 +240,8 @@ namespace vk
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorPool subpool = VK_NULL_HANDLE;
|
const auto [result, subpool] = new_subpool();
|
||||||
if (VkResult result = vkCreateDescriptorPool(*m_owner, &m_create_info, nullptr, &subpool))
|
if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
if (retries-- && (result == VK_ERROR_FRAGMENTATION_EXT))
|
if (retries-- && (result == VK_ERROR_FRAGMENTATION_EXT))
|
||||||
{
|
{
|
||||||
@@ -263,6 +260,7 @@ namespace vk
|
|||||||
m_device_subpools.push_back(
|
m_device_subpools.push_back(
|
||||||
{
|
{
|
||||||
.handle = subpool,
|
.handle = subpool,
|
||||||
|
.size = m_autoscaling_config.current_size,
|
||||||
.busy = VK_FALSE
|
.busy = VK_FALSE
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -275,6 +273,48 @@ namespace vk
|
|||||||
m_current_pool_handle = m_device_subpools[m_current_subpool_index].handle;
|
m_current_pool_handle = m_device_subpools[m_current_subpool_index].handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<VkResult, VkDescriptorPool> 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)
|
descriptor_set::descriptor_set(VkDescriptorSet set)
|
||||||
{
|
{
|
||||||
flush();
|
flush();
|
||||||
|
|||||||
@@ -39,28 +39,39 @@ namespace vk
|
|||||||
descriptor_pool() = default;
|
descriptor_pool() = default;
|
||||||
~descriptor_pool() = default;
|
~descriptor_pool() = default;
|
||||||
|
|
||||||
void create(const vk::render_device& dev, const rsx::simple_array<VkDescriptorPoolSize>& pool_sizes, u32 max_sets = 1024);
|
void create(const vk::render_device& dev, const rsx::simple_array<VkDescriptorPoolSize>& pool_sizes, u32 min_sets = 1024, u32 max_sets = 1024);
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
VkDescriptorSet allocate(VkDescriptorSetLayout layout, VkBool32 use_cache = VK_TRUE);
|
VkDescriptorSet allocate(VkDescriptorSetLayout layout, VkBool32 use_cache = VK_TRUE);
|
||||||
|
|
||||||
operator VkDescriptorPool() { return m_current_pool_handle; }
|
operator VkDescriptorPool() { return m_current_pool_handle; }
|
||||||
FORCE_INLINE bool valid() const { return !m_device_subpools.empty(); }
|
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:
|
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 reset(u32 subpool_id, VkDescriptorPoolResetFlags flags);
|
||||||
void next_subpool();
|
void next_subpool();
|
||||||
|
|
||||||
|
std::pair<VkResult, VkDescriptorPool> new_subpool();
|
||||||
|
|
||||||
struct logical_subpool_t
|
struct logical_subpool_t
|
||||||
{
|
{
|
||||||
VkDescriptorPool handle;
|
VkDescriptorPool handle = VK_NULL_HANDLE;
|
||||||
VkBool32 busy;
|
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;
|
const vk::render_device* m_owner = nullptr;
|
||||||
VkDescriptorPoolCreateInfo m_create_info = {};
|
VkDescriptorPoolCreateInfo m_create_info = {};
|
||||||
|
autoscaling_config_t m_autoscaling_config = {};
|
||||||
rsx::simple_array<VkDescriptorPoolSize> m_create_info_pool_sizes;
|
rsx::simple_array<VkDescriptorPoolSize> m_create_info_pool_sizes;
|
||||||
|
|
||||||
rsx::simple_array<logical_subpool_t> m_device_subpools;
|
rsx::simple_array<logical_subpool_t> m_device_subpools;
|
||||||
|
|||||||
Reference in New Issue
Block a user