From 9a2b06f35fdae8b78387dcfe2d46f0f2d874a9d4 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 13 May 2023 02:31:18 +0300 Subject: [PATCH] vk: Refactor vram exhausted handler to minimize risk of UAF hazards 1. A hard sync before starting the routines on fatal will release some memory going in improving chances of a successful eviction elsewhere. 2. A hard sync on exit cleans up, ensuring no UAF (with caveats) --- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 41 +++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 37bd3327ae..fd9d938a14 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1083,28 +1083,35 @@ bool VKGSRender::on_vram_exhausted(rsx::problem_severity severity) ensure(!vk::is_uninterruptible() && rsx::get_current_renderer()->is_current_thread()); bool texture_cache_relieved = false; - if (severity >= rsx::problem_severity::fatal && m_texture_cache.is_overallocated()) + if (severity >= rsx::problem_severity::fatal) { - // Evict some unused textures. Do not evict any active references - std::set exclusion_list; - auto scan_array = [&](const auto& texture_array) + // Hard sync before trying to evict anything. This guarantees no UAF crashes in the driver. + // As a bonus, we also get a free gc pass + flush_command_queue(true, true); + + if (m_texture_cache.is_overallocated()) { - for (auto i = 0ull; i < texture_array.size(); ++i) + // Evict some unused textures. Do not evict any active references + std::set exclusion_list; + auto scan_array = [&](const auto& texture_array) { - const auto& tex = texture_array[i]; - const auto addr = rsx::get_address(tex.offset(), tex.location()); - exclusion_list.insert(addr); - } - }; + for (auto i = 0ull; i < texture_array.size(); ++i) + { + const auto& tex = texture_array[i]; + const auto addr = rsx::get_address(tex.offset(), tex.location()); + exclusion_list.insert(addr); + } + }; - scan_array(rsx::method_registers.fragment_textures); - scan_array(rsx::method_registers.vertex_textures); + scan_array(rsx::method_registers.fragment_textures); + scan_array(rsx::method_registers.vertex_textures); - // Hold the secondary lock guard to prevent threads from trying to touch access violation handler stuff - std::lock_guard lock(m_secondary_cb_guard); + // Hold the secondary lock guard to prevent threads from trying to touch access violation handler stuff + std::lock_guard lock(m_secondary_cb_guard); - rsx_log.warning("Texture cache is overallocated. Will evict unnecessary textures."); - texture_cache_relieved = m_texture_cache.evict_unused(exclusion_list); + rsx_log.warning("Texture cache is overallocated. Will evict unnecessary textures."); + texture_cache_relieved = m_texture_cache.evict_unused(exclusion_list); + } } texture_cache_relieved |= m_texture_cache.handle_memory_pressure(severity); @@ -1160,7 +1167,7 @@ bool VKGSRender::on_vram_exhausted(rsx::problem_severity severity) } const bool any_cache_relieved = (texture_cache_relieved || surface_cache_relieved); - if (any_cache_relieved && severity >= rsx::problem_severity::fatal) + if (severity >= rsx::problem_severity::fatal) { // Imminent crash, full GPU sync is the least of our problems flush_command_queue(true, true);