TexCache: Stop bitpacking the hash status into the status flags

This commit is contained in:
Henrik Rydgård
2026-06-09 10:34:28 +02:00
parent 67fb9ffc4e
commit fdcf923c75
3 changed files with 39 additions and 42 deletions
+30 -31
View File
@@ -498,7 +498,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
match = false;
}
bool rehash = entry->GetHashStatus() == TexCacheEntry::STATUS_UNRELIABLE;
bool rehash = entry->hashStatus == TexHashStatus::Unreliable;
// First let's see if another texture with the same address had a hashfail.
if (entry->status & TexCacheEntry::STATUS_CLUT_RECHECK) {
@@ -545,7 +545,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
if (minihash != entry->minihash) {
match = false;
reason = "minihash";
} else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
} else if (entry->hashStatus == TexHashStatus::Reliable) {
rehash = false;
}
}
@@ -651,14 +651,14 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
VERBOSE_LOG(Log::G3D, "No texture in cache for %08x, decoding...", texaddr);
entry = new TexCacheEntry{};
cache_[cachekey].reset(entry);
entry->status = {};
if (PPGeIsFontTextureAddress(texaddr)) {
// It's the builtin font texture.
entry->status = TexCacheEntry::STATUS_RELIABLE;
entry->hashStatus = TexHashStatus::Reliable;
} else if (g_Config.bTextureBackoffCache && !IsVideo(texaddr)) {
entry->status = TexCacheEntry::STATUS_HASHING;
entry->hashStatus = TexHashStatus::Hashing;
} else {
entry->status = TexCacheEntry::STATUS_UNRELIABLE;
entry->hashStatus = TexHashStatus::Unreliable;
}
if (hasClutGPU) {
@@ -908,8 +908,8 @@ void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c
}
// Mark as hashing, if marked as reliable.
if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
entry->SetHashStatus(TexCacheEntry::STATUS_HASHING);
if (entry->hashStatus == TexHashStatus::Reliable) {
entry->hashStatus = TexHashStatus::Hashing;
}
// Also, mark any textures with the same address but different clut. They need rechecking.
@@ -2605,9 +2605,9 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
if (fullhash == entry->fullhash) {
if (g_Config.bTextureBackoffCache && !isVideo) {
if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) {
if (entry->hashStatus != TexHashStatus::Hashing && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) {
// Reset to STATUS_HASHING.
entry->SetHashStatus(TexCacheEntry::STATUS_HASHING);
entry->hashStatus = TexHashStatus::Hashing;
entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT;
}
} else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) {
@@ -2620,7 +2620,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) {
// Don't give up just yet. Let's try the secondary cache if it's been invalidated before.
if (PSP_CoreParameter().compat.flags().SecondaryTextureCache) {
// Don't forget this one was unreliable (in case we match a secondary entry.)
entry->status |= TexCacheEntry::STATUS_UNRELIABLE;
entry->hashStatus = TexHashStatus::Unreliable;
// If it's failed a bunch of times, then the second cache is just wasting time and VRAM.
// In that case, skip.
@@ -2710,8 +2710,8 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type
// Quick check for overlap. Yes the check is right.
if (addr < texEnd && addr_end > texAddr) {
if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
entry->SetHashStatus(TexCacheEntry::STATUS_HASHING);
if (entry->hashStatus == TexHashStatus::Reliable) {
entry->hashStatus = TexHashStatus::Hashing;
}
if (type == GPU_INVALIDATE_FORCE) {
// Just random values to force the hash not to match.
@@ -2748,11 +2748,11 @@ void TextureCacheCommon::InvalidateAll(GPUInvalidationType /*unused*/) {
}
timesInvalidatedAllThisFrame_++;
for (TexCache::iterator iter = cache_.begin(), end = cache_.end(); iter != end; ++iter) {
if (iter->second->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) {
iter->second->SetHashStatus(TexCacheEntry::STATUS_HASHING);
for (auto &[key, e] : cache_) {
if (e->hashStatus == TexHashStatus::Reliable) {
e->hashStatus = TexHashStatus::Hashing;
}
iter->second->invalidHint++;
e->invalidHint++;
}
}
@@ -3096,19 +3096,21 @@ CheckAlphaResult TextureCacheCommon::CheckCLUTAlpha(const uint8_t *pixelData, GE
}
}
const char *TexHashStatusToString(TexHashStatus status) {
switch (status) {
case TexHashStatus::Hashing:
return "Hashing";
case TexHashStatus::Reliable:
return "Reliable";
case TexHashStatus::Unreliable:
return "Unreliable";
default:
return "Unknown";
}
}
std::string TexStatusToString(TexCacheEntry::TexStatus status) {
std::string result;
switch (status & TexCacheEntry::STATUS_MASK) {
case TexCacheEntry::STATUS_HASHING:
result += "HASHING ";
break;
case TexCacheEntry::STATUS_RELIABLE:
result += "RELIABLE ";
break;
case TexCacheEntry::STATUS_UNRELIABLE:
result += "UNRELIABLE ";
break;
}
if (status & TexCacheEntry::STATUS_ALPHA_MASK) {
result += "ALPHA";
}
@@ -3121,9 +3123,6 @@ std::string TexStatusToString(TexCacheEntry::TexStatus status) {
if (status & TexCacheEntry::STATUS_CHANGE_FREQUENT) {
result += "FREQ ";
}
if (status & TexCacheEntry::STATUS_UNRELIABLE) {
result += "UNREL ";
}
if (status & TexCacheEntry::STATUS_TO_SCALE) {
result += "TOSCALE ";
}
+8 -11
View File
@@ -130,6 +130,11 @@ struct TextureDefinition {
// At one point we might merge the concepts of framebuffers and textures, but that
// moment is far away.
enum class TexHashStatus : u8 {
Hashing = 0,
Reliable, // Don't bother rehashing.
Unreliable, // Always recheck hash.
};
// TODO: Shrink this struct. There is some fluff.
struct TexCacheEntry {
@@ -141,11 +146,6 @@ struct TexCacheEntry {
const static int FRAMES_REGAIN_TRUST = 1000;
enum TexStatus {
STATUS_HASHING = 0x00,
STATUS_RELIABLE = 0x01, // Don't bother rehashing.
STATUS_UNRELIABLE = 0x02, // Always recheck hash.
STATUS_MASK = 0x03,
STATUS_ALPHA_UNKNOWN = 0x04,
STATUS_ALPHA_FULL = 0x00, // Has no alpha channel, or always full alpha.
STATUS_ALPHA_MASK = 0x04,
@@ -184,6 +184,8 @@ struct TexCacheEntry {
u8 maxLevel;
u16 dim;
u16 bufw;
TexHashStatus hashStatus;
union {
GLRTexture *textureName;
void *texturePtr;
@@ -202,12 +204,6 @@ struct TexCacheEntry {
u16 maxSeenV;
ReplacedTexture *replacedTexture;
TexStatus GetHashStatus() {
return TexStatus(status & STATUS_MASK);
}
void SetHashStatus(TexStatus newStatus) {
status = (status & ~STATUS_MASK) | newStatus;
}
TexStatus GetAlphaStatus() {
return TexStatus(status & STATUS_ALPHA_MASK);
}
@@ -239,6 +235,7 @@ struct TexCacheEntry {
u32 EstimateTexMemoryUsage() const;
};
const char *TexHashStatusToString(TexHashStatus status);
std::string TexStatusToString(TexCacheEntry::TexStatus status);
// Can't be unordered_map, we use lower_bound ... although for some reason that (used to?) compiles on MSVC.
+1
View File
@@ -177,6 +177,7 @@ void DrawTexturesWindow(ImConfig &cfg, TextureCacheCommon *textureCache) {
ImGui::Image(texId, ImVec2(w, h));
ImGui::Text("%08x: %dx%d, %d mips, %s", (uint32_t)(cfg.selectedTexAddr & 0xFFFFFFFF), w, h, entry->maxLevel + 1, GeTextureFormatToString((GETextureFormat)entry->format));
ImGui::Text("Stride: %d", entry->bufw);
ImGui::Text("Hash status: %s", TexHashStatusToString(entry->hashStatus));
ImGui::Text("Status: %08x: %s", entry->status, TexStatusToString((TexCacheEntry::TexStatus)(entry->status)).c_str());
ImGui::Text("Hash: %08x", entry->fullhash);
ImGui::Text("CLUT Hash: %08x", entry->cluthash);