diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index f086e3013e..c5fb8428d8 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2115,7 +2115,8 @@ void TextureCacheCommon::ApplyTexture() { // Update the hash on the texture. int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); - entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + bool swizzled = gstate.isTextureSwizzled(); + entry->fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, swizzled, GETextureFormat(entry->format), entry); // TODO: Here we could check the secondary cache; maybe the texture is in there? // We would need to abort the build if so. @@ -2536,6 +2537,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) { int w = gstate.getTextureWidth(0); int h = gstate.getTextureHeight(0); bool isVideo = IsVideo(entry->addr); + bool swizzled = gstate.isTextureSwizzled(); // Don't even check the texture, just assume it has changed. if (isVideo && g_Config.bTextureBackoffCache) { @@ -2547,7 +2549,7 @@ bool TextureCacheCommon::CheckFullHash(TexCacheEntry *entry, bool &doDelete) { u32 fullhash; { PROFILE_THIS_SCOPE("texhash"); - fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, GETextureFormat(entry->format), entry); + fullhash = QuickTexHash(replacer_, entry->addr, entry->bufw, w, h, swizzled, GETextureFormat(entry->format), entry); } if (fullhash == entry->fullhash) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 372043870e..4666e3d92b 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -438,7 +438,7 @@ protected: static CheckAlphaResult CheckCLUTAlpha(const uint8_t *pixelData, GEPaletteFormat clutFmt, int w); - inline u32 QuickTexHash(TextureReplacer &replacer, u32 addr, int bufw, int w, int h, GETextureFormat format, const TexCacheEntry *entry) const { + static inline u32 QuickTexHash(TextureReplacer &replacer, u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat format, const TexCacheEntry *entry) { if (replacer.Enabled()) { return replacer.ComputeHash(addr, bufw, w, h, format, entry->maxSeenV); } @@ -447,7 +447,17 @@ protected: h = (int)entry->maxSeenV; } - const u32 sizeInRAM = (textureBitsPerPixel[format] * bufw * h) / 8; + u32 sizeInRAM; + if (swizzled) { + // In swizzle mode, textures are stored in rectangular blocks with the height 8. + // That means that for a 64x4 texture, like in issue #9308, we would only hash half of the texture! + // In theory, we should make sure to only hash half of each block, but in reality it's not likely that + // games are using that memory for anything else. So we'll just make sure to compute the full size to hash. + // To do that, we just use the same calculation but round the height upwards to the nearest multiple of 8. + sizeInRAM = (textureBitsPerPixel[format] * bufw * ((h + 7) & ~7)) >> 3; + } else { + sizeInRAM = (textureBitsPerPixel[format] * bufw * h) >> 3; + } const u32 *checkp = (const u32 *)Memory::GetPointer(addr); gpuStats.numTextureDataBytesHashed += sizeInRAM;