From 7f26595804c06f64b47ba50da50b6c10866d982a Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Tue, 16 May 2023 10:31:29 +0100 Subject: [PATCH] GS-HW: Avoid clears with new targets --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 24 +++++++++++++++++------- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 16 ++++++++++------ pcsx2/GS/Renderers/HW/GSTextureCache.h | 2 +- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 8c58c2f60f..444a9c5455 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -1681,12 +1681,23 @@ void GSRendererHW::Draw() m_vertex.buff[1].RGBAQ.U32[0] : (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."); g_texture_cache->InvalidateVideoMem(context->offset.fb, m_r, false, true); 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) { @@ -4792,7 +4803,7 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDraw() return CLUTDrawTestResult::CLUTDrawOnCPU; 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) { bool is_dirty = false; @@ -5145,19 +5156,18 @@ bool GSRendererHW::OI_GsMemClear() } else if (format == 2) { - ; // Hack is used for FMV which are likely 24/32 bits. Let's keep the for reference -#if 0 + const u16 converted_color = ((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) | ((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F); + // Based on WritePixel16 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++) { - *pa.value(x) = 0; // Here the constant color + *pa.value(x) = converted_color; // Here the constant color } } -#endif } return true; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 179d8ff1be..d1cf55cbbd 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1174,7 +1174,7 @@ GSTextureCache::Target* GSTextureCache::FindTargetOverlap(u32 bp, u32 end_block, for (auto t : m_dst[type]) { // 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 nullptr; @@ -1524,7 +1524,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe if (!eerect.rempty()) { - GL_INS("Preloading the RT DATA"); + GL_INS("Preloading the RT DATA from updated GS Memory"); eerect = eerect.rintersect(newrect); 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; } + 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. - GSTextureCache::Target* src = GetExactTarget(SBP, SBW, spsm_s.depth ? DepthStencil : RenderTarget); - GSTextureCache::Target* dst = GetExactTarget(DBP, DBW, dpsm_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, dst_end); // 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. @@ -2776,13 +2778,15 @@ bool GSTextureCache::ShuffleMove(u32 BP, u32 BW, u32 PSM, int sx, int sy, int dx 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]; for (auto it = rts.begin(); it != rts.end(); ++it) // Iterate targets from MRU to LRU. { 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()); return t; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index 2c95a4ead3..a559a7f3c5 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -455,7 +455,7 @@ public: 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. - 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; GSVector2i GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height);