diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 9417e4d862..c31d542395 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -210,6 +210,31 @@ namespace rsx return utils::protection::rw; } + inline bool region_intersects_cache(u32 address, u32 range, bool is_writing) const + { + std::pair test_range = std::make_pair(address, address + range); + if (!is_writing) + { + if (no_access_range.first > no_access_range.second || + test_range.second < no_access_range.first || + test_range.first > no_access_range.second) + return false; + } + else + { + if (test_range.second < read_only_range.first || + test_range.first > read_only_range.second) + { + //Doesnt fall in the read_only textures range; check render targets + if (test_range.second < no_access_range.first || + test_range.first > no_access_range.second) + return false; + } + } + + return true; + } + //Get intersecting set - Returns all objects intersecting a given range and their owning blocks std::vector> get_intersecting_set(u32 address, u32 range, bool check_whole_size) { @@ -273,18 +298,23 @@ namespace rsx template thrashed_set invalidate_range_impl_base(u32 address, u32 range, bool is_writing, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras) { + if (!region_intersects_cache(address, range, is_writing)) + return {}; + auto trampled_set = get_intersecting_set(address, range, allow_flush); if (trampled_set.size() > 0) { // Rebuild the cache by only destroying ranges that need to be destroyed to unlock this page - const auto to_reprotect = !rebuild_cache? trampled_set.end() : - std::remove_if(trampled_set.begin(), trampled_set.end(), + const auto to_reprotect = std::remove_if(trampled_set.begin(), trampled_set.end(), [&](const std::pair& obj) { if (!is_writing && obj.first->get_protection() != utils::protection::no) return true; + if (!rebuild_cache) + return false; + if (!obj.first->is_flushable()) return false; @@ -292,6 +322,9 @@ namespace rsx return !std::get<0>(obj.first->overlaps_page(null_check, address, true)); }); + if (to_reprotect == trampled_set.begin()) + return {}; + std::vector sections_to_flush; for (auto It = trampled_set.begin(); It != to_reprotect; ++It) { @@ -609,16 +642,9 @@ namespace rsx template thrashed_set invalidate_range(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras) { - std::pair trampled_range = std::make_pair(address, address + range); - - if (trampled_range.second < read_only_range.first || - trampled_range.first > read_only_range.second) - { - //Doesnt fall in the read_only textures range; check render targets - if (trampled_range.second < no_access_range.first || - trampled_range.first > no_access_range.second) - return {}; - } + //Test before trying to acquire the lock + if (!region_intersects_cache(address, range, is_writing)) + return {}; writer_lock lock(m_cache_mutex); return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward(extras)...);