From b6a0d56448ebfe8d6f92a93ea5a593614c26f13c Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Mon, 17 Jun 2024 13:11:15 +0100 Subject: [PATCH] GS/HW: Allow offset channel shuffles on sources. --- bin/resources/GameIndex.yaml | 4 ++-- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 13 +++++++++++-- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 7 +++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bin/resources/GameIndex.yaml b/bin/resources/GameIndex.yaml index 7fa0d06bbfaf1..4a2bb223131b6 100644 --- a/bin/resources/GameIndex.yaml +++ b/bin/resources/GameIndex.yaml @@ -25872,9 +25872,9 @@ SLES-55169: name: "Monster Lab" region: "PAL-M5" gsHWFixes: - cpuFramebufferConversion: 1 # Fixes black with rainbow screen. gpuPaletteConversion: 2 # Fixes HC size and eliminates most texture uploads. halfPixelOffset: 2 # Fixes offset bloom. + textureInsideRT: 1 # Crowd textures. SLES-55170: name: "Margot's Word Brain" region: "PAL-M5" @@ -65671,9 +65671,9 @@ SLUS-21838: region: "NTSC-U" compat: 5 gsHWFixes: - cpuFramebufferConversion: 1 # Fixes black with rainbow screen. gpuPaletteConversion: 2 # Fixes HC size and eliminates most texture uploads. halfPixelOffset: 2 # Fixes offset bloom. + textureInsideRT: 1 # Crowd textures. SLUS-21839: name: "Ski and Shoot" region: "NTSC-U" diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 73b75ada173b4..0b4b5a7d34522 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -3921,10 +3921,19 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool // We can use the minimum UV to work out which channel it's grabbing. // Used by Ape Escape 2, Everybody's Tennis/Golf, Okage, and Valkyrie Profile 2. // Page align test to limit false detections (there is a few). - const GSVector4i min_uv = GSVector4i(m_vt.m_min.t.upld(GSVector4::zero())); + GSVector4i min_uv = GSVector4i(m_vt.m_min.t.upld(GSVector4::zero())); ChannelFetch channel = ChannelFetch_NONE; + const GSLocalMemory::psm_t& t_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];; + const GSLocalMemory::psm_t& f_psm = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM]; + GSVector4i block_offset = GSVector4i(min_uv.x / t_psm.bs.x, min_uv.y / t_psm.bs.y).xyxy(); + GSVector4i m_r_block_offset = GSVector4i((m_r.x & (f_psm.pgs.x - 1)) / f_psm.bs.x, (m_r.y & (f_psm.pgs.y - 1)) / f_psm.bs.y); + + // Adjust it back to the page boundary + min_uv.x -= block_offset.x * t_psm.bs.x; + min_uv.y -= block_offset.y * t_psm.bs.y; + if (GSLocalMemory::IsPageAligned(src->m_TEX0.PSM, m_r) && - m_r.upl64(GSVector4i::zero()).eq(GSVector4i::zero())) + block_offset.eq(m_r_block_offset)) { if (min_uv.eq(GSVector4i::cxpr(0, 0, 0, 0))) channel = ChannelFetch_RED; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 2f0a94122dadb..551e0f846dc4e 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1443,7 +1443,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } // Make sure the texture actually is INSIDE the RT, it's possibly not valid if it isn't. // Also check BP >= TBP, create source isn't equpped to expand it backwards and all data comes from the target. (GH3) - else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && GSLocalMemory::m_psm[color_psm].bpp >= 16 && + else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && + (GSLocalMemory::m_psm[color_psm].bpp >= 16 || (possible_shuffle && GSLocalMemory::m_psm[color_psm].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32)) && // Channel shuffles or non indexed lookups. t->m_age <= 1 && (!found_t || t->m_last_draw > dst->m_last_draw) && CanTranslate(bp, bw, psm, block_boundary_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW)) { @@ -1476,7 +1477,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } if (bp > t->m_TEX0.TBP0) { - GSVector4i new_rect = rect; + GSVector4i new_rect = possible_shuffle ? block_boundary_rect : rect; if (linear) { new_rect.z -= 1; @@ -4461,6 +4462,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con src->m_texture = dst->m_texture; src->m_unscaled_size = dst->m_unscaled_size; src->m_shared_texture = true; + + channel_shuffle = GSRendererHW::GetInstance()->TestChannelShuffle(dst); } // Invalidate immediately on recursive draws, because if we don't here, InvalidateVideoMem() will.