Render: Implemented simple render target pool
This avoids creating and destroying render targets every frame, which is a significant CPU overhead. Old render targets are destroyed after 3 frames.
This commit is contained in:
parent
830a03c540
commit
d8d9bc8c6c
|
@ -22,6 +22,7 @@
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TEXTURE_KILL_THRESHOLD = 200,
|
TEXTURE_KILL_THRESHOLD = 200,
|
||||||
|
RENDER_TARGET_KILL_THRESHOLD = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
TextureCache *g_texture_cache;
|
TextureCache *g_texture_cache;
|
||||||
|
@ -30,6 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr;
|
||||||
unsigned int TextureCache::temp_size;
|
unsigned int TextureCache::temp_size;
|
||||||
|
|
||||||
TextureCache::TexCache TextureCache::textures;
|
TextureCache::TexCache TextureCache::textures;
|
||||||
|
TextureCache::RenderTargetPool TextureCache::render_target_pool;
|
||||||
|
|
||||||
TextureCache::BackupConfig TextureCache::backup_config;
|
TextureCache::BackupConfig TextureCache::backup_config;
|
||||||
|
|
||||||
|
@ -67,6 +69,12 @@ void TextureCache::Invalidate()
|
||||||
delete tex.second;
|
delete tex.second;
|
||||||
}
|
}
|
||||||
textures.clear();
|
textures.clear();
|
||||||
|
|
||||||
|
for (auto& rt : render_target_pool)
|
||||||
|
{
|
||||||
|
delete rt;
|
||||||
|
}
|
||||||
|
render_target_pool.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureCache::~TextureCache()
|
TextureCache::~TextureCache()
|
||||||
|
@ -138,6 +146,22 @@ void TextureCache::Cleanup()
|
||||||
++iter;
|
++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)
|
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))
|
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
|
if (entry->type == TCET_EC_VRAM)
|
||||||
delete entry;
|
{
|
||||||
|
// try to re-use this render target later
|
||||||
|
FreeRenderTarget(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// remove it and recreate it as a render target
|
||||||
|
delete entry;
|
||||||
|
}
|
||||||
|
|
||||||
entry = nullptr;
|
entry = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -877,7 +910,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||||
if (nullptr == entry)
|
if (nullptr == entry)
|
||||||
{
|
{
|
||||||
// create the texture
|
// 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...
|
// TODO: Using the wrong dstFormat, dumb...
|
||||||
entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1);
|
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);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -119,9 +119,14 @@ private:
|
||||||
static PC_TexFormat LoadCustomTexture(u64 tex_hash, int texformat, unsigned int level, unsigned int& width, unsigned int& height);
|
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 void DumpTexture(TCacheEntryBase* entry, unsigned int level);
|
||||||
|
|
||||||
|
static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height);
|
||||||
|
static void FreeRenderTarget(TCacheEntryBase* entry);
|
||||||
|
|
||||||
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
typedef std::map<u32, TCacheEntryBase*> TexCache;
|
||||||
|
typedef std::vector<TCacheEntryBase*> RenderTargetPool;
|
||||||
|
|
||||||
static TexCache textures;
|
static TexCache textures;
|
||||||
|
static RenderTargetPool render_target_pool;
|
||||||
|
|
||||||
// Backup configuration values
|
// Backup configuration values
|
||||||
static struct BackupConfig
|
static struct BackupConfig
|
||||||
|
|
Loading…
Reference in New Issue