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; }