diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index b219745f6a..c73e3c2d11 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -7,6 +7,7 @@ #include "Common/unordered_map.hpp" #include "Emu/System.h" #include "Emu/cache_utils.hpp" +#include "Emu/Memory/vm.h" #include "Emu/RSX/Program/RSXVertexProgram.h" #include "Emu/RSX/Program/RSXFragmentProgram.h" #include "Overlays/Shaders/shader_loading_dialog.h" @@ -478,6 +479,7 @@ namespace rsx uptr local_address; u32 offset_in_heap; u32 data_length; + u64 fingerprint; }; // A weak vertex cache with no data checks or memory range locks @@ -502,11 +504,19 @@ namespace rsx { const auto key = hash(local_addr, data_length); const auto found = vertex_ranges.find(key); + if (found == vertex_ranges.end()) { return nullptr; } + // Check if data in local_address changed vs what was stored in the vertex_cache + if (auto sudo_ptr = vm::get_super_ptr(local_addr); + data_length >= 8 && found->second.fingerprint != *utils::bless(sudo_ptr)) + { + vertex_ranges.erase(key); + return nullptr; + } return std::addressof(found->second); } @@ -516,7 +526,15 @@ namespace rsx v.data_length = data_length; v.local_address = local_addr; v.offset_in_heap = offset_in_heap; + v.fingerprint = 0; + if (data_length >= 8) + { + // Uses get_super_ptr to access vm memory safely + // and bless to avoid endian conversion and circumvent compiler strict aliasing rules. + auto sudo_ptr = vm::get_super_ptr(local_addr); + v.fingerprint = *utils::bless(sudo_ptr); + } const auto key = hash(local_addr, data_length); vertex_ranges[key] = v; }