From 04fb86556ac7d2214e7611e4c26de9915e940539 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 17 Dec 2022 14:19:19 +0300 Subject: [PATCH] rsx: Fix surface metadata life-cycle - Beware of clone operations. Blindly inheriting the parent's metadata is wrong. - It is possible, especially when reusing a pre-existing slice, that the parent and child info has diverged --- Utilities/stack_trace.h | 30 ++++++++++++++++++++++++++-- rpcs3/Emu/RSX/Common/surface_utils.h | 16 +++++++++++++++ rpcs3/Emu/RSX/Common/texture_cache.h | 1 + rpcs3/Emu/RSX/GL/GLRenderTargets.h | 8 ++------ rpcs3/Emu/RSX/VK/VKRenderTargets.h | 8 ++------ 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/Utilities/stack_trace.h b/Utilities/stack_trace.h index b1077bcd42..f57175611f 100644 --- a/Utilities/stack_trace.h +++ b/Utilities/stack_trace.h @@ -4,17 +4,43 @@ namespace utils { + namespace stack_trace + { + // Printing utilities + + template + concept Logger = requires (T& t, const std::string& msg) + { + { t.print(msg) }; + }; + + struct print_to_log + { + logs::channel& log; + + public: + print_to_log(logs::channel& chan) + : log(chan) + {} + + void print(const std::string& s) + { + log.error("%s", s); + } + }; + } + std::vector get_backtrace(int max_depth = 255); std::vector get_backtrace_symbols(const std::vector& stack); - FORCE_INLINE void print_trace(logs::channel& logger, int max_depth = 255) + FORCE_INLINE void print_trace(stack_trace::Logger auto& logger, int max_depth = 255) { const auto trace = get_backtrace(max_depth); const auto lines = get_backtrace_symbols(trace); for (const auto& line : lines) { - logger.error("%s", line); + logger.print(line); } } } diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index 0ffa1e9009..7b2b251fcf 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -392,6 +392,9 @@ namespace rsx ensure(native_pitch); ensure(rsx_pitch); + // Clear metadata + reset(); + base_addr = address; const u32 size_x = (native_pitch > 8)? (native_pitch - 8) : 0u; @@ -746,6 +749,19 @@ namespace rsx } } + void on_clone_from(const render_target_descriptor* ref) + { + if (ref->is_locked() && !is_locked()) + { + // Propagate locked state only. + texture_cache_metadata = ref->texture_cache_metadata; + } + + rsx_pitch = ref->get_rsx_pitch(); + last_use_tag = ref->last_use_tag; + raster_type = ref->raster_type; // Can't actually cut up swizzled data + } + bool is_locked() const { return texture_cache_metadata.locked; diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 7717015c48..02cf355fb0 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -583,6 +583,7 @@ namespace rsx } data.flushed = true; + update_cache_tag(); } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index adbc2d7d0d..3650076c98 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -215,7 +215,7 @@ struct gl_render_target_traits sink->queue_tag(address); } - prev.target = sink.get(); + sink->on_clone_from(ref); if (!sink->old_contents.empty()) { @@ -230,11 +230,8 @@ struct gl_render_target_traits } } - sink->set_rsx_pitch(ref->get_rsx_pitch()); + prev.target = sink.get(); sink->set_old_contents_region(prev, false); - sink->texture_cache_metadata = ref->texture_cache_metadata; - sink->last_use_tag = ref->last_use_tag; - sink->raster_type = ref->raster_type; // Can't actually cut up swizzled data } static @@ -294,7 +291,6 @@ struct gl_render_target_traits } surface->release(); - surface->reset(); } static diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index e340d493cb..18a2c1e064 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -325,7 +325,7 @@ namespace vk sink->change_layout(cmd, best_layout); } - prev.target = sink.get(); + sink->on_clone_from(ref); if (!sink->old_contents.empty()) { @@ -340,11 +340,8 @@ namespace vk } } - sink->rsx_pitch = ref->get_rsx_pitch(); + prev.target = sink.get(); sink->set_old_contents_region(prev, false); - sink->texture_cache_metadata = ref->texture_cache_metadata; - sink->last_use_tag = ref->last_use_tag; - sink->raster_type = ref->raster_type; // Can't actually cut up swizzled data } static std::unique_ptr convert_pitch( @@ -416,7 +413,6 @@ namespace vk } surface->release(); - surface->reset(); } static void notify_surface_persist(const std::unique_ptr& /*surface*/)