diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 9e8cb9387f..0bbc336a31 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -22,6 +22,7 @@ enum { TEXTURE_KILL_THRESHOLD = 200, + RENDER_TARGET_KILL_THRESHOLD = 3, }; TextureCache *g_texture_cache; @@ -30,6 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr; unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; +TextureCache::RenderTargetPool TextureCache::render_target_pool; TextureCache::BackupConfig TextureCache::backup_config; @@ -67,6 +69,12 @@ void TextureCache::Invalidate() delete tex.second; } textures.clear(); + + for (auto& rt : render_target_pool) + { + delete rt; + } + render_target_pool.clear(); } TextureCache::~TextureCache() @@ -138,6 +146,22 @@ void TextureCache::Cleanup() ++iter; } } + + for (size_t i = 0; i < render_target_pool.size();) + { + auto rt = render_target_pool[i]; + + if (frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) + { + delete rt; + render_target_pool[i] = render_target_pool.back(); + render_target_pool.pop_back(); + } + else + { + ++i; + } + } } void TextureCache::InvalidateRange(u32 start_address, u32 size) @@ -868,8 +892,17 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat } else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) { - // remove it and recreate it as a render target - delete entry; + if (entry->type == TCET_EC_VRAM) + { + // try to re-use this render target later + FreeRenderTarget(entry); + } + else + { + // remove it and recreate it as a render target + delete entry; + } + entry = nullptr; } } @@ -877,7 +910,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (nullptr == entry) { // create the texture - textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); + textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); @@ -890,3 +923,26 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } + +TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height) +{ + for (size_t i = 0; i < render_target_pool.size(); ++i) + { + auto rt = render_target_pool[i]; + + if (rt->virtual_width != width || rt->virtual_height != height) + continue; + + render_target_pool[i] = render_target_pool.back(); + render_target_pool.pop_back(); + + return rt; + } + + return g_texture_cache->CreateRenderTargetTexture(width, height); +} + +void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) +{ + render_target_pool.push_back(entry); +} diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index f5229f72ff..eb13096624 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -119,9 +119,14 @@ private: static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height); static void DumpTexture(TCacheEntryBase* entry, unsigned int level); + static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height); + static void FreeRenderTarget(TCacheEntryBase* entry); + typedef std::map TexCache; + typedef std::vector RenderTargetPool; static TexCache textures; + static RenderTargetPool render_target_pool; // Backup configuration values static struct BackupConfig