GS: add texture-cache hit/miss perfmon counters

There were no texture-cache hit/miss counters at all. Hit/miss was visible only
as GL_CACHE strings, which are compiled out unless ENABLE_OGL_DEBUG is set and
are further gated on UseDebugDevice at emit time -- so on a shipped build the
texture cache is completely opaque. For a tiler-bound title, source misses
(upload + swizzle) are a prime suspect we could not see.

Adds TCSourceHit/Miss, TCTargetHit/Miss and HashCacheHit/Miss, incremented at
the existing hit/miss forks in LookupSource and the hash cache lookup. The new
entries are appended after the ROV counters so the aliased slots
(TextureCopies = Fillrate, TextureUploads = SyncPoint) keep their indices.

Also fills in the three missing HW counter names. names_hw was declared
[CounterLastHW] but had only 10 initialisers, leaving TextureCopiesROV,
DrawCallsROV and BarriersROV as null pointers -- GSPerfMon::Dump iterates to
CounterLastHW and passed them straight to fprintf %s.
This commit is contained in:
Brian Degenhardt
2026-07-22 21:16:44 -07:00
parent 1fde0e4467
commit 6b079a4e12
3 changed files with 28 additions and 1 deletions
+10
View File
@@ -26,6 +26,16 @@ public:
TextureCopiesROV, // Overlaps with regular texture copies.
DrawCallsROV, // Overlaps with regular draw calls.
BarriersROV, // Overlaps with regular barriers.
// Texture cache lookup outcomes (HW only). Appended last so the aliased
// slots below keep their existing indices.
TCTargetHit,
TCTargetMiss,
TCSourceHit,
TCSourceMiss,
HashCacheHit,
HashCacheMiss,
CounterLast,
// Reused counters for HW.
+10 -1
View File
@@ -190,7 +190,16 @@ const char* GSUtil::GetPerfMonCounterName(GSPerfMon::counter_t counter, bool hw)
"TextureCopies",
"TextureUploads",
"Barriers",
"RenderPasses"
"RenderPasses",
"TextureCopiesROV",
"DrawCallsROV",
"BarriersROV",
"TCTargetHit",
"TCTargetMiss",
"TCSourceHit",
"TCSourceMiss",
"HashCacheHit",
"HashCacheMiss"
};
return counter < std::size(names_hw) ? names_hw[counter] : "";
}
+8
View File
@@ -2150,6 +2150,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (!src)
{
// A Source has to be built: upload + swizzle. This is the expensive outcome.
g_perfmon.Put(GSPerfMon::TCSourceMiss, 1);
g_perfmon.Put(dst ? GSPerfMon::TCTargetHit : GSPerfMon::TCTargetMiss, 1);
#ifdef ENABLE_OGL_DEBUG
if (dst)
{
@@ -2225,6 +2229,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
}
else
{
g_perfmon.Put(GSPerfMon::TCSourceHit, 1);
GL_CACHE("TC: src hit: (0x%x, 0x%x, %s)",
TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0,
GSUtil::GetPSMName(TEX0.PSM));
@@ -7036,6 +7042,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
if (it != m_hash_cache.end())
{
// super easy, cache hit. remove paltex if it's a replacement texture.
g_perfmon.Put(GSPerfMon::HashCacheHit, 1);
GL_CACHE("TC: HC Hit: %" PRIx64 " %" PRIx64 " R-%ux%u", key.TEX0Hash, key.CLUTHash, key.region_width, key.region_height);
HashCacheEntry* entry = &it->second;
paltex &= (entry->texture->GetFormat() == GSTexture::Format::UNorm8);
@@ -7044,6 +7051,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
}
// cache miss.
g_perfmon.Put(GSPerfMon::HashCacheMiss, 1);
GL_CACHE("TC: HC Miss: %" PRIx64 " %" PRIx64 " R-%ux%u", key.TEX0Hash, key.CLUTHash, key.region_width, key.region_height);
// check for a replacement texture with the full clut key