From cfb5e203b36ce1b560ad07f50c9b925615c96709 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Mon, 14 Nov 2022 11:36:38 +0000 Subject: [PATCH] GS-HW: Increase channel shuffle sizes to resolution or higher. GS-TC: Fix small bug which could end up with an invalidation being skipped. --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 21 +++++++++++++++++---- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 8 ++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index bb67c45be2..6a7d0a0073 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -823,11 +823,24 @@ GSVector2i GSRendererHW::GetTargetSize(GSVector2i* unscaled_size) } } + u32 width = m_context->FRAME.FBW * 64u; + + // If it's a channel shuffle, it'll likely be just a single page, so assume full screen. + if (m_channel_shuffle) + { + const int page_x = GSLocalMemory::m_psm[m_context->FRAME.PSM].pgs.x - 1; + const int page_y = GSLocalMemory::m_psm[m_context->FRAME.PSM].pgs.y - 1; + + // Round up the page as channel shuffles are generally done in pages at a time + width = (std::max(static_cast(GetResolution().x), width) + page_x) & ~page_x; + min_height = (std::max(static_cast(GetResolution().y), min_height) + page_y) & ~page_y; + } + // Align to even lines, reduces the chance of tiny resizes. min_height = Common::AlignUpPow2(min_height, 2); - const u32 width = m_context->FRAME.FBW * 64u; - const u32 height = m_tc->GetTargetHeight(m_context->FRAME.FBP, m_context->FRAME.FBW, m_context->FRAME.PSM, min_height); + u32 height = m_tc->GetTargetHeight(m_context->FRAME.FBP, m_context->FRAME.FBW, m_context->FRAME.PSM, min_height); + if (unscaled_size) { unscaled_size->x = static_cast(width); @@ -1705,8 +1718,8 @@ void GSRendererHW::Draw() { // We still need to make sure the dimensions of the targets match. const GSVector2 up_s(GetTextureScaleFactor()); - const int new_w = std::max(t_size.x, std::max(rt ? rt->m_texture->GetWidth() : 0, ds ? ds->m_texture->GetWidth() : 0)); - const int new_h = std::max(t_size.y, std::max(rt ? rt->m_texture->GetHeight() : 0, ds ? ds->m_texture->GetHeight() : 0)); + int new_w = std::max(t_size.x, std::max(rt ? rt->m_texture->GetWidth() : 0, ds ? ds->m_texture->GetWidth() : 0)); + int new_h = std::max(t_size.y, std::max(rt ? rt->m_texture->GetHeight() : 0, ds ? ds->m_texture->GetHeight() : 0)); if (rt) { diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 918a60bad2..1ee67ed64c 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -880,7 +880,7 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r auto& list = m_dst[type]; for (auto i = list.begin(); i != list.end();) { - auto j = i++; + auto j = i; Target* t = *j; // GH: (I think) this code is completely broken. Typical issue: @@ -935,12 +935,14 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r } if (!ComputeSurfaceOffset(off, r, t).is_valid) { - list.erase(j); + i = list.erase(j); GL_CACHE("TC: Remove Target(%s) %d (0x%x)", to_string(type), t->m_texture ? t->m_texture->GetID() : 0, t->m_TEX0.TBP0); delete t; } + else + i++; continue; } } @@ -953,6 +955,8 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r t->m_dirty_alpha = false; } + i++; + // GH: Try to detect texture write that will overlap with a target buffer // TODO Use ComputeSurfaceOffset below. if (GSUtil::HasSharedBits(psm, t->m_TEX0.PSM))