mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
rsx: Avoid false positives by early rejection. Should keep cache thashing to a minimum
This commit is contained in:
parent
055f0e2e4a
commit
7abf755a57
1 changed files with 38 additions and 12 deletions
|
@ -210,6 +210,31 @@ namespace rsx
|
||||||
return utils::protection::rw;
|
return utils::protection::rw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool region_intersects_cache(u32 address, u32 range, bool is_writing) const
|
||||||
|
{
|
||||||
|
std::pair<u32, u32> 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
|
//Get intersecting set - Returns all objects intersecting a given range and their owning blocks
|
||||||
std::vector<std::pair<section_storage_type*, ranged_storage*>> get_intersecting_set(u32 address, u32 range, bool check_whole_size)
|
std::vector<std::pair<section_storage_type*, ranged_storage*>> get_intersecting_set(u32 address, u32 range, bool check_whole_size)
|
||||||
{
|
{
|
||||||
|
@ -273,18 +298,23 @@ namespace rsx
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
thrashed_set invalidate_range_impl_base(u32 address, u32 range, bool is_writing, bool discard_only, bool rebuild_cache, bool allow_flush, Args&&... extras)
|
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);
|
auto trampled_set = get_intersecting_set(address, range, allow_flush);
|
||||||
|
|
||||||
if (trampled_set.size() > 0)
|
if (trampled_set.size() > 0)
|
||||||
{
|
{
|
||||||
// Rebuild the cache by only destroying ranges that need to be destroyed to unlock this page
|
// 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() :
|
const auto to_reprotect = std::remove_if(trampled_set.begin(), trampled_set.end(),
|
||||||
std::remove_if(trampled_set.begin(), trampled_set.end(),
|
|
||||||
[&](const std::pair<section_storage_type*, ranged_storage*>& obj)
|
[&](const std::pair<section_storage_type*, ranged_storage*>& obj)
|
||||||
{
|
{
|
||||||
if (!is_writing && obj.first->get_protection() != utils::protection::no)
|
if (!is_writing && obj.first->get_protection() != utils::protection::no)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (!rebuild_cache)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!obj.first->is_flushable())
|
if (!obj.first->is_flushable())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -292,6 +322,9 @@ namespace rsx
|
||||||
return !std::get<0>(obj.first->overlaps_page(null_check, address, true));
|
return !std::get<0>(obj.first->overlaps_page(null_check, address, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (to_reprotect == trampled_set.begin())
|
||||||
|
return {};
|
||||||
|
|
||||||
std::vector<section_storage_type*> sections_to_flush;
|
std::vector<section_storage_type*> sections_to_flush;
|
||||||
for (auto It = trampled_set.begin(); It != to_reprotect; ++It)
|
for (auto It = trampled_set.begin(); It != to_reprotect; ++It)
|
||||||
{
|
{
|
||||||
|
@ -609,16 +642,9 @@ namespace rsx
|
||||||
template <typename ...Args>
|
template <typename ...Args>
|
||||||
thrashed_set invalidate_range(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
|
thrashed_set invalidate_range(u32 address, u32 range, bool is_writing, bool discard, bool allow_flush, Args&&... extras)
|
||||||
{
|
{
|
||||||
std::pair<u32, u32> trampled_range = std::make_pair(address, address + range);
|
//Test before trying to acquire the lock
|
||||||
|
if (!region_intersects_cache(address, range, is_writing))
|
||||||
if (trampled_range.second < read_only_range.first ||
|
return {};
|
||||||
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 {};
|
|
||||||
}
|
|
||||||
|
|
||||||
writer_lock lock(m_cache_mutex);
|
writer_lock lock(m_cache_mutex);
|
||||||
return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward<Args>(extras)...);
|
return invalidate_range_impl(address, range, is_writing, discard, allow_flush, std::forward<Args>(extras)...);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue