rsx: Fix memory protection

- Fixes hanging when wcb is enabled
This commit is contained in:
kd-11 2017-10-12 23:04:49 +03:00
parent 479aa91368
commit 86bf61ad35
3 changed files with 35 additions and 10 deletions

View file

@ -209,7 +209,7 @@ namespace rsx
if (tex.is_dirty()) continue;
if (!tex.is_locked()) continue; //flushable sections can be 'clean' but unlocked. TODO: Handle this better
auto overlapped = tex.overlaps_page(trampled_range, address);
auto overlapped = tex.overlaps_page(trampled_range, address, false);
if (std::get<0>(overlapped))
{
auto &new_range = std::get<1>(overlapped);
@ -277,9 +277,9 @@ namespace rsx
auto &tex = range_data.data[i];
if (tex.is_dirty()) continue;
if (!tex.is_flushable()) continue;
if (!tex.is_locked()) continue;
auto overlapped = tex.overlaps_page(trampled_range, address);
auto overlapped = tex.overlaps_page(trampled_range, address, true);
if (std::get<0>(overlapped))
{
auto &new_range = std::get<1>(overlapped);
@ -292,12 +292,20 @@ namespace rsx
range_reset = true;
}
//Defer actual flush operation until all affected regions are cleared to prevent recursion
if (tex.is_flushable())
{
sections_to_flush.push_back(&tex);
}
else
{
m_unreleased_texture_objects++;
tex.set_dirty(true);
}
tex.unprotect();
sections_to_flush.push_back(&tex);
range_data.remove_one();
response = true;
range_data.remove_one();
}
}

View file

@ -835,7 +835,7 @@ namespace rsx
const auto window_origin = rsx::method_registers.shader_window_origin();
const u32 window_height = rsx::method_registers.shader_window_height();
const f32 resolution_scale = (window_height <= g_cfg.video.min_scalable_dimension)? 1.f : rsx::get_resolution_scale();
const f32 resolution_scale = (window_height <= (u32)g_cfg.video.min_scalable_dimension)? 1.f : rsx::get_resolution_scale();
const f32 wpos_scale = (window_origin == rsx::window_origin::top) ? (1.f / resolution_scale) : (-1.f / resolution_scale);
const f32 wpos_bias = (window_origin == rsx::window_origin::top) ? 0.f : window_height;

View file

@ -68,6 +68,7 @@ namespace rsx
u32 cpu_address_range = 0;
utils::protection protection = utils::protection::rw;
protection_policy guard_policy;
bool locked = false;
bool dirty = false;
@ -115,6 +116,7 @@ namespace rsx
locked_address_range = align(base + length, 4096) - locked_address_base;
protection = utils::protection::rw;
guard_policy = protect_policy;
locked = false;
}
@ -170,7 +172,7 @@ namespace rsx
* 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
std::tuple<bool, std::pair<u32, u32>> overlaps_page(std::pair<u32, u32> old_range, u32 address, bool full_range_check) const
{
const u32 page_base = address & ~4095;
const u32 page_limit = address + 4096;
@ -178,10 +180,25 @@ namespace rsx
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))
u32 memory_base, memory_range;
if (full_range_check && guard_policy != protection_policy::protect_policy_full_range)
{
//Make sure protection range is full range
memory_base = (cpu_address_base & ~4095);
memory_range = align(cpu_address_base + cpu_address_range, 4096u) - memory_base;
}
else
{
memory_base = locked_address_base;
memory_range = locked_address_range;
}
if (!region_overlaps(memory_base, memory_base + memory_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)));
const u32 _min = std::min(memory_base, compare_min);
const u32 _max = std::max(memory_base + memory_range, compare_max);
return std::make_tuple(true, std::make_pair(_min, _max));
}
bool is_locked() const