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.
This commit is contained in:
parent
e98fb0af84
commit
9f625417c0
|
@ -211,6 +211,32 @@ bool TextureCacheBase::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u
|
||||||
return true;
|
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<TlutFormat>(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)
|
void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBase** entry, u32 new_width, u32 new_height)
|
||||||
{
|
{
|
||||||
if ((*entry)->config.width == new_width && (*entry)->config.height == 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);
|
newentry->textures_by_hash_iter = textures_by_hash.emplace((*entry)->hash, newentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the old texture
|
FreeTexture(GetTexCacheIter(*entry));
|
||||||
std::pair<TexCache::iterator, TexCache::iterator>iter_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++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*entry = newentry;
|
*entry = newentry;
|
||||||
textures_by_address.emplace((*entry)->addr, *entry);
|
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;
|
TCacheEntryBase* entry_to_update = iter_t->second;
|
||||||
const bool isPaletteTexture = (entry_to_update->format == GX_TF_C4
|
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 == GX_TF_C14X2
|
||||||
|| entry_to_update->format >= 0x10000);
|
|| entry_to_update->format >= 0x10000);
|
||||||
|
|
||||||
// Efb copies and paletted textures are excluded from these updates, until there's an example where a game would
|
// EFB copies 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.
|
// benefit from updating. This would require more work to be done.
|
||||||
if (entry_to_update->IsEfbCopy()
|
if (entry_to_update->IsEfbCopy())
|
||||||
|| isPaletteTexture)
|
|
||||||
return entry_to_update;
|
return entry_to_update;
|
||||||
|
|
||||||
u32 block_width = TexDecoder_GetBlockWidthInTexels(entry_to_update->format & 0xf);
|
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 (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;
|
u32 src_x, src_y, dst_x, dst_y;
|
||||||
|
|
||||||
// Note for understanding the math:
|
// Note for understanding the math:
|
||||||
|
@ -369,6 +396,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
|
||||||
entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect);
|
entry_to_update->CopyRectangleFromTexture(entry, srcrect, dstrect);
|
||||||
// Mark the texture update as used, as if it was loaded directly
|
// Mark the texture update as used, as if it was loaded directly
|
||||||
entry->frameCount = FRAMECOUNT_INVALID;
|
entry->frameCount = FRAMECOUNT_INVALID;
|
||||||
|
|
||||||
|
// Remove the converted texture, it won't be used anywhere else
|
||||||
|
if (isPaletteTexture)
|
||||||
|
FreeTexture(GetTexCacheIter(entry));
|
||||||
}
|
}
|
||||||
else
|
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 &&
|
if (entry->hash == full_hash && entry->format == full_format && entry->native_levels >= tex_levels &&
|
||||||
entry->native_width == nativeW && entry->native_height == nativeH)
|
entry->native_width == nativeW && entry->native_height == nativeH)
|
||||||
{
|
{
|
||||||
entry = DoPartialTextureUpdates(iter);
|
entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt);
|
||||||
|
|
||||||
return ReturnEntry(stage, entry);
|
return ReturnEntry(stage, entry);
|
||||||
}
|
}
|
||||||
|
@ -613,26 +644,10 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
||||||
|
|
||||||
if (unconverted_copy != textures_by_address.end())
|
if (unconverted_copy != textures_by_address.end())
|
||||||
{
|
{
|
||||||
// Perform palette decoding.
|
TCacheEntryBase* decoded_entry = unconverted_copy->second->ApplyPalette(&texMem[tlutaddr], tlutfmt);
|
||||||
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);
|
|
||||||
|
|
||||||
if (decoded_entry)
|
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);
|
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 &&
|
if (entry->format == full_format && entry->native_levels >= tex_levels &&
|
||||||
entry->native_width == nativeW && entry->native_height == nativeH)
|
entry->native_width == nativeW && entry->native_height == nativeH)
|
||||||
{
|
{
|
||||||
entry = DoPartialTextureUpdates(iter);
|
entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt);
|
||||||
|
|
||||||
return ReturnEntry(stage, entry);
|
return ReturnEntry(stage, entry);
|
||||||
}
|
}
|
||||||
|
@ -798,7 +813,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
|
||||||
INCSTAT(stats.numTexturesUploaded);
|
INCSTAT(stats.numTexturesUploaded);
|
||||||
SETSTAT(stats.numTexturesAlive, textures_by_address.size());
|
SETSTAT(stats.numTexturesAlive, textures_by_address.size());
|
||||||
|
|
||||||
entry = DoPartialTextureUpdates(iter);
|
entry = DoPartialTextureUpdates(iter, &texMem[tlutaddr], tlutfmt);
|
||||||
|
|
||||||
return ReturnEntry(stage, entry);
|
return ReturnEntry(stage, entry);
|
||||||
}
|
}
|
||||||
|
@ -1271,8 +1286,26 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::AllocateTexture(const TCach
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextureCacheBase::TexCache::iterator TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry)
|
||||||
|
{
|
||||||
|
std::pair<TexCache::iterator, TexCache::iterator>iter_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)
|
TextureCacheBase::TexCache::iterator TextureCacheBase::FreeTexture(TexCache::iterator iter)
|
||||||
{
|
{
|
||||||
|
if (iter == textures_by_address.end())
|
||||||
|
return textures_by_address.end();
|
||||||
|
|
||||||
TCacheEntryBase* entry = iter->second;
|
TCacheEntryBase* entry = iter->second;
|
||||||
|
|
||||||
if (entry->textures_by_hash_iter != textures_by_hash.end())
|
if (entry->textures_by_hash_iter != textures_by_hash.end())
|
||||||
|
|
|
@ -109,6 +109,8 @@ public:
|
||||||
|
|
||||||
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
bool OverlapsMemoryRange(u32 range_address, u32 range_size) const;
|
||||||
|
|
||||||
|
TextureCacheBase::TCacheEntryBase* ApplyPalette(u8* palette, u32 tlutfmt);
|
||||||
|
|
||||||
bool IsEfbCopy() const { return is_efb_copy; }
|
bool IsEfbCopy() const { return is_efb_copy; }
|
||||||
|
|
||||||
u32 NumBlocksY() const;
|
u32 NumBlocksY() const;
|
||||||
|
@ -156,11 +158,12 @@ private:
|
||||||
typedef std::multimap<u64, TCacheEntryBase*> TexCache;
|
typedef std::multimap<u64, TCacheEntryBase*> TexCache;
|
||||||
typedef std::unordered_multimap<TCacheEntryConfig, TCacheEntryBase*, TCacheEntryConfig::Hasher> TexPool;
|
typedef std::unordered_multimap<TCacheEntryConfig, TCacheEntryBase*, TCacheEntryConfig::Hasher> TexPool;
|
||||||
static void ScaleTextureCacheEntryTo(TCacheEntryBase** entry, u32 new_width, u32 new_height);
|
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 DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level);
|
||||||
static void CheckTempSize(size_t required_size);
|
static void CheckTempSize(size_t required_size);
|
||||||
|
|
||||||
static TCacheEntryBase* AllocateTexture(const TCacheEntryConfig& config);
|
static TCacheEntryBase* AllocateTexture(const TCacheEntryConfig& config);
|
||||||
|
static TexCache::iterator GetTexCacheIter(TCacheEntryBase* entry);
|
||||||
static TexCache::iterator FreeTexture(TexCache::iterator t_iter);
|
static TexCache::iterator FreeTexture(TexCache::iterator t_iter);
|
||||||
|
|
||||||
static TCacheEntryBase* ReturnEntry(unsigned int stage, TCacheEntryBase* entry);
|
static TCacheEntryBase* ReturnEntry(unsigned int stage, TCacheEntryBase* entry);
|
||||||
|
|
Loading…
Reference in New Issue