rsx: Improve texture cache invalidate

- Bunch of improvements
- Properly signal renderer to rebind textures!
- TODO: Range checks, should be pretty easy
This commit is contained in:
kd-11 2021-01-28 21:53:49 +03:00 committed by kd-11
parent 52acc23ecf
commit 195fb1cf66
4 changed files with 52 additions and 20 deletions

View File

@ -53,6 +53,7 @@ namespace rsx
{ {
bool violation_handled = false; bool violation_handled = false;
bool flushed = false; bool flushed = false;
bool invalidate_samplers = false;
invalidation_cause cause; invalidation_cause cause;
std::vector<section_storage_type*> sections_to_flush; // Sections to be flushed std::vector<section_storage_type*> sections_to_flush; // Sections to be flushed
std::vector<section_storage_type*> sections_to_unprotect; // These sections are to be unpotected and discarded by caller std::vector<section_storage_type*> sections_to_unprotect; // These sections are to be unpotected and discarded by caller
@ -683,13 +684,6 @@ namespace rsx
auto &tex = *It; auto &tex = *It;
if (!tex.is_locked(true))
{
// Ignore hash sections, they are not involved in page faults
It++;
continue;
}
AUDIT(tex.is_locked()); // we should be iterating locked sections only, but just to make sure... AUDIT(tex.is_locked()); // we should be iterating locked sections only, but just to make sure...
AUDIT(tex.cache_tag != cache_tag || last_dirty_block != UINT32_MAX); // cache tag should not match during the first loop AUDIT(tex.cache_tag != cache_tag || last_dirty_block != UINT32_MAX); // cache tag should not match during the first loop
@ -799,6 +793,7 @@ namespace rsx
{ {
// Discard - this section won't be needed any more // Discard - this section won't be needed any more
tex.discard(/* set_dirty */ true); tex.discard(/* set_dirty */ true);
result.invalidate_samplers = true;
} }
else if (g_cfg.video.strict_texture_flushing && tex.is_flushable()) else if (g_cfg.video.strict_texture_flushing && tex.is_flushable())
{ {
@ -807,6 +802,7 @@ namespace rsx
else else
{ {
tex.set_dirty(true); tex.set_dirty(true);
result.invalidate_samplers = true;
} }
} }
} }
@ -821,6 +817,7 @@ namespace rsx
if (invalidate_range == fault_range) if (invalidate_range == fault_range)
{ {
result.violation_handled = true; result.violation_handled = true;
result.invalidate_samplers = true;
#ifdef TEXTURE_CACHE_DEBUG #ifdef TEXTURE_CACHE_DEBUG
// Post-check the result // Post-check the result
result.check_post_sanity(); result.check_post_sanity();
@ -840,7 +837,7 @@ namespace rsx
{ {
auto &tex = *obj; auto &tex = *obj;
if (!tex.is_locked(true)) if (!tex.is_locked())
continue; continue;
const rsx::section_bounds bounds = tex.get_overlap_test_bounds(); const rsx::section_bounds bounds = tex.get_overlap_test_bounds();
@ -859,7 +856,11 @@ namespace rsx
) )
{ {
// False positive // False positive
result.sections_to_exclude.push_back(&tex); if (tex.is_locked(true))
{
// Do not exclude hashed pages from unprotect! They will cause protection holes
result.sections_to_exclude.push_back(&tex);
}
continue; continue;
} }
@ -894,7 +895,17 @@ namespace rsx
tex.set_dirty(true); tex.set_dirty(true);
} }
result.sections_to_unprotect.push_back(&tex); if (tex.is_locked(true))
{
result.sections_to_unprotect.push_back(&tex);
}
else
{
// No need to waste resources on hashed section, just discard immediately
tex.discard(true);
result.invalidate_samplers = true;
}
continue; continue;
} }
@ -944,6 +955,8 @@ namespace rsx
result.violation_handled = false; result.violation_handled = false;
} }
result.invalidate_samplers |= result.violation_handled;
#ifdef TEXTURE_CACHE_DEBUG #ifdef TEXTURE_CACHE_DEBUG
// Post-check the result // Post-check the result
result.check_post_sanity(); result.check_post_sanity();
@ -981,7 +994,6 @@ namespace rsx
for (auto It = m_storage.range_begin(test_range, full_range, check_unlocked); It != m_storage.range_end(); It++) for (auto It = m_storage.range_begin(test_range, full_range, check_unlocked); It != m_storage.range_end(); It++)
{ {
auto &tex = *It; auto &tex = *It;
tex.sync_protection();
if (!tex.is_dirty() && (context_mask & static_cast<u32>(tex.get_context()))) if (!tex.is_dirty() && (context_mask & static_cast<u32>(tex.get_context())))
{ {
@ -990,6 +1002,11 @@ namespace rsx
continue; continue;
} }
if (!tex.sync_protection())
{
continue;
}
results.push_back(&tex); results.push_back(&tex);
} }
} }
@ -1003,14 +1020,17 @@ namespace rsx
auto &block = m_storage.block_for(rsx_address); auto &block = m_storage.block_for(rsx_address);
for (auto &tex : block) for (auto &tex : block)
{ {
tex.sync_protection();
if constexpr (check_unlocked) if constexpr (check_unlocked)
{ {
if (!tex.is_locked()) if (!tex.is_locked())
{
continue; continue;
}
} }
if (!tex.is_dirty() && tex.matches(rsx_address, format, width, height, depth, mipmaps)) if (!tex.is_dirty() &&
tex.matches(rsx_address, format, width, height, depth, mipmaps) &&
tex.sync_protection())
{ {
return &tex; return &tex;
} }
@ -1035,6 +1055,9 @@ namespace rsx
{ {
if (tex.matches(range)) if (tex.matches(range))
{ {
// We must validate
tex.sync_protection();
if (allow_dirty || !tex.is_dirty()) if (allow_dirty || !tex.is_dirty())
{ {
if (!confirm_dimensions || tex.matches(attr.gcm_format, attr.width, attr.height, attr.depth, attr.mipmaps)) if (!confirm_dimensions || tex.matches(attr.gcm_format, attr.width, attr.height, attr.depth, attr.mipmaps))

View File

@ -1480,13 +1480,16 @@ namespace rsx
flush_exclusions.clear(); flush_exclusions.clear();
} }
void sync_protection() bool sync_protection()
{ {
if (!buffered_section::sync()) if (!buffered_section::sync())
{ {
discard(true); discard(true);
ensure(is_dirty()); ensure(is_dirty());
return false;
} }
return true;
} }

View File

@ -918,14 +918,17 @@ bool GLGSRender::on_access_violation(u32 address, bool is_writing)
auto cmd = can_flush ? gl::command_context{ gl_state } : gl::command_context{}; auto cmd = can_flush ? gl::command_context{ gl_state } : gl::command_context{};
auto result = m_gl_texture_cache.invalidate_address(cmd, address, cause); auto result = m_gl_texture_cache.invalidate_address(cmd, address, cause);
if (!result.violation_handled) if (result.invalidate_samplers)
return false;
{ {
std::lock_guard lock(m_sampler_mutex); std::lock_guard lock(m_sampler_mutex);
m_samplers_dirty.store(true); m_samplers_dirty.store(true);
} }
if (!result.violation_handled)
{
return false;
}
if (result.num_flushable > 0) if (result.num_flushable > 0)
{ {
auto &task = post_flush_request(address, result); auto &task = post_flush_request(address, result);

View File

@ -660,14 +660,17 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
result = std::move(m_texture_cache.invalidate_address(m_secondary_command_buffer, address, cause)); result = std::move(m_texture_cache.invalidate_address(m_secondary_command_buffer, address, cause));
} }
if (!result.violation_handled) if (result.invalidate_samplers)
return false;
{ {
std::lock_guard lock(m_sampler_mutex); std::lock_guard lock(m_sampler_mutex);
m_samplers_dirty.store(true); m_samplers_dirty.store(true);
} }
if (!result.violation_handled)
{
return false;
}
if (result.num_flushable > 0) if (result.num_flushable > 0)
{ {
if (g_fxo->get<rsx::dma_manager>()->is_current_thread()) if (g_fxo->get<rsx::dma_manager>()->is_current_thread())