From 5d1b7eb9454fc69aee47c8b157cbcec08463a845 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 20 Aug 2019 23:22:21 +0300 Subject: [PATCH] rsx: Fix reference leaks in texture_cache<->surface_cache communication - Properly commit orphaned blocks not invalidating existing cache structures - Do not ignore overwritten objects when commiting as unprotected fbo. Avoids stale references to invalidated surface objects. --- rpcs3/Emu/RSX/Common/texture_cache.h | 2 +- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 58 ++++++++++++++-------------- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 50 ++++++++++++------------ 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 782666426b..ba9beeec64 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -853,7 +853,7 @@ namespace rsx (invalidation_ignore_unsynchronized && tex.is_flushable() && (cause.skip_flush() || !tex.is_synchronized()) && !overlaps_fault_range) || // HACK: When being superseded by an fbo, we preserve other overlapped fbos unless the start addresses match // If region is committed as fbo, all non-fbo data is removed but all fbos in the region must be preserved if possible - (overlaps_fault_range && tex.get_context() == texture_upload_context::framebuffer_storage && cause.skip_fbos() && (tex.get_section_base() != fault_range_in.start || cause == invalidation_cause::committed_as_fbo)) + (overlaps_fault_range && tex.get_context() == texture_upload_context::framebuffer_storage && cause.skip_fbos() && tex.get_section_base() != fault_range_in.start) ) { // False positive diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index ce5c1dd8e1..d2a089b63a 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -365,38 +365,40 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk if (!m_rtts.orphaned_surfaces.empty()) { - if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer) + gl::texture::format format; + gl::texture::type type; + bool swap_bytes; + + for (auto& surface : m_rtts.orphaned_surfaces) { - gl::texture::format format; - gl::texture::type type; - bool swap_bytes; + const bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer : + !!g_cfg.video.write_color_buffers; - for (auto& surface : m_rtts.orphaned_surfaces) + if (LIKELY(!lock)) { - if (surface->is_depth_surface()) - { - if (!g_cfg.video.write_depth_buffer) continue; - - const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(surface->get_surface_depth_format()); - format = depth_format_gl.format; - type = depth_format_gl.type; - swap_bytes = (type != gl::texture::type::uint_24_8); - } - else - { - if (!g_cfg.video.write_color_buffers) continue; - - const auto color_format_gl = rsx::internals::surface_color_format_to_gl(surface->get_surface_color_format()); - format = color_format_gl.format; - type = color_format_gl.type; - swap_bytes = color_format_gl.swap_bytes; - } - - m_gl_texture_cache.lock_memory_region( - cmd, surface, surface->get_memory_range(), false, - surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), - format, type, swap_bytes); + m_gl_texture_cache.commit_framebuffer_memory_region(cmd, surface->get_memory_range()); + continue; } + + if (surface->is_depth_surface()) + { + const auto depth_format_gl = rsx::internals::surface_depth_format_to_gl(surface->get_surface_depth_format()); + format = depth_format_gl.format; + type = depth_format_gl.type; + swap_bytes = (type != gl::texture::type::uint_24_8); + } + else + { + const auto color_format_gl = rsx::internals::surface_color_format_to_gl(surface->get_surface_color_format()); + format = color_format_gl.format; + type = color_format_gl.type; + swap_bytes = color_format_gl.swap_bytes; + } + + m_gl_texture_cache.lock_memory_region( + cmd, surface, surface->get_memory_range(), false, + surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), + format, type, swap_bytes); } m_rtts.orphaned_surfaces.clear(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index be391dd13b..aa6ec8b93d 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2927,34 +2927,36 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) if (!m_rtts.orphaned_surfaces.empty()) { - if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer) + u32 gcm_format; + bool swap_bytes; + + for (auto& surface : m_rtts.orphaned_surfaces) { - u32 gcm_format; - bool swap_bytes; + const bool lock = surface->is_depth_surface() ? !!g_cfg.video.write_depth_buffer : + !!g_cfg.video.write_color_buffers; - for (auto& surface : m_rtts.orphaned_surfaces) + if (LIKELY(!lock)) { - if (surface->is_depth_surface()) - { - if (!g_cfg.video.write_depth_buffer) continue; - - gcm_format = (surface->get_surface_depth_format() != rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8; - swap_bytes = true; - } - else - { - if (!g_cfg.video.write_color_buffers) continue; - - auto info = get_compatible_gcm_format(surface->get_surface_color_format()); - gcm_format = info.first; - swap_bytes = info.second; - } - - m_texture_cache.lock_memory_region( - *m_current_command_buffer, surface, surface->get_memory_range(), false, - surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), - gcm_format, swap_bytes); + m_texture_cache.commit_framebuffer_memory_region(*m_current_command_buffer, surface->get_memory_range()); + continue; } + + if (surface->is_depth_surface()) + { + gcm_format = (surface->get_surface_depth_format() != rsx::surface_depth_format::z16) ? CELL_GCM_TEXTURE_DEPTH16 : CELL_GCM_TEXTURE_DEPTH24_D8; + swap_bytes = true; + } + else + { + auto info = get_compatible_gcm_format(surface->get_surface_color_format()); + gcm_format = info.first; + swap_bytes = info.second; + } + + m_texture_cache.lock_memory_region( + *m_current_command_buffer, surface, surface->get_memory_range(), false, + surface->get_surface_width(rsx::surface_metrics::pixels), surface->get_surface_height(rsx::surface_metrics::pixels), surface->get_rsx_pitch(), + gcm_format, swap_bytes); } m_rtts.orphaned_surfaces.clear();