diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 0f2ff7b918..2aa0730b24 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -2339,13 +2339,20 @@ void GSRendererHW::Draw() if (process_texture) { GIFRegCLAMP MIP_CLAMP = m_cached_ctx.CLAMP; - const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r)+1; - const bool draw_uses_target = src->m_from_target && ((src->m_from_target_TEX0.TBP0 <= m_cached_ctx.FRAME.Block() && - src->m_from_target->UnwrappedEndBlock() > m_cached_ctx.FRAME.Block()) || - (m_cached_ctx.FRAME.Block() < src->m_from_target_TEX0.TBP0 && draw_end > src->m_from_target_TEX0.TBP0)); - + const GSVertex* v = &m_vertex.buff[0]; + if (rt) { + // Hypothesis: texture shuffle is used as a postprocessing effect so texture will be an old target. + // Initially code also tested the RT but it gives too much false-positive + const int first_x = (v[0].XYZ.X + 8) >> 4; + const int first_u = PRIM->FST ? ((v[0].U + 8) >> 4) : static_cast(((1 << m_cached_ctx.TEX0.TW) * (v[0].ST.S / v[1].RGBAQ.Q)) + 0.5f); + const bool shuffle_coords = (first_x ^ first_u) & 8; + const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1; + const bool draw_uses_target = src->m_from_target && ((src->m_from_target_TEX0.TBP0 <= m_cached_ctx.FRAME.Block() && + src->m_from_target->UnwrappedEndBlock() > m_cached_ctx.FRAME.Block()) || + (m_cached_ctx.FRAME.Block() < src->m_from_target_TEX0.TBP0 && draw_end > src->m_from_target_TEX0.TBP0)); + // copy of a 16bit source in to this target, make sure it's opaque and not bilinear to reduce false positives. m_copy_16bit_to_target_shuffle = m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() && rt->m_32_bits_fmt == true && IsOpaque() && !(context->TEX1.MMIN & 1) && !src->m_32_bits_fmt && m_cached_ctx.FRAME.FBMSK; @@ -2353,22 +2360,13 @@ void GSRendererHW::Draw() // It's not actually possible to do a C16->C16 texture shuffle of B to A as they are the same group // However you can do it by using C32 and offsetting the target verticies to point to B A, then mask as appropriate. m_same_group_texture_shuffle = draw_uses_target && (m_cached_ctx.TEX0.PSM & 0xE) == PSMCT32 && (m_cached_ctx.FRAME.PSM & 0x7) == PSMCT16 && (m_vt.m_min.p.x == 8.0f); - } - const GSVertex* v = &m_vertex.buff[0]; - // Hypothesis: texture shuffle is used as a postprocessing effect so texture will be an old target. - // Initially code also tested the RT but it gives too much false-positive - const int first_x = (v[0].XYZ.X + 8) >> 4; - const int first_u = PRIM->FST ? ((v[0].U + 8) >> 4) : static_cast(((1 << m_cached_ctx.TEX0.TW) * (v[0].ST.S / v[1].RGBAQ.Q)) + 0.5f); - const bool shuffle_coords = (first_x ^ first_u) & 8; - // Both input and output are 16 bits and texture was initially 32 bits! Same for the target, Sonic Unleash makes a new target which really is 16bit. - m_texture_shuffle = ((m_same_group_texture_shuffle || (tex_psm.bpp == 16)) && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) && - (shuffle_coords || rt->m_32_bits_fmt)) - && draw_sprite_tex && (src->m_32_bits_fmt || m_copy_16bit_to_target_shuffle); - /* const bool old_shuffle = ((m_same_group_texture_shuffle || (tex_psm.bpp == 16)) && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16)) - && draw_sprite_tex && (src->m_32_bits_fmt || m_copy_16bit_to_target_shuffle); - if (old_shuffle && !m_texture_shuffle) - DevCon.Warning("Here draw %d", s_n);*/ + // Both input and output are 16 bits and texture was initially 32 bits! Same for the target, Sonic Unleash makes a new target which really is 16bit. + m_texture_shuffle = ((m_same_group_texture_shuffle || (tex_psm.bpp == 16)) && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) && + (shuffle_coords || rt->m_32_bits_fmt)) + && draw_sprite_tex && (src->m_32_bits_fmt || m_copy_16bit_to_target_shuffle); + }; + // Okami mustn't call this code if (m_texture_shuffle && m_vertex.next < 3 && PRIM->FST && ((m_cached_ctx.FRAME.FBMSK & fm_mask) == 0)) {