From 65e75f3da2ae07e048875f1f5eda7fb9bbc16be1 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Mon, 7 Aug 2023 22:13:29 +0100 Subject: [PATCH] GS/TC: Ignore linear part of rect when translating --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 4 +- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 82 +++++++++++++++++------- pcsx2/GS/Renderers/HW/GSTextureCache.h | 4 +- 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 37711ad4ff..e8de2781d6 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -2168,8 +2168,8 @@ void GSRendererHW::Draw() MIP_CLAMP.MAXV + 1); } const bool possible_shuffle = m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 || IsPossibleChannelShuffle(); - src = tex_psm.depth ? g_texture_cache->LookupDepthSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle) : - g_texture_cache->LookupSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap >= HWMipmapLevel::Basic || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr, possible_shuffle); + src = tex_psm.depth ? g_texture_cache->LookupDepthSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear()) : + g_texture_cache->LookupSource(TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap >= HWMipmapLevel::Basic || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr, possible_shuffle, m_vt.IsLinear()); if (unlikely(!src)) { GL_INS("ERROR: Source lookup failed, skipping."); diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index eecae12f65..2f17c7436d 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -586,7 +586,7 @@ __ri static GSTextureCache::Source* FindSourceInMap(const GIFRegTEX0& TEX0, cons return nullptr; } -GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, bool palette) +GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, bool palette) { if (GSConfig.UserHacks_DisableDepthSupport) { @@ -646,12 +646,19 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0 const GSVector2i page_size = GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs; const bool can_translate = CanTranslate(bp, TEX0.TBW, psm, r, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); const bool swizzle_match = psm_s.depth == GSLocalMemory::m_psm[t->m_TEX0.PSM].depth; + GSVector4i new_rect = r; + + if (linear) + { + new_rect.z -= 1; + new_rect.w -= 1; + } if (can_translate) { if (swizzle_match) { - target_rc = TranslateAlignedRectByPage(t, bp, psm, TEX0.TBW, r); + target_rc = TranslateAlignedRectByPage(t, bp, psm, TEX0.TBW, new_rect); } else { @@ -669,8 +676,8 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0 { target_rc.x &= ~(page_size.x - 1); target_rc.y &= ~(page_size.y - 1); - target_rc.z = (r.z + (page_size.x - 1)) & ~(page_size.x - 1); - target_rc.w = (r.w + (page_size.y - 1)) & ~(page_size.y - 1); + target_rc.z = (new_rect.z + (page_size.x - 1)) & ~(page_size.x - 1); + target_rc.w = (new_rect.w + (page_size.y - 1)) & ~(page_size.y - 1); } target_rc = TranslateAlignedRectByPage(t, bp & ~((1 << 5) - 1), psm, TEX0.TBW, target_rc); } @@ -681,6 +688,11 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0 inside_target = true; } } + if (linear) + { + new_rect.z += 1; + new_rect.w += 1; + } } } @@ -764,7 +776,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0 else { // This is a bit of a worry, since it could load junk from local memory... but it's better than skipping the draw. - return LookupSource(TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle); + return LookupSource(TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle, linear); } ASSERT(src->m_texture); @@ -773,7 +785,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const GIFRegTEX0& TEX0 return src; } -GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle) +GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear) { GL_CACHE("TC: Lookup Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z, r.w, TEX0.TBP0, psm_str(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH); @@ -857,6 +869,13 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con if (rect_clean && tex_overlaps && !t->m_dirty.empty() && width_match) { GSVector4i new_rect = r; + + if (linear) + { + new_rect.z -= 1; + new_rect.w -= 1; + } + bool partial = false; // If it's compatible and page aligned, then handle it this way. // It's quicker, and Surface Offsets can get it wrong. @@ -865,14 +884,14 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con if (bp > t->m_TEX0.TBP0) { const GSVector2i page_size = GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs; - const bool can_translate = CanTranslate(bp, bw, psm, r, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); + const bool can_translate = CanTranslate(bp, bw, psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); const bool swizzle_match = GSLocalMemory::m_psm[psm].depth == GSLocalMemory::m_psm[t->m_TEX0.PSM].depth; if (can_translate) { if (swizzle_match) { - new_rect = TranslateAlignedRectByPage(t, bp, psm, bw, r); + new_rect = TranslateAlignedRectByPage(t, bp, psm, bw, new_rect); } else { @@ -887,8 +906,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con { new_rect.x &= ~(page_size.x - 1); new_rect.y &= ~(page_size.y - 1); - new_rect.z = (r.z + (page_size.x - 1)) & ~(page_size.x - 1); - new_rect.w = (r.w + (page_size.y - 1)) & ~(page_size.y - 1); + new_rect.z = (new_rect.z + (page_size.x - 1)) & ~(page_size.x - 1); + new_rect.w = (new_rect.w + (page_size.y - 1)) & ~(page_size.y - 1); } new_rect = TranslateAlignedRectByPage(t, bp & ~((1 << 5) - 1), psm, bw, new_rect); } @@ -901,7 +920,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con sok.elems[0].bp = bp; sok.elems[0].bw = bw; sok.elems[0].psm = psm; - sok.elems[0].rect = r; + sok.elems[0].rect = new_rect; sok.elems[1].bp = t->m_TEX0.TBP0; sok.elems[1].bw = t->m_TEX0.TBW; sok.elems[1].psm = t->m_TEX0.PSM; @@ -941,6 +960,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con // If not all channels are clean/dirty or only part of the rect is dirty, we need to update the target. if (((channels & channel_mask) != channel_mask || partial)) t->Update(); + + if (linear) + { + new_rect.z += 1; + new_rect.w += 1; + } } else { @@ -1014,23 +1039,29 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con if (bp > t->m_TEX0.TBP0) { + GSVector4i new_rect = r; + if (linear) + { + new_rect.z -= 1; + new_rect.w -= 1; + } // Check if it is possible to hit with valid offset on the given Target. // Fixes Jak eyes rendering. // Fixes Xenosaga 3 last dungeon graphic bug. // Fixes Pause menu in The Getaway. - const bool can_translate = CanTranslate(bp, bw, psm, r, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); + const bool can_translate = CanTranslate(bp, bw, psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); if (can_translate) { const bool swizzle_match = GSLocalMemory::m_psm[psm].depth == GSLocalMemory::m_psm[t->m_TEX0.PSM].depth; const GSVector2i& page_size = GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs; const GSVector4i page_mask(GSVector4i((page_size.x - 1), (page_size.y - 1)).xyxy()); - GSVector4i rect = r & ~page_mask; + GSVector4i rect = new_rect & ~page_mask; if (swizzle_match) { - rect = TranslateAlignedRectByPage(t, bp, psm, bw, r); - rect.x -= r.x; - rect.y -= r.y; + rect = TranslateAlignedRectByPage(t, bp, psm, bw, new_rect); + rect.x -= new_rect.x; + rect.y -= new_rect.y; } else { @@ -1045,12 +1076,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con { rect.x &= ~(page_size.x - 1); rect.y &= ~(page_size.y - 1); - rect.z = (r.z + (page_size.x - 1)) & ~(page_size.x - 1); - rect.w = (r.w + (page_size.y - 1)) & ~(page_size.y - 1); + rect.z = (new_rect.z + (page_size.x - 1)) & ~(page_size.x - 1); + rect.w = (new_rect.w + (page_size.y - 1)) & ~(page_size.y - 1); } rect = TranslateAlignedRectByPage(t, bp & ~((1 << 5) - 1), psm, bw, rect); - rect.x -= r.x & ~(page_size.y - 1); - rect.y -= r.x & ~(page_size.y - 1); + rect.x -= new_rect.x & ~(page_size.y - 1); + rect.y -= new_rect.x & ~(page_size.y - 1); } rect = rect.rintersect(t->m_valid); @@ -1085,7 +1116,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con { // Improves Beyond Good & Evil shadow. const u32 bp_unwrap = bp + GSTextureCache::MAX_BP + 0x1; - so = ComputeSurfaceOffset(bp_unwrap, bw, psm, r, t); + so = ComputeSurfaceOffset(bp_unwrap, bw, psm, new_rect, t); } if (so.is_valid) { @@ -1099,6 +1130,11 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con continue; } } + if (linear) + { + new_rect.z += 1; + new_rect.w += 1; + } } else { @@ -1172,11 +1208,11 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const GIFRegTEX0& TEX0, con GIFRegTEX0 depth_TEX0; depth_TEX0.U32[0] = TEX0.U32[0] | (0x30u << 20u); depth_TEX0.U32[1] = TEX0.U32[1]; - return LookupDepthSource(depth_TEX0, TEXA, CLAMP, r, possible_shuffle); + return LookupDepthSource(depth_TEX0, TEXA, CLAMP, r, possible_shuffle, linear); } else { - return LookupDepthSource(TEX0, TEXA, CLAMP, r, possible_shuffle, true); + return LookupDepthSource(TEX0, TEXA, CLAMP, r, possible_shuffle, linear, true); } } } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index db7458acd4..3831ac2f40 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -473,8 +473,8 @@ public: GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size); std::shared_ptr LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture); - Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle); - Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, bool palette = false); + Source* LookupSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear); + Source* LookupDepthSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, bool palette = false); Target* FindTargetOverlap(Target* target, int type, int psm); Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,