vk: Handle VK_ERROR_FRAGMENTATION when allocating descriptor pools

This commit is contained in:
kd-11 2023-06-12 23:31:13 +03:00 committed by kd-11
commit c1d875d841
5 changed files with 41 additions and 3 deletions

View file

@ -1202,6 +1202,12 @@ bool VKGSRender::on_vram_exhausted(rsx::problem_severity severity)
return any_cache_relieved; return any_cache_relieved;
} }
void VKGSRender::on_descriptor_pool_fragmentation()
{
// Just flush everything. Unless the hardware is very deficient, this should happen very rarely.
flush_command_queue(true, true);
}
void VKGSRender::notify_tile_unbound(u32 tile) void VKGSRender::notify_tile_unbound(u32 tile)
{ {
//TODO: Handle texture writeback //TODO: Handle texture writeback

View file

@ -263,6 +263,9 @@ public:
// External callback to handle out of video memory problems // External callback to handle out of video memory problems
bool on_vram_exhausted(rsx::problem_severity severity); bool on_vram_exhausted(rsx::problem_severity severity);
// Handle pool creation failure due to fragmentation
void on_descriptor_pool_fragmentation();
// Conditional rendering // Conditional rendering
void begin_conditional_rendering(const std::vector<rsx::reports::occlusion_query_info*>& sources) override; void begin_conditional_rendering(const std::vector<rsx::reports::occlusion_query_info*>& sources) override;
void end_conditional_rendering() override; void end_conditional_rendering() override;

View file

@ -268,4 +268,12 @@ namespace vk
renderer->emergency_query_cleanup(&cmd); renderer->emergency_query_cleanup(&cmd);
} }
void on_descriptor_pool_fragmentation()
{
if (auto vkthr = dynamic_cast<VKGSRender*>(rsx::get_current_renderer()))
{
vkthr->on_descriptor_pool_fragmentation();
}
}
} }

View file

@ -4,6 +4,9 @@
namespace vk namespace vk
{ {
// Error handler callback
extern void on_descriptor_pool_fragmentation();
namespace descriptors namespace descriptors
{ {
class dispatch_manager class dispatch_manager
@ -111,6 +114,7 @@ namespace vk
ensure(max_sets > 16); ensure(max_sets > 16);
m_create_info_pool_sizes = pool_sizes; m_create_info_pool_sizes = pool_sizes;
for (auto& size : m_create_info_pool_sizes) for (auto& size : m_create_info_pool_sizes)
{ {
ensure(size.descriptorCount < 128); // Sanity check. Remove before commit. ensure(size.descriptorCount < 128); // Sanity check. Remove before commit.
@ -221,8 +225,6 @@ namespace vk
vk::get_gc()->dispose(cleanup_obj); vk::get_gc()->dispose(cleanup_obj);
} }
std::lock_guard lock(m_subpool_lock);
m_current_subpool_offset = 0; m_current_subpool_offset = 0;
m_current_subpool_index = umax; m_current_subpool_index = umax;
@ -238,7 +240,23 @@ namespace vk
if (m_current_subpool_index == umax) if (m_current_subpool_index == umax)
{ {
VkDescriptorPool subpool = VK_NULL_HANDLE; VkDescriptorPool subpool = VK_NULL_HANDLE;
CHECK_RESULT(vkCreateDescriptorPool(*m_owner, &m_create_info, nullptr, &subpool));
// Only attempt recovery once. Can be bumped up if we have a more complex setup in future.
int retries = 1;
while (VkResult result = vkCreateDescriptorPool(*m_owner, &m_create_info, nullptr, &subpool))
{
if (retries-- && (result == VK_ERROR_FRAGMENTATION_EXT))
{
rsx_log.warning("Descriptor pool creation failed with fragmentation error. Will attempt to recover.");
vk::on_descriptor_pool_fragmentation();
continue;
}
vk::die_with_error(result);
}
std::lock_guard lock(m_subpool_lock);
m_device_subpools.push_back( m_device_subpools.push_back(
{ {

View file

@ -96,6 +96,9 @@ namespace vk
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR: case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR:
error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)"; error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)";
break; break;
case VK_ERROR_FRAGMENTATION_EXT:
error_message = "Descriptor pool creation failed (VK_ERROR_FRAGMENTATION)";
break;
default: default:
error_message = fmt::format("Unknown Code (%Xh, %d)%s", static_cast<s32>(error_code), static_cast<s32>(error_code), src_loc{line, col, file, func}); error_message = fmt::format("Unknown Code (%Xh, %d)%s", static_cast<s32>(error_code), static_cast<s32>(error_code), src_loc{line, col, file, func});
break; break;