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.
This commit is contained in:
parent
abb5a64919
commit
b6d09c61ed
|
@ -1353,7 +1353,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFo
|
||||||
TextureCacheBase::TCacheEntryBase*
|
TextureCacheBase::TCacheEntryBase*
|
||||||
TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
|
TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
|
||||||
{
|
{
|
||||||
TexPool::iterator iter = texture_pool.find(config);
|
TexPool::iterator iter = FindMatchingTextureFromPool(config);
|
||||||
TextureCacheBase::TCacheEntryBase* entry;
|
TextureCacheBase::TCacheEntryBase* entry;
|
||||||
if (iter != texture_pool.end())
|
if (iter != texture_pool.end())
|
||||||
{
|
{
|
||||||
|
@ -1373,6 +1373,19 @@ TextureCacheBase::AllocateTexture(const TCacheEntryConfig& config)
|
||||||
return entry;
|
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::TexCache::iterator
|
||||||
TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry)
|
TextureCacheBase::GetTexCacheIter(TextureCacheBase::TCacheEntryBase* entry)
|
||||||
{
|
{
|
||||||
|
|
|
@ -193,6 +193,7 @@ private:
|
||||||
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 TexPool::iterator FindMatchingTextureFromPool(const TCacheEntryConfig& config);
|
||||||
static TexCache::iterator GetTexCacheIter(TCacheEntryBase* entry);
|
static TexCache::iterator GetTexCacheIter(TCacheEntryBase* entry);
|
||||||
|
|
||||||
// Removes and unlinks texture from texture cache and returns it to the pool
|
// Removes and unlinks texture from texture cache and returns it to the pool
|
||||||
|
|
Loading…
Reference in New Issue