From 61740fc9edd4a2d89206b653f501ff489ba2d523 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 May 2023 23:41:03 +1000 Subject: [PATCH] GS/HW: Break channel shuffle on CBP change Needed for Tomb Raider: Underworld --- pcsx2/GS/GSState.cpp | 8 ++++++++ pcsx2/GS/GSState.h | 1 + pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 2 ++ pcsx2/GS/Renderers/HW/GSRendererHW.h | 1 - 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index 8068b9b180..dbeccc8292 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -827,7 +827,15 @@ void GSState::ApplyTEX0(GIFRegTEX0& TEX0) m_mem.m_clut.ClearDrawInvalidity(); CLUTAutoFlush(PRIM->PRIM); } + Flush(GSFlushReason::CLUTCHANGE); + + // Abort any channel shuffle skipping, since this is likely part of a new shuffle. + // Test case: Tomb Raider series. This is gated by the CBP actually changing, because + // Urban Chaos writes to the memory backing the CLUT in the middle of a shuffle, and + // it's unclear whether the CLUT would actually get reloaded in that case. + if (TEX0.CBP != m_mem.m_clut.GetCLUTCBP()) + m_channel_shuffle = false; } TEX0.CPSM &= 0xa; // 1010b diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index b043da89ea..c610505bbc 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -227,6 +227,7 @@ public: bool m_mipmap = false; bool m_texflush_flag = false; bool m_isPackedUV_HackFlag = false; + bool m_channel_shuffle = false; u8 m_scanmask_used = 0; u8 m_force_preload = 0; u32 m_dirty_gs_regs = 0; diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 1d9cbac037..5f9433181f 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -1415,6 +1415,8 @@ void GSRendererHW::Draw() { // NFSU2 does consecutive channel shuffles with blending, reducing the alpha channel over time. // Fortunately, it seems to change the FBMSK along the way, so this check alone is sufficient. + // Tomb Raider: Underworld does similar, except with R, G, B in separate palettes, therefore + // we need to split on those too. m_channel_shuffle = IsPossibleChannelShuffle() && m_last_channel_shuffle_fbmsk == m_context->FRAME.FBMSK; #ifdef ENABLE_OGL_DEBUG diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.h b/pcsx2/GS/Renderers/HW/GSRendererHW.h index 5d3f4829e3..bc0a6eb6e4 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.h +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.h @@ -135,7 +135,6 @@ private: u32 m_split_texture_shuffle_start_TBP = 0; u32 m_last_channel_shuffle_fbmsk = 0; - bool m_channel_shuffle = false; bool m_userhacks_tcoffset = false; float m_userhacks_tcoffset_x = 0.0f;