diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 34345f20a1..b8670a66f2 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -1145,67 +1145,22 @@ void TextureCache::SetTexture(bool force) { rehash = true; } - bool hashFail = false; if (texhash != entry->hash) { - fullhash = QuickTexHash(replacer, texaddr, bufw, w, h, format, entry); - hashFail = true; + match = false; + } else if (entry->GetHashStatus() == TexCacheEntry::STATUS_RELIABLE) { rehash = false; } - if (rehash && entry->GetHashStatus() != TexCacheEntry::STATUS_RELIABLE) { - fullhash = QuickTexHash(replacer, texaddr, bufw, w, h, format, entry); - if (fullhash != entry->fullhash) { - hashFail = true; - } else { - if (g_Config.bTextureBackoffCache) { - if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) { - // Reset to STATUS_HASHING. - entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) { - entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - } - - if (hashFail) { - match = false; - reason = "hash fail"; - entry->status |= TexCacheEntry::STATUS_UNRELIABLE; - if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) { - if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) { - entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE; - } else { - entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; - } - } - entry->numFrames = 0; - - // Don't give up just yet. Let's try the secondary cache if it's been invalidated before. - // If it's failed a bunch of times, then the second cache is just wasting time and VRAM. - if (g_Config.bTextureSecondaryCache) { - if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { - u64 secondKey = fullhash | (u64)cluthash << 32; - TexCache::iterator secondIter = secondCache.find(secondKey); - if (secondIter != secondCache.end()) { - TexCacheEntry *secondEntry = &secondIter->second; - if (secondEntry->Matches(dim, format, maxLevel)) { - // Reset the numInvalidated value lower, we got a match. - if (entry->numInvalidated > 8) { - --entry->numInvalidated; - } - entry = secondEntry; - match = true; - } - } else { - secondKey = entry->fullhash | ((u64)entry->cluthash << 32); - secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); - secondCache[secondKey] = *entry; - doDelete = false; - } - } + if (rehash) { + if (!CheckFullHash(entry, doDelete)) { + match = false; + } else if (nextTexture_ != nullptr) { + // Secondary cache picked a different texture, use it. + entry = nextTexture_; + nextTexture_ = nullptr; } + // CheckFullHash updated the entry's fullhash value. + fullhash = entry->fullhash; } } @@ -1274,6 +1229,69 @@ void TextureCache::SetTexture(bool force) { BuildTexture(entry, replaceImages); } +bool TextureCache::CheckFullHash(TexCacheEntry *const entry, bool &doDelete) { + bool hashFail = false; + int w = gstate.getTextureWidth(0); + int h = gstate.getTextureHeight(0); + u32 fullhash = QuickTexHash(replacer, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + if (fullhash != entry->fullhash) { + hashFail = true; + } else { + if (g_Config.bTextureBackoffCache) { + if (entry->GetHashStatus() != TexCacheEntry::STATUS_HASHING && entry->numFrames > TexCacheEntry::FRAMES_REGAIN_TRUST) { + // Reset to STATUS_HASHING. + entry->SetHashStatus(TexCacheEntry::STATUS_HASHING); + entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; + } + } else if (entry->numFrames > TEXCACHE_FRAME_CHANGE_FREQUENT_REGAIN_TRUST) { + entry->status &= ~TexCacheEntry::STATUS_CHANGE_FREQUENT; + } + } + + if (hashFail) { + entry->status |= TexCacheEntry::STATUS_UNRELIABLE; + if (entry->numFrames < TEXCACHE_FRAME_CHANGE_FREQUENT) { + if (entry->status & TexCacheEntry::STATUS_FREE_CHANGE) { + entry->status &= ~TexCacheEntry::STATUS_FREE_CHANGE; + } else { + entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; + } + } + entry->numFrames = 0; + + // Don't give up just yet. Let's try the secondary cache if it's been invalidated before. + // If it's failed a bunch of times, then the second cache is just wasting time and VRAM. + if (g_Config.bTextureSecondaryCache) { + if (entry->numInvalidated > 2 && entry->numInvalidated < 128 && !lowMemoryMode_) { + u64 secondKey = fullhash | (u64)entry->cluthash << 32; + TexCache::iterator secondIter = secondCache.find(secondKey); + if (secondIter != secondCache.end()) { + TexCacheEntry *secondEntry = &secondIter->second; + if (secondEntry->Matches(entry->dim, entry->format, entry->maxLevel)) { + // Reset the numInvalidated value lower, we got a match. + if (entry->numInvalidated > 8) { + --entry->numInvalidated; + } + nextTexture_ = secondEntry; + return true; + } + } else { + secondKey = entry->fullhash | ((u64)entry->cluthash << 32); + secondCacheSizeEstimate_ += EstimateTexMemoryUsage(entry); + secondCache[secondKey] = *entry; + doDelete = false; + } + } + } + + // We know it failed, so update the full hash right away. + entry->fullhash = fullhash; + return false; + } + + return true; +} + bool TextureCache::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) { bool replaceImages = false; diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 0a5b10e867..e037f36f7e 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -107,6 +107,7 @@ private: void SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); void ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffer *framebuffer); + bool CheckFullHash(TexCacheEntry *const entry, bool &doDelete); bool HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete); void BuildTexture(TexCacheEntry *const entry, bool replaceImages);