From ece3780e14985f01ec7dc84e4757a772ddbff2e9 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Wed, 12 Jun 2024 20:27:23 +0100 Subject: [PATCH 1/2] GS/HW: Don't kill old targets unless completely dirty or targets overlap --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 014c2e3efeafa..640f6f3929804 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -4296,7 +4296,7 @@ void GSTextureCache::IncAge() AgeHashCache(); - // As of 04/15/2024 this is s et to 60 (just 1 second of targets), which should be fine now as it doesn't destroy targets which haven't been coevred. + // As of 04/15/2024 this is s et to 60 (just 1 second of targets), which should be fine now as it doesn't destroy targets which haven't been covered. // // For reference, here are some games sensitive to killing old targets: // Original maxage was 4 here, Xenosaga 2 needs at least 240, else it flickers on scene transitions. @@ -4318,7 +4318,7 @@ void GSTextureCache::IncAge() { const Target* overlapping_tgt = FindOverlappingTarget(t); - if (!t->m_dirty.empty() || overlapping_tgt != nullptr) + if (overlapping_tgt != nullptr || t->m_dirty.GetTotalRect(t->m_TEX0, GSVector2i(t->m_valid.width(), t->m_valid.height())).rintersect(t->m_valid).eq(t->m_valid)) { i = list.erase(i); GL_CACHE("TC: Remove Target(%s): (0x%x) due to age", to_string(type), From f555ee0a5e6f419c318e6c4dbeedab2a97d9d0c3 Mon Sep 17 00:00:00 2001 From: refractionpcsx2 Date: Wed, 12 Jun 2024 22:15:15 +0100 Subject: [PATCH 2/2] GS/HW: Include block offsets on invalidation by page --- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 640f6f3929804..2f0a94122dadb 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -544,7 +544,7 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe const bool matched_format = (src_info->bpp == dst_info->bpp); const bool block_matched_format = matched_format && block_aligned_rect; const bool req_depth_offset = (src_info->depth > 0 && !page_aligned_rect); - + bool address_offset = block_offset > 0; // If there is block offset left over, try to adjust to that. if (block_matched_format && (block_offset || req_depth_offset)) { @@ -586,6 +586,7 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe b2a_offset.x = 0; } + address_offset = false; in_rect = (in_rect + b2a_offset.xyxy()).max_i32(GSVector4i(0)); if (block_offset > 0 && !req_depth_offset) @@ -647,6 +648,17 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe const int block_y = in_rect.y & (src_info->pgs.y - 1); x_offset += block_x; y_offset += block_y; + + if (address_offset) + { + const int blocks_wide = src_info->pgs.x / src_info->bs.x; + const int block_x_offset = (block_offset % blocks_wide) * src_info->bs.x; + const int block_y_offset = (block_offset / blocks_wide) * src_info->bs.y; + + x_offset += block_x_offset; + y_offset += block_y_offset; + } + if (block_x) in_rect = GSVector4i(in_rect.x - block_x, in_rect.y, in_rect.z - block_x, in_rect.w); if (block_y)