rsx: Handle rsx-self-tripping in draw call and triggering invalid invalidation

- If draw call resources consume memory that intersects with NA parts of the texture cache, we get a framebuffer test mismatch.
  This mismatch is false and happens because the thread has not yet reached the point of relocking the pages
This commit is contained in:
kd-11 2018-12-20 22:38:48 +03:00 committed by kd-11
parent a95a44cf66
commit 3be4b474d9

View file

@ -1494,7 +1494,7 @@ namespace rsx
template <typename render_target_type, typename surface_store_type> template <typename render_target_type, typename surface_store_type>
sampled_image_descriptor process_framebuffer_resource(commandbuffer_type& cmd, render_target_type texptr, u32 texaddr, u32 gcm_format, surface_store_type& m_rtts, sampled_image_descriptor process_framebuffer_resource(commandbuffer_type& cmd, render_target_type texptr, u32 texaddr, u32 gcm_format, surface_store_type& m_rtts,
u16 tex_width, u16 tex_height, u16 tex_depth, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth, u32 encoded_remap, const texture_channel_remap_t& decoded_remap) u16 tex_width, u16 tex_height, u16 tex_depth, u16 tex_pitch, rsx::texture_dimension_extended extended_dimension, bool is_depth, bool is_bound, u32 encoded_remap, const texture_channel_remap_t& decoded_remap)
{ {
const u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN); const u32 format = gcm_format & ~(CELL_GCM_TEXTURE_UN | CELL_GCM_TEXTURE_LN);
const auto surface_width = texptr->get_surface_width(); const auto surface_width = texptr->get_surface_width();
@ -1628,46 +1628,21 @@ namespace rsx
if (internal_height > surface_height) if (internal_height > surface_height)
scale_y *= ((f32)internal_height / surface_height); scale_y *= ((f32)internal_height / surface_height);
if (!is_depth) if (is_bound)
{
for (const auto& tex : m_rtts.m_bound_render_targets)
{
if (std::get<0>(tex) == texaddr)
{ {
if (g_cfg.video.strict_rendering_mode) if (g_cfg.video.strict_rendering_mode)
{ {
LOG_WARNING(RSX, "Attempting to sample a currently bound render target @ 0x%x", texaddr); LOG_TRACE(RSX, "Attempting to sample a currently bound %s target @ 0x%x", is_depth? "depth" : "color", texaddr);
requires_processing = true;
update_subresource_cache = true;
break;
}
else
{
//issue a texture barrier to ensure previous writes are visible
insert_texture_barrier(cmd, texptr);
break;
}
}
}
}
else
{
if (texaddr == std::get<0>(m_rtts.m_bound_depth_stencil))
{
if (g_cfg.video.strict_rendering_mode)
{
LOG_WARNING(RSX, "Attempting to sample a currently bound depth surface @ 0x%x", texaddr);
requires_processing = true; requires_processing = true;
update_subresource_cache = true; update_subresource_cache = true;
} }
else else
{ {
//issue a texture barrier to ensure previous writes are visible // Issue a texture barrier to ensure previous writes are visible
insert_texture_barrier(cmd, texptr); insert_texture_barrier(cmd, texptr);
} }
} }
} }
}
if (!requires_processing) if (!requires_processing)
{ {
@ -1724,15 +1699,16 @@ namespace rsx
if (!is_compressed_format) if (!is_compressed_format)
{ {
//Check for sampleable rtts from previous render passes // Check for sampleable rtts from previous render passes
//TODO: When framebuffer Y compression is properly handled, this section can be removed. A more accurate framebuffer storage check exists below this block // TODO: When framebuffer Y compression is properly handled, this section can be removed. A more accurate framebuffer storage check exists below this block
if (auto texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr)) if (auto texptr = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
{ {
if (texptr->test()) const bool is_active = m_rtts.address_is_bound(texaddr, false);
if (texptr->test() || is_active)
{ {
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts,
tex_width, tex_height, depth, tex_pitch, extended_dimension, false, tex.remap(), tex_width, tex_height, depth, tex_pitch, extended_dimension, false, is_active,
tex.decoded_remap()); tex.remap(), tex.decoded_remap());
} }
else else
{ {
@ -1743,11 +1719,12 @@ namespace rsx
if (auto texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr)) if (auto texptr = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{ {
if (texptr->test()) const bool is_active = m_rtts.address_is_bound(texaddr, true);
if (texptr->test() || is_active)
{ {
return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts, return process_framebuffer_resource(cmd, texptr, texaddr, tex.format(), m_rtts,
tex_width, tex_height, depth, tex_pitch, extended_dimension, true, tex.remap(), tex_width, tex_height, depth, tex_pitch, extended_dimension, true, is_active,
tex.decoded_remap()); tex.remap(), tex.decoded_remap());
} }
else else
{ {
@ -1771,7 +1748,7 @@ namespace rsx
const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch); const auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, tex_width, tex_height, tex_pitch);
if (rsc.surface) if (rsc.surface)
{ {
if (!rsc.surface->test()) if (!rsc.surface->test() && !m_rtts.address_is_bound(rsc.base_address, rsc.is_depth_surface))
{ {
m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface); m_rtts.invalidate_surface_address(rsc.base_address, rsc.is_depth_surface);
invalidate_address(rsc.base_address, invalidation_cause::read, std::forward<Args>(extras)...); invalidate_address(rsc.base_address, invalidation_cause::read, std::forward<Args>(extras)...);
@ -1952,14 +1929,14 @@ namespace rsx
src_is_render_target = false; src_is_render_target = false;
} }
if (src_is_render_target && !src_subres.surface->test()) if (src_is_render_target && !src_subres.surface->test() && !m_rtts.address_is_bound(src_subres.base_address, src_subres.is_depth_surface))
{ {
m_rtts.invalidate_surface_address(src_subres.base_address, src_subres.is_depth_surface); m_rtts.invalidate_surface_address(src_subres.base_address, src_subres.is_depth_surface);
invalidate_address(src_subres.base_address, invalidation_cause::read, std::forward<Args>(extras)...); invalidate_address(src_subres.base_address, invalidation_cause::read, std::forward<Args>(extras)...);
src_is_render_target = false; src_is_render_target = false;
} }
if (dst_is_render_target && !dst_subres.surface->test()) if (dst_is_render_target && !dst_subres.surface->test() && !m_rtts.address_is_bound(dst_subres.base_address, dst_subres.is_depth_surface))
{ {
m_rtts.invalidate_surface_address(dst_subres.base_address, dst_subres.is_depth_surface); m_rtts.invalidate_surface_address(dst_subres.base_address, dst_subres.is_depth_surface);
invalidate_address(dst_subres.base_address, invalidation_cause::read, std::forward<Args>(extras)...); invalidate_address(dst_subres.base_address, invalidation_cause::read, std::forward<Args>(extras)...);