mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-01 04:51:49 +01:00
Merge pull request #2447 from kd-11/cache_invalidation_fix
gl/vk/cache: Fix invalidating intersecting and overlapping memory regions
This commit is contained in:
commit
1f45f05f8d
@ -776,18 +776,33 @@ namespace gl
|
|||||||
bool mark_as_dirty(u32 address)
|
bool mark_as_dirty(u32 address)
|
||||||
{
|
{
|
||||||
bool response = false;
|
bool response = false;
|
||||||
|
std::pair<u32, u32> 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 &&
|
if (address >= texture_cache_range.first &&
|
||||||
address < texture_cache_range.second)
|
address < texture_cache_range.second)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_section_mutex);
|
std::lock_guard<std::mutex> 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.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.unprotect();
|
||||||
tex.set_dirty(true);
|
tex.set_dirty(true);
|
||||||
|
|
||||||
@ -801,12 +816,23 @@ namespace gl
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_section_mutex);
|
std::lock_guard<std::mutex> 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.unprotect();
|
||||||
rtt.set_dirty(true);
|
rtt.set_dirty(true);
|
||||||
|
|
||||||
|
@ -270,20 +270,33 @@ namespace vk
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool invalidate_address(u32 rsx_address)
|
bool invalidate_address(u32 address)
|
||||||
{
|
{
|
||||||
if (rsx_address < texture_cache_range.first ||
|
if (address < texture_cache_range.first ||
|
||||||
rsx_address > texture_cache_range.second)
|
address > texture_cache_range.second)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool response = false;
|
bool response = false;
|
||||||
|
std::pair<u32, u32> 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.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.set_dirty(true);
|
||||||
tex.unprotect();
|
tex.unprotect();
|
||||||
|
|
||||||
|
@ -163,6 +163,24 @@ namespace rsx
|
|||||||
return (locked_address_base <= address && (address - locked_address_base) < locked_address_range);
|
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 <min, max> with updated invalid range
|
||||||
|
*/
|
||||||
|
std::tuple<bool, std::pair<u32, u32>> overlaps_page(std::pair<u32, u32> 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
|
bool is_locked() const
|
||||||
{
|
{
|
||||||
return locked;
|
return locked;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user