GS/HW: Allow offset channel shuffles on sources.

This commit is contained in:
refractionpcsx2 2024-06-17 13:11:15 +01:00
parent e843e17403
commit 55e0464cd3
3 changed files with 18 additions and 6 deletions

View File

@ -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"

View File

@ -3923,10 +3923,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;

View File

@ -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.