From b8fcbb68b03fe888b4d748b73d642f043dd24714 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 1 Mar 2017 00:15:57 +0300 Subject: [PATCH] gl/vk/cache: Fix invalidating intersecting and overlapping memory regions whitespace fix --- rpcs3/Emu/RSX/GL/GLTextureCache.h | 36 ++++++++++++++++++++++++++----- rpcs3/Emu/RSX/VK/VKTextureCache.h | 23 +++++++++++++++----- rpcs3/Emu/RSX/rsx_cache.h | 18 ++++++++++++++++ 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index 96ddcfe40e..8df1b616ec 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -776,18 +776,33 @@ namespace gl bool mark_as_dirty(u32 address) { bool response = false; + std::pair trampled_range = std::make_pair(0xffffffff, 0x0); + + //TODO: Optimize this function! + //Multi-pass checking is slow. Pre-calculate dependency tree at section creation if (address >= texture_cache_range.first && address < texture_cache_range.second) { std::lock_guard lock(m_section_mutex); - for (cached_texture_section &tex : m_texture_cache) + for (int i = 0; i < m_texture_cache.size(); ++i) { + auto &tex = m_texture_cache[i]; if (!tex.is_locked()) continue; - if (tex.overlaps(address)) + auto overlapped = tex.overlaps_page(trampled_range, address); + if (std::get<0>(overlapped)) { + auto &new_range = std::get<1>(overlapped); + + if (new_range.first != trampled_range.first || + new_range.second != trampled_range.second) + { + trampled_range = new_range; + i = 0; + } + tex.unprotect(); tex.set_dirty(true); @@ -801,12 +816,23 @@ namespace gl { std::lock_guard lock(m_section_mutex); - for (cached_rtt_section &rtt : m_rtt_cache) + for (int i = 0; i < m_rtt_cache.size(); ++i) { - if (rtt.is_dirty()) continue; + auto &rtt = m_rtt_cache[i]; + if (rtt.is_dirty() || !rtt.is_locked()) continue; - if (rtt.is_locked() && rtt.overlaps(address)) + auto overlapped = rtt.overlaps_page(trampled_range, address); + if (std::get<0>(overlapped)) { + auto &new_range = std::get<1>(overlapped); + + if (new_range.first != trampled_range.first || + new_range.second != trampled_range.second) + { + trampled_range = new_range; + i = 0; + } + rtt.unprotect(); rtt.set_dirty(true); diff --git a/rpcs3/Emu/RSX/VK/VKTextureCache.h b/rpcs3/Emu/RSX/VK/VKTextureCache.h index 611116aabc..dda52c0416 100644 --- a/rpcs3/Emu/RSX/VK/VKTextureCache.h +++ b/rpcs3/Emu/RSX/VK/VKTextureCache.h @@ -270,20 +270,33 @@ namespace vk return view; } - bool invalidate_address(u32 rsx_address) + bool invalidate_address(u32 address) { - if (rsx_address < texture_cache_range.first || - rsx_address > texture_cache_range.second) + if (address < texture_cache_range.first || + address > texture_cache_range.second) return false; bool response = false; + std::pair trampled_range = std::make_pair(0xffffffff, 0x0); - for (auto &tex : m_cache) + for (int i = 0; i < m_cache.size(); ++i) { + auto &tex = m_cache[i]; + if (tex.is_dirty()) continue; - if (tex.overlaps(rsx_address)) + auto overlapped = tex.overlaps_page(trampled_range, address); + if (std::get<0>(overlapped)) { + auto &new_range = std::get<1>(overlapped); + + if (new_range.first != trampled_range.first || + new_range.second != trampled_range.second) + { + trampled_range = new_range; + i = 0; + } + tex.set_dirty(true); tex.unprotect(); diff --git a/rpcs3/Emu/RSX/rsx_cache.h b/rpcs3/Emu/RSX/rsx_cache.h index f7bdc32720..8fa2954cbf 100644 --- a/rpcs3/Emu/RSX/rsx_cache.h +++ b/rpcs3/Emu/RSX/rsx_cache.h @@ -163,6 +163,24 @@ namespace rsx return (locked_address_base <= address && (address - locked_address_base) < locked_address_range); } + /** + * Check if the page containing the address tramples this section. Also compares a former trampled page range to compare + * If true, returns the range with updated invalid range + */ + std::tuple> overlaps_page(std::pair old_range, u32 address) + { + const u32 page_base = address & ~4095; + const u32 page_limit = address + 4096; + + const u32 compare_min = std::min(old_range.first, page_base); + const u32 compare_max = std::max(old_range.second, page_limit); + + if (!region_overlaps(locked_address_base, locked_address_base + locked_address_range, compare_min, compare_max)) + return std::make_tuple(false, old_range); + + return std::make_tuple(true, get_min_max(std::make_pair(compare_min, compare_max))); + } + bool is_locked() const { return locked;