GS-HW: Avoid clears with new targets

This commit is contained in:
refractionpcsx2 2023-05-16 10:31:29 +01:00
parent 68ec70f24f
commit 7f26595804
3 changed files with 28 additions and 14 deletions

View File

@ -1681,12 +1681,23 @@ void GSRendererHW::Draw()
m_vertex.buff[1].RGBAQ.U32[0] : m_vertex.buff[1].RGBAQ.U32[0] :
(m_vertex.buff[1].RGBAQ.U32[0] & ~0xFF000000)) == 0) && m_cached_ctx.FRAME.FBMSK == 0 && IsBlendedOrOpaque(); (m_vertex.buff[1].RGBAQ.U32[0] & ~0xFF000000)) == 0) && m_cached_ctx.FRAME.FBMSK == 0 && IsBlendedOrOpaque();
if (is_zero_clear && OI_GsMemClear() && clear_height_valid) const u32 rt_end = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].info.bn(m_r.z - 1, m_r.w - 1, m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW);
const bool req_z = m_cached_ctx.FRAME.FBP != m_cached_ctx.ZBUF.ZBP && !m_cached_ctx.ZBUF.ZMSK;
bool no_target_found = false;
// This is behind the if just to reduce lookups.
if (is_zero_clear && !clear_height_valid)
no_target_found = !g_texture_cache->GetExactTarget(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, GSTextureCache::RenderTarget, rt_end) &&
!g_texture_cache->GetExactTarget(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, GSTextureCache::DepthStencil, rt_end);
if (is_zero_clear && OI_GsMemClear() && (clear_height_valid || (!req_z && no_target_found)))
{ {
GL_INS("Clear draw with mem clear and valid clear height, invalidating."); GL_INS("Clear draw with mem clear and valid clear height, invalidating.");
g_texture_cache->InvalidateVideoMem(context->offset.fb, m_r, false, true); g_texture_cache->InvalidateVideoMem(context->offset.fb, m_r, false, true);
g_texture_cache->InvalidateVideoMemType(GSTextureCache::RenderTarget, m_cached_ctx.FRAME.Block()); g_texture_cache->InvalidateVideoMemType(GSTextureCache::RenderTarget, m_cached_ctx.FRAME.Block());
if(no_target_found)
g_texture_cache->InvalidateVideoMemType(GSTextureCache::DepthStencil, m_cached_ctx.FRAME.Block());
if (m_cached_ctx.ZBUF.ZMSK == 0) if (m_cached_ctx.ZBUF.ZMSK == 0)
{ {
@ -4792,7 +4803,7 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDraw()
return CLUTDrawTestResult::CLUTDrawOnCPU; return CLUTDrawTestResult::CLUTDrawOnCPU;
GSTextureCache::Target* tgt = g_texture_cache->GetExactTarget( GSTextureCache::Target* tgt = g_texture_cache->GetExactTarget(
m_cached_ctx.TEX0.TBP0, m_cached_ctx.TEX0.TBW, GSTextureCache::RenderTarget); m_cached_ctx.TEX0.TBP0, m_cached_ctx.TEX0.TBW, GSTextureCache::RenderTarget, m_cached_ctx.TEX0.TBP0);
if (tgt) if (tgt)
{ {
bool is_dirty = false; bool is_dirty = false;
@ -5145,19 +5156,18 @@ bool GSRendererHW::OI_GsMemClear()
} }
else if (format == 2) else if (format == 2)
{ {
; // Hack is used for FMV which are likely 24/32 bits. Let's keep the for reference const u16 converted_color = ((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) | ((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F);
#if 0
// Based on WritePixel16 // Based on WritePixel16
for (int y = r.top; y < r.bottom; y++) for (int y = r.top; y < r.bottom; y++)
{ {
auto pa = off.assertSizesMatch(GSLocalMemory::swizzle16).paMulti(m_mem.m_vm16, 0, y); auto pa = off.assertSizesMatch(GSLocalMemory::swizzle16).paMulti(m_mem.vm16(), 0, y);
for (int x = r.left; x < r.right; x++) for (int x = r.left; x < r.right; x++)
{ {
*pa.value(x) = 0; // Here the constant color *pa.value(x) = converted_color; // Here the constant color
} }
} }
#endif
} }
return true; return true;

View File

@ -1174,7 +1174,7 @@ GSTextureCache::Target* GSTextureCache::FindTargetOverlap(u32 bp, u32 end_block,
for (auto t : m_dst[type]) for (auto t : m_dst[type])
{ {
// Only checks that the texure starts at the requested bp, which shares data. Size isn't considered. // Only checks that the texure starts at the requested bp, which shares data. Size isn't considered.
if (t->m_TEX0.TBP0 >= bp && t->m_TEX0.TBP0 < end_block_bp && GSUtil::HasSharedBits(t->m_TEX0.PSM, psm)) if (t->m_TEX0.TBP0 >= bp && t->m_TEX0.TBP0 < end_block_bp && GSUtil::HasCompatibleBits(t->m_TEX0.PSM, psm))
return t; return t;
} }
return nullptr; return nullptr;
@ -1524,7 +1524,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (!eerect.rempty()) if (!eerect.rempty())
{ {
GL_INS("Preloading the RT DATA"); GL_INS("Preloading the RT DATA from updated GS Memory");
eerect = eerect.rintersect(newrect); eerect = eerect.rintersect(newrect);
AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16); AddDirtyRectTarget(dst, eerect, TEX0.PSM, TEX0.TBW, rgba, GSLocalMemory::m_psm[TEX0.PSM].trbpp >= 16);
} }
@ -2583,9 +2583,11 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
return false; return false;
} }
const u32 src_end = GSLocalMemory::m_psm[SPSM].info.bn(sx + w - 1, sy + h - 1, SBP, SBW);
const u32 dst_end = GSLocalMemory::m_psm[DPSM].info.bn(dx + w - 1, dy + h - 1, DBP, DBW);
// Look for an exact match on the targets. // Look for an exact match on the targets.
GSTextureCache::Target* src = GetExactTarget(SBP, SBW, spsm_s.depth ? DepthStencil : RenderTarget); GSTextureCache::Target* src = GetExactTarget(SBP, SBW, spsm_s.depth ? DepthStencil : RenderTarget, src_end);
GSTextureCache::Target* dst = GetExactTarget(DBP, DBW, dpsm_s.depth ? DepthStencil : RenderTarget); GSTextureCache::Target* dst = GetExactTarget(DBP, DBW, dpsm_s.depth ? DepthStencil : RenderTarget, dst_end);
// Beware of the case where a game might create a larger texture by moving a bunch of chunks around. // Beware of the case where a game might create a larger texture by moving a bunch of chunks around.
// We use dx/dy == 0 and the TBW check as a safeguard to make sure these go through to local memory. // We use dx/dy == 0 and the TBW check as a safeguard to make sure these go through to local memory.
@ -2776,13 +2778,15 @@ bool GSTextureCache::ShuffleMove(u32 BP, u32 BW, u32 PSM, int sx, int sy, int dx
return true; return true;
} }
GSTextureCache::Target* GSTextureCache::GetExactTarget(u32 BP, u32 BW, int type) GSTextureCache::Target* GSTextureCache::GetExactTarget(u32 BP, u32 BW, int type, u32 end_bp)
{ {
auto& rts = m_dst[type]; auto& rts = m_dst[type];
for (auto it = rts.begin(); it != rts.end(); ++it) // Iterate targets from MRU to LRU. for (auto it = rts.begin(); it != rts.end(); ++it) // Iterate targets from MRU to LRU.
{ {
Target* t = *it; Target* t = *it;
if (t->m_TEX0.TBP0 == BP && t->m_TEX0.TBW == BW) const u32 end_block = (t->m_end_block < t->m_TEX0.TBP0) ? t->m_end_block + 0x4000 : t->m_end_block;
if (t->m_TEX0.TBP0 == BP && t->m_TEX0.TBW == BW && end_block >= end_bp)
{ {
rts.MoveFront(it.Index()); rts.MoveFront(it.Index());
return t; return t;

View File

@ -455,7 +455,7 @@ public:
Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale); Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale);
/// Looks up a target in the cache, and only returns it if the BP/BW match exactly. /// Looks up a target in the cache, and only returns it if the BP/BW match exactly.
Target* GetExactTarget(u32 BP, u32 BW, int type); Target* GetExactTarget(u32 BP, u32 BW, int type, u32 end_bp);
Target* GetTargetWithSharedBits(u32 BP, u32 PSM) const; Target* GetTargetWithSharedBits(u32 BP, u32 PSM) const;
GSVector2i GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height); GSVector2i GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height);