Improve safe texture cache - now using sparse CRC to identify textures. Far less video glitches - metroid intro looks good.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1298 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2008-11-25 23:56:57 +00:00
parent a95e804681
commit d0a48f654a
3 changed files with 33 additions and 5 deletions

View File

@ -57,6 +57,29 @@ int TexDecoder_GetTexelSizeInNibbles(int format)
} }
} }
int TexDecoder_GetTextureSizeInBytes(int width, int height, int format)
{
return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 4;
}
u32 TexDecoder_GetSafeTextureHash(const u8 *src, int width, int height, int texformat)
{
int sz = TexDecoder_GetTextureSizeInBytes(width, height, texformat);
u32 hash = 0x1337c0de;
if (sz < 2048) {
for (int i = 0; i < sz / 4; i += 13) {
hash = _rotl(hash, 17) ^ ((u32 *)src)[i];
}
return hash;
} else {
int step = sz / 13 / 4;
for (int i = 0; i < sz / 4; i += step) {
hash = _rotl(hash, 17) ^ ((u32 *)src)[i];
}
}
return hash;
}
int TexDecoder_GetBlockWidthInTexels(int format) int TexDecoder_GetBlockWidthInTexels(int format)
{ {
switch (format) { switch (format) {

View File

@ -65,6 +65,7 @@ enum TextureFormat
}; };
int TexDecoder_GetTexelSizeInNibbles(int format); int TexDecoder_GetTexelSizeInNibbles(int format);
int TexDecoder_GetTextureSizeInBytes(int width, int height, int format);
int TexDecoder_GetBlockWidthInTexels(int format); int TexDecoder_GetBlockWidthInTexels(int format);
int TexDecoder_GetPaletteSize(int fmt); int TexDecoder_GetPaletteSize(int fmt);
@ -76,6 +77,8 @@ enum PC_TexFormat
PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt); PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt);
u32 TexDecoder_GetSafeTextureHash(const u8 *src, int width, int height, int texformat);
void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center); void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center);
#endif #endif

View File

@ -217,10 +217,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
} }
} }
int bs = TexDecoder_GetBlockWidthInTexels(format) - 1;
int expandedWidth = (width + bs) & (~bs);
if (iter != textures.end()) { if (iter != textures.end()) {
TCacheEntry &entry = iter->second; TCacheEntry &entry = iter->second;
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) { //stupid, improve if (entry.isRenderTarget ||
(TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format) == entry.hash &&
palhash == entry.paletteHash)) {
entry.frameCount = frameCount; entry.frameCount = frameCount;
//glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D);
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture); glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture);
@ -251,18 +256,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
} }
} }
int bs = TexDecoder_GetBlockWidthInTexels(format) - 1;
int expandedWidth = (width + bs) & (~bs);
PC_TexFormat dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt); PC_TexFormat dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt);
//Make an entry in the table //Make an entry in the table
TCacheEntry& entry = textures[address]; TCacheEntry& entry = textures[address];
entry.hashoffset = 0;
entry.paletteHash = palhash; entry.paletteHash = palhash;
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
if (g_Config.bSafeTextureCache) { if (g_Config.bSafeTextureCache) {
entry.hash = entry.oldpixel; entry.hash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format);
} else { } else {
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
((u32 *)ptr)[entry.hashoffset] = entry.hash; ((u32 *)ptr)[entry.hashoffset] = entry.hash;