From 9f625417c060c2c43e0b321d283d2c288cc84ce0 Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Sat, 26 Mar 2016 03:43:32 +0100 Subject: [PATCH] Partial updates for paletted textures This pr fixes another regression that happened after pr #3165 was merged. The shadows in mario baseball should now work again. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 113 ++++++++++++------- Source/Core/VideoCommon/TextureCacheBase.h | 5 +- 2 files changed, 77 insertions(+), 41 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 1503b2461b..ee8491fb86 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -211,6 +211,32 @@ bool TextureCacheBase::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u return true; } +TextureCacheBase::TCacheEntryBase* TextureCacheBase::TCacheEntryBase::ApplyPalette(u8* palette, u32 tlutfmt) +{ + TCacheEntryConfig newconfig; + newconfig.rendertarget = true; + newconfig.width = config.width; + newconfig.height = config.height; + newconfig.layers = config.layers; + TCacheEntryBase *decoded_entry = AllocateTexture(newconfig); + + if (decoded_entry) + { + decoded_entry->SetGeneralParameters(addr, size_in_bytes, format); + decoded_entry->SetDimensions(native_width, native_height, 1); + decoded_entry->SetHashes(base_hash, hash); + decoded_entry->frameCount = FRAMECOUNT_INVALID; + decoded_entry->is_efb_copy = false; + + g_texture_cache->ConvertTexture(decoded_entry, this, palette, static_cast(tlutfmt)); + textures_by_address.emplace(addr, decoded_entry); + + return decoded_entry; + } + + return nullptr; +} + void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBase** entry, u32 new_width, u32 new_height) { if ((*entry)->config.width == new_width && (*entry)->config.height == new_height) @@ -256,21 +282,7 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas newentry->textures_by_hash_iter = textures_by_hash.emplace((*entry)->hash, newentry); } - // Remove the old texture - std::pairiter_range = textures_by_address.equal_range((*entry)->addr); - TexCache::iterator iter = iter_range.first; - while (iter != iter_range.second) - { - if (iter->second == *entry) - { - FreeTexture(iter); - iter = iter_range.second; - } - else - { - iter++; - } - } + FreeTexture(GetTexCacheIter(*entry)); *entry = newentry; textures_by_address.emplace((*entry)->addr, *entry); @@ -281,7 +293,7 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas } } -TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(TexCache::iterator iter_t) +TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(TexCache::iterator iter_t, u8* palette, u32 tlutfmt) { TCacheEntryBase* entry_to_update = iter_t->second; const bool isPaletteTexture = (entry_to_update->format == GX_TF_C4 @@ -289,10 +301,9 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex || entry_to_update->format == GX_TF_C14X2 || entry_to_update->format >= 0x10000); - // Efb copies and paletted textures are excluded from these updates, until there's an example where a game would - // benefit from this. Both would require more work to be done. - if (entry_to_update->IsEfbCopy() - || isPaletteTexture) + // EFB copies are excluded from these updates, until there's an example where a game would + // benefit from updating. This would require more work to be done. + if (entry_to_update->IsEfbCopy()) return entry_to_update; u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format & 0xf); @@ -313,6 +324,22 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex { if (entry->hash == entry->CalculateHash()) { + if (isPaletteTexture) + { + TCacheEntryBase *decoded_entry = entry->ApplyPalette(palette, tlutfmt); + if (decoded_entry) + { + // Mark the texture update as used, as if it was loaded directly + entry->frameCount = FRAMECOUNT_INVALID; + entry = decoded_entry; + } + else + { + ++iter; + continue; + } + } + u32 src_x, src_y, dst_x, dst_y; // Note for understanding the math: @@ -369,6 +396,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect); // Mark the texture update as used, as if it was loaded directly entry->frameCount = FRAMECOUNT_INVALID; + + // Remove the converted texture, it won't be used anywhere else + if (isPaletteTexture) + FreeTexture(GetTexCacheIter(entry)); } else { @@ -591,7 +622,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage) if (entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { - entry = DoPartialTextureUpdates(iter); + entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt); return ReturnEntry(stage, entry); } @@ -613,26 +644,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage) if (unconverted_copy != textures_by_address.end()) { - // Perform palette decoding. - TCacheEntryBase *entry = unconverted_copy->second; - - TCacheEntryConfig config; - config.rendertarget = true; - config.width = entry->config.width; - config.height = entry->config.height; - config.layers = FramebufferManagerBase::GetEFBLayers(); - TCacheEntryBase *decoded_entry = AllocateTexture(config); + TCacheEntryBase* decoded_entry = unconverted_copy->second->ApplyPalette(&texMem[tlutaddr], tlutfmt); if (decoded_entry) { - decoded_entry->SetGeneralParameters(address, texture_size, full_format); - decoded_entry->SetDimensions(entry->native_width, entry->native_height, 1); - decoded_entry->SetHashes(base_hash, full_hash); - decoded_entry->frameCount = FRAMECOUNT_INVALID; - decoded_entry->is_efb_copy = false; - - g_texture_cache->ConvertTexture(decoded_entry, entry, &texMem[tlutaddr], (TlutFormat)tlutfmt); - textures_by_address.emplace((u64)address, decoded_entry); return ReturnEntry(stage, decoded_entry); } } @@ -653,7 +668,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage) if (entry->format == full_format && entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { - entry = DoPartialTextureUpdates(iter); + entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt); return ReturnEntry(stage, entry); } @@ -798,7 +813,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage) INCSTAT(stats.numTexturesUploaded); SETSTAT(stats.numTexturesAlive, textures_by_address.size()); - entry = DoPartialTextureUpdates(iter); + entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt); return ReturnEntry(stage, entry); } @@ -1271,8 +1286,26 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::AllocateTexture(const TCach return entry; } +TextureCacheBase::TexCache::iterator TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry) +{ + std::pairiter_range = textures_by_address.equal_range(entry->addr); + TexCache::iterator iter = iter_range.first; + while (iter != iter_range.second) + { + if (iter->second == entry) + { + return iter; + } + ++iter; + } + return textures_by_address.end(); +} + TextureCacheBase::TexCache::iterator TextureCacheBase::FreeTexture(TexCache::iterator iter) { + if (iter == textures_by_address.end()) + return textures_by_address.end(); + TCacheEntryBase* entry = iter->second; if (entry->textures_by_hash_iter != textures_by_hash.end()) diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index a997ff64bd..e87dfc29d1 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -109,6 +109,8 @@ public: bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; + TextureCacheBase::TCacheEntryBase* ApplyPalette(u8* palette, u32 tlutfmt); + bool IsEfbCopy() const { return is_efb_copy; } u32 NumBlocksY() const; @@ -156,11 +158,12 @@ private: typedef std::multimap TexCache; typedef std::unordered_multimap TexPool; static void ScaleTextureCacheEntryTo(TCacheEntryBase** entry, u32 new_width, u32 new_height); - static TCacheEntryBase* DoPartialTextureUpdates(TexCache::iterator iter); + static TCacheEntryBase* DoPartialTextureUpdates(TexCache::iterator iter, u8* palette, u32 tlutfmt); static void DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level); static void CheckTempSize(size_t required_size); static TCacheEntryBase* AllocateTexture(const TCacheEntryConfig& config); + static TexCache::iterator GetTexCacheIter(TCacheEntryBase* entry); static TexCache::iterator FreeTexture(TexCache::iterator t_iter); static TCacheEntryBase* ReturnEntry(unsigned int stage, TCacheEntryBase* entry);