From 6a9d1edee17248ef14d64e3cf96eb5050ad144dc Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 23 Jul 2021 20:15:07 +0300 Subject: [PATCH] vk: Fix use-after-free hazard by checking if we're faulting from within the texture cache - If we're using the texture cache, DO NOT delete resources. --- rpcs3/Emu/RSX/Common/texture_cache.h | 12 +++++++++++- rpcs3/Emu/RSX/VK/VKTextureCache.cpp | 10 +++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index c43a605a44..9950be5056 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -1455,8 +1455,16 @@ namespace rsx bool evict_unused(const std::set& exclusion_list) { - // Manage synchronization externally. It is very likely for RSX to call this after failing to create a new texture while already owning the mutex + // Some sanity checks. Do not evict if the cache is currently in use. ensure(rsx::get_current_renderer()->is_current_thread()); + std::unique_lock lock(m_cache_mutex, std::defer_lock); + + if (!lock.try_lock()) + { + rsx_log.warning("Unable to evict the texture cache because we're faulting from within in the texture cache!"); + return false; + } + rsx_log.warning("[PERFORMANCE WARNING] Texture cache is running eviction routine. This will affect performance."); thrashed_set evicted_set; @@ -1523,7 +1531,9 @@ namespace rsx } } + std::lock_guard lock(m_cache_mutex); image_view_type result = 0; + switch (desc.op) { case deferred_request_command::cubemap_gather: diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp index 1b731e8da9..b9c2c055f7 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.cpp +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.cpp @@ -1094,8 +1094,9 @@ namespace vk bool texture_cache::handle_memory_pressure(rsx::problem_severity severity) { - bool any_released = baseclass::handle_memory_pressure(severity); + auto any_released = baseclass::handle_memory_pressure(severity); + // TODO: This can cause invalidation of in-flight resources if (severity <= rsx::problem_severity::low || !m_temporary_memory_size) { // Nothing left to do @@ -1109,6 +1110,13 @@ namespace vk return any_released; } + std::unique_lock lock(m_cache_mutex, std::defer_lock); + if (!lock.try_lock()) + { + rsx_log.warning("Unable to remove temporary resources because we're already in the texture cache!"); + return any_released; + } + // Nuke temporary resources. They will still be visible to the GPU. auto gc = vk::get_resource_manager(); u64 actual_released_memory = 0;