GS/HW: Don't try to dirty targets which don't overlap

The current invalidation code sucks, but at least this stops things
which are blatently wrong from happening.
This commit is contained in:
Stenzek 2023-02-22 23:16:20 +10:00 committed by refractionpcsx2
parent c1bc1af302
commit c7e9c9542e
3 changed files with 20 additions and 1 deletions

View File

@ -1330,7 +1330,8 @@ void GSRendererHW::Draw()
// We trigger the sw prim render here super early, to avoid creating superfluous render targets. // We trigger the sw prim render here super early, to avoid creating superfluous render targets.
if (CanUseSwPrimRender(no_rt, no_ds, draw_sprite_tex) && SwPrimRender(*this, true)) if (CanUseSwPrimRender(no_rt, no_ds, draw_sprite_tex) && SwPrimRender(*this, true))
{ {
GL_CACHE("Possible texture decompression, drawn with SwPrimRender()"); GL_CACHE("Possible texture decompression, drawn with SwPrimRender() (BP %x BW %u TBP0 %x TBW %u)",
m_context->FRAME.Block(), m_context->FRAME.FBMSK, m_context->TEX0.TBP0, m_context->TEX0.TBW);
return; return;
} }

View File

@ -1192,6 +1192,10 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
if (!target) if (!target)
return; return;
// Handle the case where the transfer wrapped around the end of GS memory.
const u32 end_bp = off.bn(rect.z - 1, rect.w - 1);
const u32 unwrapped_end_bp = end_bp + ((end_bp < bp) ? MAX_BLOCKS : 0);
for (int type = 0; type < 2; type++) for (int type = 0; type < 2; type++)
{ {
auto& list = m_dst[type]; auto& list = m_dst[type];
@ -1200,6 +1204,13 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r
auto j = i; auto j = i;
Target* t = *j; Target* t = *j;
// Don't bother checking any further if the target doesn't overlap with the write/invalidation.
if ((bp < t->m_TEX0.TBP0 && unwrapped_end_bp < t->m_TEX0.TBP0) || bp > t->UnwrappedEndBlock())
{
++i;
continue;
}
// GH: (I think) this code is completely broken. Typical issue: // GH: (I think) this code is completely broken. Typical issue:
// EE write an alpha channel into 32 bits texture // EE write an alpha channel into 32 bits texture
// Results: the target is deleted (because HasCompatibleBits is false) // Results: the target is deleted (because HasCompatibleBits is false)

View File

@ -248,6 +248,13 @@ public:
Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type); Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type);
~Target(); ~Target();
/// Returns true if the target wraps around the end of GS memory.
bool Wraps() const { return (m_end_block < m_TEX0.TBP0); }
/// Returns the end block for the target, but doesn't wrap at 0x3FFF.
/// Can be used for overlap tests.
u32 UnwrappedEndBlock() const { return (m_end_block + (Wraps() ? MAX_BLOCKS : 0)); }
void ResizeValidity(const GSVector4i& rect); void ResizeValidity(const GSVector4i& rect);
void UpdateValidity(const GSVector4i& rect, bool can_resize = true); void UpdateValidity(const GSVector4i& rect, bool can_resize = true);