diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index cc9aed284d..a18c25d2ca 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -374,6 +374,7 @@ namespace rsx auto &object = storage[e.first]; ensure(object); + if (!surface->old_contents.empty()) [[unlikely]] { surface->read_barrier(cmd); diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 6a58028256..24e5712d7d 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -515,6 +515,34 @@ namespace rsx } } + // Resync any exclusions that do not require flushing + std::vector surfaces_to_inherit; + for (auto& surface : data.sections_to_exclude) + { + if (surface->get_context() != texture_upload_context::framebuffer_storage) + { + continue; + } + + // Check for any 'newer' flushed overlaps. Memory must be re-acquired to avoid holding stale contents + // Note that the surface cache inheritance will minimize the impact + surfaces_to_inherit.clear(); + + for (auto& flushed_surface : data.sections_to_flush) + { + if (flushed_surface->get_context() != texture_upload_context::framebuffer_storage || + flushed_surface->last_write_tag <= surface->last_write_tag || + !flushed_surface->get_confirmed_range().overlaps(surface->get_confirmed_range())) + { + continue; + } + + surfaces_to_inherit.push_back(flushed_surface); + } + + surface->sync_surface_memory(surfaces_to_inherit); + } + data.flushed = true; } diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index cbf04807c4..772b7ee21b 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -350,6 +350,17 @@ namespace gl baseclass::on_section_resources_destroyed(); } + void sync_surface_memory(const std::vector& surfaces) + { + auto rtt = gl::as_rtt(vram_texture); + rtt->sync_tag(); + + for (auto& surface : surfaces) + { + rtt->inherit_surface_contents(gl::as_rtt(surface->vram_texture)); + } + } + bool exists() const { return (vram_texture != nullptr); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index a3108cf6bd..db1bef53c7 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -321,6 +321,17 @@ namespace vk rsx_pitch = pitch; } + void sync_surface_memory(const std::vector& surfaces) + { + auto rtt = vk::as_rtt(vram_texture); + rtt->sync_tag(); + + for (auto& surface : surfaces) + { + rtt->inherit_surface_contents(vk::as_rtt(surface->vram_texture)); + } + } + bool is_synchronized() const { return synchronized;