From ed5984aa3ace7c15d83bd38d41e91980235ffeaa Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Sat, 18 Mar 2023 01:58:59 +0000 Subject: [PATCH] GS-TC: Update draw rect on draw + invalidate bad match old targets --- pcsx2/GS/Renderers/HW/GSRendererHW.cpp | 9 ++++- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 45 ++++++++++++++++-------- pcsx2/GS/Renderers/HW/GSTextureCache.h | 2 ++ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index d45e9046ba..db4923d0b6 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -2053,11 +2053,14 @@ void GSRendererHW::Draw() rt->ResizeTexture(new_w, new_h); if (!m_texture_shuffle && !m_channel_shuffle) + { rt->ResizeValidity(rt->GetUnscaledRect()); + rt->ResizeDrawn(rt->GetUnscaledRect()); + } // Limit to 2x the vertical height of the resolution (for double buffering) rt->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2)); - + rt->UpdateDrawn(m_r, can_update_size || m_r.w <= (resolution.y * 2)); // Probably changing to double buffering, so invalidate any old target that was next to it. // This resolves an issue where the PCRTC will find the old target in FMV's causing flashing. // Grandia Xtreme, Onimusha Warlord. @@ -2090,10 +2093,14 @@ void GSRendererHW::Draw() ds->ResizeTexture(new_w, new_h); if (!m_texture_shuffle && !m_channel_shuffle) + { ds->ResizeValidity(ds->GetUnscaledRect()); + ds->ResizeDrawn(ds->GetUnscaledRect()); + } // Limit to 2x the vertical height of the resolution (for double buffering) ds->UpdateValidity(m_r, can_update_size || m_r.w <= (resolution.y * 2)); + ds->UpdateDrawn(m_r, can_update_size || m_r.w <= (resolution.y * 2)); if (!new_rect && new_height && old_end_block != ds->m_end_block) { diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 6aca6c542f..145329680a 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -2053,6 +2053,21 @@ void GSTextureCache::InvalidateVideoMem(const GSOffset& off, const GSVector4i& r // It's quicker, and Surface Offsets can get it wrong. // Example doing PSMT8H to C32, BP 0x1c80, TBP 0x1d80, incoming rect 0,128 -> 128,256 // Surface offsets translates it to 0, 128 -> 128, 128, not 0, 0 -> 128, 128. + + // If the RT is more than 1 frame old and the new data just doesn't line up properly, it's probably not made for it, kill the old target. + if (t->m_age > 1 && bw > 1 && bw != t->m_TEX0.TBW) + { + i = list.erase(j); + GL_CACHE("TC: Tex in RT Remove Old Target(%s) %d (0x%x) TPSM %x PSM %x bp 0x%x", to_string(type), + t->m_texture ? t->m_texture->GetID() : 0, + t->m_TEX0.TBP0, + t->m_TEX0.PSM, + psm, + bp); + delete t; + continue; + } + const GSVector2i page_size = GSLocalMemory::m_psm[psm].pgs; const bool can_translate = CanTranslate(bp, bw, psm, r, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW); @@ -4394,6 +4409,22 @@ void GSTextureCache::Target::UpdateIfDirtyIntersects(const GSVector4i& rc) break; } } +void GSTextureCache::Target::ResizeDrawn(const GSVector4i& rect) +{ + m_drawn_since_read = m_drawn_since_read.rintersect(rect); +} + + +void GSTextureCache::Target::UpdateDrawn(const GSVector4i& rect, bool can_resize) +{ + if (can_resize) + { + if(m_drawn_since_read.rempty()) + m_drawn_since_read = rect.rintersect(m_valid); + else + m_drawn_since_read = m_drawn_since_read.runion(rect); + } +} void GSTextureCache::Target::ResizeValidity(const GSVector4i& rect) { @@ -4423,12 +4454,6 @@ void GSTextureCache::Target::ResizeValidity(const GSVector4i& rect) void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect, bool can_resize) { - if (m_valid.runion(rect).eq(m_valid)) - { - m_drawn_since_read = m_drawn_since_read.runion(rect); - return; - } - if (can_resize) { if (m_valid.eq(GSVector4i::zero())) @@ -4447,14 +4472,6 @@ void GSTextureCache::Target::UpdateValidity(const GSVector4i& rect, bool can_res m_end_block = (((m_end_block + page_mask) & ~page_mask)) - 1; } } - - if (m_drawn_since_read.eq(GSVector4i::zero()) || !can_resize) - { - m_drawn_since_read = rect.rintersect(m_valid); - } - else - m_drawn_since_read = m_drawn_since_read.runion(rect); - // GL_CACHE("UpdateValidity (0x%x->0x%x) from R:%d,%d Valid: %d,%d", m_TEX0.TBP0, m_end_block, rect.z, rect.w, m_valid.z, m_valid.w); } diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.h b/pcsx2/GS/Renderers/HW/GSTextureCache.h index 3b98da9a0d..7401f314ca 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.h +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.h @@ -267,6 +267,8 @@ public: Target(const GIFRegTEX0& TEX0, const bool depth_supported, const int type); ~Target(); + void ResizeDrawn(const GSVector4i& rect); + void UpdateDrawn(const GSVector4i& rect, bool can_resize = true); void ResizeValidity(const GSVector4i& rect); void UpdateValidity(const GSVector4i& rect, bool can_resize = true); void UpdateValidBits(u32 bits_written);