From cb7630a6ab86c24443b9cd91704104f194ad35c0 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Fri, 30 May 2025 01:54:02 +0100 Subject: [PATCH] GS/HW: Create new targets on shuffles when no target found And get rid of some valid sizing thing which is just insane --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 9 +++-- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 42 ++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index a3f6e1f661..9438e3395f 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -4092,8 +4092,13 @@ void GSRendererHW::Draw() const bool rt_update = can_update_size || (m_texture_shuffle && (src && rt && src->m_from_target != rt)); // If it's updating from a texture shuffle, limit the size to the source size. - if (rt_update && !can_update_size && src->m_from_target) - update_rect = update_rect.rintersect(src->m_from_target->m_valid); + if (rt_update && !can_update_size) + { + if(src->m_from_target) + update_rect = update_rect.rintersect(src->m_from_target->m_valid); + + update_rect = update_rect.rintersect(GSVector4i::loadh(GSVector2i(new_w, new_h))); + } // if frame is masked or afailing always to never write frame, wanna make sure we don't touch it. This might happen if DATE or Alpha Test is being used to write to Z. const bool frame_masked = ((m_cached_ctx.FRAME.FBMSK & frame_psm.fmsk) == frame_psm.fmsk) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ATST_NEVER && !(m_cached_ctx.TEST.AFAIL & AFAIL_FB_ONLY)); diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 2b0dd67e61..d0e2ba9cc5 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -1988,6 +1988,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const src = CreateMergedSource(TEX0, TEXA, region, dst->m_scale); } + GSVector4i rect = r; + if (!src) { #ifdef ENABLE_OGL_DEBUG @@ -2006,7 +2008,43 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const } #endif - src = CreateSource(TEX0, TEXA, dst, x_offset, y_offset, lod, &r, gpu_clut, region); + // This is for the condition where the target doesn't exist on a shuffle and it needs to load from memory. + // The Godfather clears the depth buffer with a normal clear, so our depth target gets deleted, then because it finds no target + // it assumes it really is 16bits, causing the texture to be full of garbage, and our shuffle handling becomes a mess. + // In this case it's actually C24, but let's just assume it means C32, it shouldn't matter in this case. + GIFRegTEX0 src_TEX0 = TEX0; + if (possible_shuffle && !dst && psm_s.bpp == 16) + { + if (frame.FBW == src_TEX0.TBW && frame.FBW <= 14) + { + rect.y /= 2; + rect.w /= 2; + } + else + { + rect.x /= 2; + rect.z /= 2; + } + if (TEX0.TBP0 == frame.Block()) + { + GIFRegTEX0 target_TEX0; + target_TEX0.TBP0 = frame.Block(); + target_TEX0.PSM = PSMCT32; + target_TEX0.TBW = frame.FBW; + + if (target_TEX0.TBW > 14) + target_TEX0.TBW /= 2; + + dst = g_texture_cache->CreateTarget(target_TEX0, GSVector2i(rect.z, rect.w), GSVector2i(rect.z, rect.w), GSRendererHW::GetInstance()->GetUpscaleMultiplier(), + GSLocalMemory::m_psm[TEX0.PSM].depth ? DepthStencil : RenderTarget, true, 0, false, true, possible_shuffle, rect, nullptr); + } + else + { + src_TEX0.PSM = PSMCT32; + } + } + + src = CreateSource(src_TEX0, TEXA, dst, x_offset, y_offset, lod, &rect, gpu_clut, region); if (!src) [[unlikely]] return nullptr; } @@ -2071,7 +2109,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const AttachPaletteToSource(src, psm_s.pal, true, true); } - src->Update(r); + src->Update(rect); return src; }