From 26c6413f5ce2287cafb47628aff4d37df0c1fd9b Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sun, 24 Dec 2023 01:44:33 +0000 Subject: [PATCH] GS/HW: Fix some behaviour when target is copied from Z --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 29 ++++++++++++++++++++++++ pcsx2/GS/Renderers/HW/GSTextureCache.h | 1 + 2 files changed, 30 insertions(+) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 31c674a1907dd8..8db37d704518c1 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -115,6 +115,12 @@ bool GSTextureCache::FullRectDirty(Target* target, u32 rgba_mask) return true; } + // Check drawn areas on dst matches. + if (target->m_was_dst_matched && target->m_dirty.size() == 1 && target->m_drawn_since_read.rintersect(target->m_dirty[0].r).eq(target->m_drawn_since_read)) + { + return true; + } + return false; } @@ -1289,6 +1295,25 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con } else { + if ((psm == PSMT4 || psm == PSMT8) && t->m_was_dst_matched && !t->m_valid_rgb) + { + + GL_CACHE("TC: Attempt to repopulate RGB for target [%x] on source lookup", t->m_TEX0.TBP0); + for (Target* dst_match : m_dst[DepthStencil]) + { + if (dst_match->m_TEX0.TBP0 != t->m_TEX0.TBP0 || !dst_match->m_valid_rgb) + continue; + + if (!CopyRGBFromDepthToColor(t, dst_match)) + { + // If we can't update it, then just read back the valid data. + DevCon.Warning("Failed to update dst matched texture"); + } + t->m_valid_rgb = true; + break; + } + + } dst = t; found_t = true; @@ -1812,6 +1837,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe } // If our RGB was invalidated, we need to pull it from depth. + // Terminator 3 will reuse our dst_matched target with the RGB masked, then later use the full ARGB area, so we need to update the depth. const bool preserve_target = preserve_rgb || preserve_alpha; if (type == RenderTarget && (preserve_target || !dst->m_valid.rintersect(draw_rect).eq(dst->m_valid)) && !dst->m_valid_rgb && !FullRectDirty(dst, 0x7) && @@ -1827,6 +1853,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe if (dst_match->m_TEX0.TBP0 != TEX0.TBP0 || !dst_match->m_valid_rgb) continue; + dst->m_was_dst_matched = true; + if (!CopyRGBFromDepthToColor(dst, dst_match)) { // Needed new texture and memory allocation failed. @@ -1966,6 +1994,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe dst->m_valid_alpha_low = dst_match->m_valid_alpha_low;//&& psm_s.trbpp != 24; dst->m_valid_alpha_high = dst_match->m_valid_alpha_high;//&& psm_s.trbpp != 24; dst->m_valid_rgb = dst_match->m_valid_rgb; + dst->m_was_dst_matched = true; if(GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[dst_match->m_TEX0.PSM].bpp > 16) dst->m_TEX0.TBW = dst_match->m_TEX0.TBW; // Be careful of shuffles of the depth as C16, but using a buffer width of 16 (Mercenaries). diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index 90899967c04a9e..d0d8dbb2e01e64 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -146,6 +146,7 @@ class GSTextureCache int m_age = 0; u32 m_end_block = MAX_BP; // Hint of the surface area. bool m_32_bits_fmt = false; // Allow to detect the casting of 32 bits as 16 bits texture + bool m_was_dst_matched = false; bool m_shared_texture = false; __fi GSTexture* GetTexture() const { return m_texture; }