From daaa83b9ca9f769b0083014486b4ca2c843bff72 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Fri, 3 Nov 2017 17:17:39 +0300 Subject: [PATCH] rsx: Fix for framebuffer validation --- rpcs3/Emu/RSX/Common/texture_cache.h | 58 ++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 6bda216bb6..1fe28601db 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -207,19 +207,30 @@ namespace rsx private: //Internal implementation methods and helpers - utils::protection get_memory_protection(u32 address) + std::pair get_memory_protection(u32 address) { auto found = m_cache.find(get_block_address(address)); if (found != m_cache.end()) { - for (const auto &tex : found->second.data) + for (auto &tex : found->second.data) { if (tex.is_locked() && tex.overlaps(address, false)) - return tex.get_protection(); + return{ tex.get_protection(), &tex }; } } - return utils::protection::rw; + //Get the preceding block and check if any hits are found + found = m_cache.find(get_block_address(address) - get_block_size()); + if (found != m_cache.end()) + { + for (auto &tex : found->second.data) + { + if (tex.is_locked() && tex.overlaps(address, false)) + return{ tex.get_protection(), &tex }; + } + } + + return{ utils::protection::rw, nullptr }; } inline bool region_intersects_cache(u32 address, u32 range, bool is_writing) const @@ -1379,12 +1390,26 @@ namespace rsx if (!g_cfg.video.strict_rendering_mode) return; - switch (get_memory_protection(texaddr)) + writer_lock lock(m_cache_mutex); + + const auto protect_info = get_memory_protection(texaddr); + if (protect_info.first != utils::protection::rw) { - case utils::protection::no: - return; - case utils::protection::ro: - LOG_ERROR(RSX, "Framebuffer memory occupied by regular texture!"); + if (protect_info.second->overlaps(texaddr, true)) + { + if (protect_info.first == utils::protection::no) + return; + + if (protect_info.second->get_context() != texture_upload_context::blit_engine_dst) + { + //TODO: Invalidate this section + LOG_TRACE(RSX, "Framebuffer memory occupied by regular texture!"); + } + } + + protect_info.second->unprotect(); + vm::ps3::write32(texaddr, texaddr); + protect_info.second->protect(protect_info.first); return; } @@ -1398,8 +1423,19 @@ namespace rsx if (g_cfg.video.write_color_buffers || g_cfg.video.write_depth_buffer) { - if (get_memory_protection(texaddr) == utils::protection::no) - return true; + writer_lock lock(m_cache_mutex); + auto protect_info = get_memory_protection(texaddr); + if (protect_info.first == utils::protection::no) + { + if (protect_info.second->overlaps(texaddr, true)) + return true; + + //Address isnt actually covered by the region, it only shares a page with it + protect_info.second->unprotect(); + bool result = (vm::ps3::read32(texaddr) == texaddr); + protect_info.second->protect(utils::protection::no); + return result; + } } return vm::ps3::read32(texaddr) == texaddr;