From 68823c524fbc92644a37fbca893ec3459f2e10ba Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sun, 12 Jan 2025 06:55:12 +0000 Subject: [PATCH] GS/HW: Backport target expansion change from RT in RT PR --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 12 +++++++++--- pcsx2/GS/Renderers/HW/GSRendererHW.h | 2 +- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 19 +++++++++++-------- pcsx2/GS/Renderers/HW/GSTextureCache.h | 2 +- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index 6429f1a7f3..e564fe81a7 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -952,11 +952,11 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex) return GSVector2i(width, height); } -GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex) +GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand) { const GSVector2i valid_size = GetValidSize(tex); - return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y); + return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y, can_expand); } bool GSRendererHW::IsPossibleChannelShuffle() const @@ -2612,8 +2612,14 @@ void GSRendererHW::Draw() } } + // Urban Reign trolls by scissoring a draw to a target at 0x0-0x117F to 378x449 which ends up the size being rounded up to 640x480 + // causing the buffer to expand to around 0x1400, which makes a later framebuffer at 0x1180 to fail to be created correctly. + // We can cheese this by checking if the Z is masked and the resultant colour is going to be black anyway. + const bool output_black = PRIM->ABE && ((m_context->ALPHA.A == 1 && m_context->ALPHA.B == 0 && GetAlphaMinMax().min >= 128) || m_context->ALPHA.IsBlack()) && m_draw_env->COLCLAMP.CLAMP == 1; + const bool can_expand = !(m_cached_ctx.ZBUF.ZMSK && output_black); + // Estimate size based on the scissor rectangle and height cache. - const GSVector2i t_size = GetTargetSize(src); + const GSVector2i t_size = GetTargetSize(src, can_expand); const GSVector4i t_size_rect = GSVector4i::loadh(t_size); // Ensure draw rect is clamped to framebuffer size. Necessary for updating valid area. diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.h b/pcsx2/GS/Renderers/HW/GSRendererHW.h index 1ed0d96d92..fced6cb8bd 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.h +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.h @@ -214,7 +214,7 @@ public: void MergeSprite(GSTextureCache::Source* tex); float GetTextureScaleFactor() override; GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr); - GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr); + GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true); void Reset(bool hardware_reset) override; void UpdateSettings(const Pcsx2Config::GSOptions& old_config) override; diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index e50263bfac..c63531d8c1 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -4204,7 +4204,7 @@ GSTextureCache::Target* GSTextureCache::FindOverlappingTarget(u32 BP, u32 BW, u3 return FindOverlappingTarget(BP, end_bp); } -GSVector2i GSTextureCache::GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height) +GSVector2i GSTextureCache::GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height, bool can_expand) { TargetHeightElem search = {}; search.bp = bp; @@ -4218,14 +4218,17 @@ GSVector2i GSTextureCache::GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width TargetHeightElem& elem = const_cast(*it); if (elem.bits == search.bits) { - if (elem.width < min_width || elem.height < min_height) + if (can_expand) { - DbgCon.WriteLn("Expand size at %x %u %u from %ux%u to %ux%u", bp, fbw, psm, elem.width, elem.height, - min_width, min_height); - } + if (elem.width < min_width || elem.height < min_height) + { + DbgCon.WriteLn("Expand size at %x %u %u from %ux%u to %ux%u", bp, fbw, psm, elem.width, elem.height, + min_width, min_height); + } - elem.width = std::max(elem.width, min_width); - elem.height = std::max(elem.height, min_height); + elem.width = std::max(elem.width, min_width); + elem.height = std::max(elem.height, min_height); + } m_target_heights.MoveFront(it.Index()); elem.age = 0; @@ -4233,7 +4236,7 @@ GSVector2i GSTextureCache::GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width } } - DbgCon.WriteLn("New size at %x %u %u: %ux%u", bp, fbw, psm, min_width, min_height); + DbgCon.WriteLn("New size at %x %u %u: %ux%u draw %d", bp, fbw, psm, min_width, min_height, GSState::s_n); m_target_heights.push_front(search); return GSVector2i(min_width, min_height); } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index c2551f4b39..756ecd881e 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -504,7 +504,7 @@ public: Target* FindOverlappingTarget(u32 BP, u32 end_bp) const; Target* FindOverlappingTarget(u32 BP, u32 BW, u32 PSM, GSVector4i rc) const; - GSVector2i GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height); + GSVector2i GetTargetSize(u32 bp, u32 fbw, u32 psm, s32 min_width, s32 min_height, bool can_expand = true); bool HasTargetInHeightCache(u32 bp, u32 fbw, u32 psm, u32 max_age = std::numeric_limits::max(), bool move_front = true); bool Has32BitTarget(u32 bp);