Skip to content

Commit

Permalink
GS/HW: Try to keep old targets around without overlap or dirty areas
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Apr 15, 2024
1 parent d98b7d9 commit 79a882d
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
46 changes: 38 additions & 8 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Expand Up @@ -4054,6 +4054,23 @@ GSTextureCache::Target* GSTextureCache::GetTargetWithSharedBits(u32 BP, u32 PSM)
return nullptr;
}

GSTextureCache::Target* GSTextureCache::FindOverlappingTarget(GSTextureCache::Target* target) const
{
for (int i = 0; i < 2; i++)
{
for (Target* tgt : m_dst[i])
{
if (tgt == target)
continue;

if (CheckOverlap(tgt->m_TEX0.TBP0, tgt->m_end_block, target->m_TEX0.TBP0, target->m_end_block))
return tgt;
}
}

return nullptr;
}

GSTextureCache::Target* GSTextureCache::FindOverlappingTarget(u32 BP, u32 end_bp) const
{
for (int i = 0; i < 2; i++)
Expand Down Expand Up @@ -4254,11 +4271,13 @@ void GSTextureCache::IncAge()

AgeHashCache();

// Clearing of Rendertargets causes flickering in many scene transitions.
// Sigh, this seems to be used to invalidate surfaces. So set a huge maxage to avoid flicker,
// but still invalidate surfaces. (Disgaea 2 fmv when booting the game through the BIOS)
// 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.
//
// 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.
static constexpr int max_rt_age = 400; // ffx intro scene changes leave the old image untouched for a couple of frames and only then start using it
// ffx intro scene changes leave the old image untouched for a couple of frames and only then start using it
// Disgaea 2 fmv when booting the game through the BIOS
static constexpr int max_rt_age = 60;

// Toss and recompute sizes after 2 seconds of not being used. Should be sufficient for most loading screens.
static constexpr int max_size_age = 120;
Expand All @@ -4272,11 +4291,22 @@ void GSTextureCache::IncAge()

if (++t->m_age > max_rt_age)
{
i = list.erase(i);
GL_CACHE("TC: Remove Target(%s): (0x%x) due to age", to_string(type),
t->m_TEX0.TBP0);
const Target* overlapping_tgt = FindOverlappingTarget(t);

delete t;
if (!t->m_dirty.empty() || overlapping_tgt != nullptr)
{
i = list.erase(i);
GL_CACHE("TC: Remove Target(%s): (0x%x) due to age", to_string(type),
t->m_TEX0.TBP0);

delete t;
}
else
{
GL_CACHE("Extending life of target for %x", t->m_TEX0.TBP0);
t->m_age = 10;
++i;
}
}
else
{
Expand Down
1 change: 1 addition & 0 deletions pcsx2/GS/Renderers/HW/GSTextureCache.h
Expand Up @@ -498,6 +498,7 @@ class GSTextureCache
/// Looks up a target in the cache, and only returns it if the BP/BW match exactly.
Target* GetExactTarget(u32 BP, u32 BW, int type, u32 end_bp);
Target* GetTargetWithSharedBits(u32 BP, u32 PSM) const;
Target* FindOverlappingTarget(GSTextureCache::Target* target) const;
Target* FindOverlappingTarget(u32 BP, u32 end_bp) const;
Target* FindOverlappingTarget(u32 BP, u32 BW, u32 PSM, GSVector4i rc) const;

Expand Down

0 comments on commit 79a882d

Please sign in to comment.