summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureCacheBase.cpp
diff options
context:
space:
mode:
authorDolphin Bot <dolphin-emu-bot@users.noreply.github.com>2016-06-17 18:31:03 +0200
committerGitHub <noreply@github.com>2016-06-17 18:31:03 +0200
commit847cb540d9d2113032c28fda71e8467f5a75579a (patch)
tree30fe00352cd52adda49d910887a8901b5e03da9b /Source/Core/VideoCommon/TextureCacheBase.cpp
parent08764c10e6c2bdbaa219ecf760e16a23da9a1471 (diff)
parent96ab76f81d264a0b76207b3303dbb336b6909cfc (diff)
Merge pull request #3902 from phire/lets_just_release_5_0_already
TextureCache: Track efb copies used in a partially updated texture (fixes regression for 5.0)
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp48
1 files changed, 34 insertions, 14 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index ee8491fb86..7d77f48392 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -162,7 +162,7 @@ void TextureCacheBase::Cleanup(int _frameCount)
if ((_frameCount - iter->second->frameCount) % TEXTURE_KILL_THRESHOLD == 1 &&
iter->second->hash != iter->second->CalculateHash())
{
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
}
else
{
@@ -171,7 +171,7 @@ void TextureCacheBase::Cleanup(int _frameCount)
}
else
{
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
}
}
else
@@ -282,7 +282,7 @@ void TextureCacheBase::ScaleTextureCacheEntryTo(TextureCacheBase::TCacheEntryBas
newentry->textures_by_hash_iter = textures_by_hash.emplace((*entry)->hash, newentry);
}
- FreeTexture(GetTexCacheIter(*entry));
+ InvalidateTexture(GetTexCacheIter(*entry));
*entry = newentry;
textures_by_address.emplace((*entry)->addr, *entry);
@@ -319,6 +319,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
TCacheEntryBase* entry = iter->second;
if (entry != entry_to_update
&& entry->IsEfbCopy()
+ && entry->references.count(entry_to_update) == 0
&& entry->OverlapsMemoryRange(entry_to_update->addr, entry_to_update->size_in_bytes)
&& entry->memory_stride == numBlocksX * block_size)
{
@@ -329,6 +330,8 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
TCacheEntryBase *decoded_entry = entry->ApplyPalette(palette, tlutfmt);
if (decoded_entry)
{
+ // Link the efb copy with the partially updated texture, so we won't apply this partial update again
+ entry->CreateReference(entry_to_update);
// Mark the texture update as used, as if it was loaded directly
entry->frameCount = FRAMECOUNT_INVALID;
entry = decoded_entry;
@@ -394,17 +397,26 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::DoPartialTextureUpdates(Tex
dstrect.right = (dst_x + copy_width);
dstrect.bottom = (dst_y + copy_height);
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));
+ {
+ // Remove the temporary converted texture, it won't be used anywhere else
+ // TODO: It would be nice to convert and copy in one step, but this code path isn't common
+ InvalidateTexture(GetTexCacheIter(entry));
+ }
+ else
+ {
+ // Link the two textures together, so we won't apply this partial update again
+ entry->CreateReference(entry_to_update);
+ // Mark the texture update as used, as if it was loaded directly
+ entry->frameCount = FRAMECOUNT_INVALID;
+ }
}
else
{
// If the hash does not match, this EFB copy will not be used for anything, so remove it
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
continue;
}
}
@@ -612,7 +624,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
// never be useful again. It's theoretically possible for a game to do
// something weird where the copy could become useful in the future, but in
// practice it doesn't happen.
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
continue;
}
}
@@ -680,7 +692,7 @@ TextureCacheBase::TCacheEntryBase* TextureCacheBase::Load(const u32 stage)
if (temp_frameCount != 0x7fffffff)
{
// pool this texture and make a new one later
- FreeTexture(oldest_entry);
+ InvalidateTexture(oldest_entry);
}
std::shared_ptr<HiresTexture> hires_tex;
@@ -1128,13 +1140,17 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
unsigned int scaled_tex_w = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledX(tex_w) : tex_w;
unsigned int scaled_tex_h = g_ActiveConfig.bCopyEFBScaled ? Renderer::EFBToScaledY(tex_h) : tex_h;
- // remove all texture cache entries at dstAddr
+ // Remove all texture cache entries at dstAddr
+ // It's not possible to have two EFB copies at the same address, this makes sure any old efb copies
+ // (or normal textures) are removed from texture cache. They are also un-linked from any partially
+ // updated textures, which forces that partially updated texture to be updated.
+ // TODO: This also wipes out non-efb copies, which is counterproductive.
{
std::pair<TexCache::iterator, TexCache::iterator> iter_range = textures_by_address.equal_range((u64)dstAddr);
TexCache::iterator iter = iter_range.first;
while (iter != iter_range.second)
{
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
}
}
@@ -1215,6 +1231,8 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
// Invalidate all textures that overlap the range of our efb copy.
// Unless our efb copy has a weird stride, then we want avoid invalidating textures which
// we might be able to do a partial texture update on.
+ // TODO: This also invalidates partial overlaps, which we currently don't have a better way
+ // of dealing with.
if (dstStride == bytes_per_row || !copy_to_vram)
{
TexCache::iterator iter = textures_by_address.begin();
@@ -1223,7 +1241,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
if (iter->second->addr + iter->second->size_in_bytes <= dstAddr || iter->second->addr >= dstAddr + num_blocks_y * dstStride)
++iter;
else
- iter = FreeTexture(iter);
+ iter = InvalidateTexture(iter);
}
}
@@ -1301,7 +1319,7 @@ TextureCacheBase::TexCache::iterator TextureCacheBase::GetTexCacheIter(TextureCa
return textures_by_address.end();
}
-TextureCacheBase::TexCache::iterator TextureCacheBase::FreeTexture(TexCache::iterator iter)
+TextureCacheBase::TexCache::iterator TextureCacheBase::InvalidateTexture(TexCache::iterator iter)
{
if (iter == textures_by_address.end())
return textures_by_address.end();
@@ -1314,6 +1332,8 @@ TextureCacheBase::TexCache::iterator TextureCacheBase::FreeTexture(TexCache::ite
entry->textures_by_hash_iter = textures_by_hash.end();
}
+ entry->DestroyAllReferences();
+
entry->frameCount = FRAMECOUNT_INVALID;
texture_pool.emplace(entry->config, entry);