diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index accf1791ea..7f4b907c52 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -61,6 +61,9 @@ namespace rsx // List of sections derived from a section that has been split and invalidated std::vector orphaned_surfaces; + // List of sections that have been wholly inherited and invalidated + std::vector superseded_surfaces; + std::list invalidated_resources; u64 cache_tag = 1ull; // Use 1 as the start since 0 is default tag on new surfaces u64 write_tag = 1ull; @@ -410,6 +413,7 @@ namespace rsx invalidate(object); storage.erase(e.first); + superseded_surfaces.push_back(surface); } } } diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index d87ef4aa65..6211ad6649 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -753,14 +753,6 @@ namespace rsx tex.is_flushable() && tex.get_section_base() != fault_range_in.start) { - if (tex.get_context() == texture_upload_context::framebuffer_storage && - tex.inside(fault_range, section_bounds::full_range)) - { - // FBO data 'lives on' in the new region. Surface cache handles memory intersection for us. - verify(HERE), tex.inside(fault_range, section_bounds::locked_range); - tex.discard(false); - } - // HACK: When being superseded by an fbo, we preserve overlapped flushables unless the start addresses match continue; } @@ -1174,6 +1166,20 @@ namespace rsx invalidate_range_impl_base(cmd, rsx_range, invalidation_cause::committed_as_fbo, std::forward(extras)...); } + template + void discard_framebuffer_memory_region(commandbuffer_type& cmd, const address_range& rsx_range, Args&&... extras) + { + if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer) + { + auto* region_ptr = find_cached_texture(rsx_range, RSX_GCM_FORMAT_IGNORED, false, false); + if (region_ptr && region_ptr->is_locked() && region_ptr->get_context() == texture_upload_context::framebuffer_storage) + { + verify(HERE), region_ptr->get_protection() == utils::protection::no; + region_ptr->discard(false); + } + } + } + void set_memory_read_flags(const address_range &memory_range, memory_read_flags flags) { std::lock_guard lock(m_cache_mutex); diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 07646e0965..e0c90bbe0f 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -329,6 +329,16 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool sk m_gl_texture_cache.clear_ro_tex_invalidate_intr(); + if (!m_rtts.superseded_surfaces.empty()) + { + for (auto& surface : m_rtts.superseded_surfaces) + { + m_gl_texture_cache.discard_framebuffer_memory_region(cmd, surface->get_memory_range()); + } + + m_rtts.superseded_surfaces.clear(); + } + const auto color_format = rsx::internals::surface_color_format_to_gl(m_framebuffer_layout.color_format); for (u8 i = 0; i < rsx::limits::color_buffers_count; ++i) {