summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/TextureCacheBase.cpp
diff options
context:
space:
mode:
authorStenzek <stenzek@gmail.com>2016-10-06 00:27:02 +1000
committerStenzek <stenzek@gmail.com>2016-10-06 20:23:37 +1000
commitb6d09c61ed328259f2e43bc9e14ad725d8ba0017 (patch)
treebeb6f75982050daa3f18a51e7fc057355d3071ee /Source/Core/VideoCommon/TextureCacheBase.cpp
parentabb5a64919f0425db5f282803eda43b764282482 (diff)
TextureCache: Don't re-use pooled textures within the same frame
This is an issue because a driver may have to maintain two copies of a texture if it batches all uploads together at the start of a frame. In the Vulkan backend, we do something similar to avoid breaking out of a render pass to copy a texture from the streaming buffer to the destination image. This was causing issues in the sms-bubbles fifolog, where an EFB copy to the same address of a previously-used texture caused the previous texture to be re-used again for a different image later on in the frame, causing the original contents to be discarded.
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
-rw-r--r--Source/Core/VideoCommon/TextureCacheBase.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp
index 39af7f155c..0f8a39b341 100644
--- a/Source/Core/VideoCommon/TextureCacheBase.cpp
+++ b/Source/Core/VideoCommon/TextureCacheBase.cpp
@@ -1353,7 +1353,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
TextureCacheBase::TCacheEntryBase*
TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
{
- TexPool::iterator iter = texture_pool.find(config);
+ TexPool::iterator iter = FindMatchingTextureFromPool(config);
TextureCacheBase::TCacheEntryBase* entry;
if (iter != texture_pool.end())
{
@@ -1373,6 +1373,19 @@ TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
return entry;
}
+TextureCacheBase::TexPool::iterator
+TextureCacheBase::FindMatchingTextureFromPool(const TCacheEntryConfig& config)
+{
+ // Find a texture from the pool that does not have a frameCount of FRAMECOUNT_INVALID.
+ // This prevents a texture from being used twice in a single frame with different data,
+ // which potentially means that a driver has to maintain two copies of the texture anyway.
+ auto range = texture_pool.equal_range(config);
+ auto matching_iter = std::find_if(range.first, range.second, [](const auto& iter) {
+ return iter.second->frameCount != FRAMECOUNT_INVALID;
+ });
+ return matching_iter != range.second ? matching_iter : texture_pool.end();
+}
+
TextureCacheBase::TexCache::iterator
TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry)
{