TexCache: also incude textures within the render target pool

This commit is contained in:
degasus 2015-01-17 10:29:10 +01:00
parent 6cd6e6546f
commit 4639d3b1bc
4 changed files with 49 additions and 50 deletions

View File

@ -28,6 +28,7 @@ std::string Statistics::ToString()
{ {
std::string str; std::string str;
str += StringFromFormat("Textures created: %i\n", stats.numTexturesCreated); str += StringFromFormat("Textures created: %i\n", stats.numTexturesCreated);
str += StringFromFormat("Textures uploaded: %i\n", stats.numTexturesUploaded);
str += StringFromFormat("Textures alive: %i\n", stats.numTexturesAlive); str += StringFromFormat("Textures alive: %i\n", stats.numTexturesAlive);
str += StringFromFormat("pshaders created: %i\n", stats.numPixelShadersCreated); str += StringFromFormat("pshaders created: %i\n", stats.numPixelShadersCreated);
str += StringFromFormat("pshaders alive: %i\n", stats.numPixelShadersAlive); str += StringFromFormat("pshaders alive: %i\n", stats.numPixelShadersAlive);

View File

@ -18,6 +18,7 @@ struct Statistics
int numVertexShadersAlive; int numVertexShadersAlive;
int numTexturesCreated; int numTexturesCreated;
int numTexturesUploaded;
int numTexturesAlive; int numTexturesAlive;
int numVertexLoaders; int numVertexLoaders;

View File

@ -22,7 +22,7 @@
static const u64 TEXHASH_INVALID = 0; static const u64 TEXHASH_INVALID = 0;
static const int TEXTURE_KILL_THRESHOLD = 200; static const int TEXTURE_KILL_THRESHOLD = 200;
static const int RENDER_TARGET_KILL_THRESHOLD = 3; static const int TEXTURE_POOL_KILL_THRESHOLD = 3;
static const u64 FRAMECOUNT_INVALID = 0; static const u64 FRAMECOUNT_INVALID = 0;
TextureCache *g_texture_cache; TextureCache *g_texture_cache;
@ -31,7 +31,7 @@ GC_ALIGNED16(u8 *TextureCache::temp) = nullptr;
size_t TextureCache::temp_size; size_t TextureCache::temp_size;
TextureCache::TexCache TextureCache::textures; TextureCache::TexCache TextureCache::textures;
TextureCache::RenderTargetPool TextureCache::render_target_pool; TextureCache::TexturePool TextureCache::texture_pool;
TextureCache::BackupConfig TextureCache::backup_config; TextureCache::BackupConfig TextureCache::backup_config;
@ -80,11 +80,11 @@ void TextureCache::Invalidate()
} }
textures.clear(); textures.clear();
for (auto& rt : render_target_pool) for (auto& rt : texture_pool)
{ {
delete rt; delete rt;
} }
render_target_pool.clear(); texture_pool.clear();
} }
TextureCache::~TextureCache() TextureCache::~TextureCache()
@ -152,7 +152,7 @@ void TextureCache::Cleanup(int _frameCount)
// EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted
!iter->second->IsEfbCopy()) !iter->second->IsEfbCopy())
{ {
delete iter->second; FreeTexture(iter->second);
iter = textures.erase(iter); iter = textures.erase(iter);
} }
else else
@ -161,15 +161,15 @@ void TextureCache::Cleanup(int _frameCount)
} }
} }
for (size_t i = 0; i < render_target_pool.size();) for (size_t i = 0; i < texture_pool.size();)
{ {
auto rt = render_target_pool[i]; auto rt = texture_pool[i];
if (_frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) if (_frameCount > TEXTURE_POOL_KILL_THRESHOLD + rt->frameCount)
{ {
delete rt; delete rt;
render_target_pool[i] = render_target_pool.back(); texture_pool[i] = texture_pool.back();
render_target_pool.pop_back(); texture_pool.pop_back();
} }
else else
{ {
@ -187,7 +187,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size)
{ {
if (iter->second->OverlapsMemoryRange(start_address, size)) if (iter->second->OverlapsMemoryRange(start_address, size))
{ {
delete iter->second; FreeTexture(iter->second);
textures.erase(iter++); textures.erase(iter++);
} }
else else
@ -246,7 +246,7 @@ void TextureCache::ClearRenderTargets()
{ {
if (iter->second->type == TCET_EC_VRAM) if (iter->second->type == TCET_EC_VRAM)
{ {
delete iter->second; FreeTexture(iter->second);
textures.erase(iter++); textures.erase(iter++);
} }
else else
@ -407,7 +407,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
else else
{ {
// delete the texture and make a new one // delete the texture and make a new one
delete entry; FreeTexture(entry);
entry = nullptr; entry = nullptr;
} }
} }
@ -433,7 +433,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
// If we thought we could reuse the texture before, make sure to pool it now! // If we thought we could reuse the texture before, make sure to pool it now!
if (entry) if (entry)
{ {
delete entry; FreeTexture(entry);
entry = nullptr; entry = nullptr;
} }
} }
@ -467,7 +467,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
if (entry && entry->config.levels != texLevels) if (entry && entry->config.levels != texLevels)
{ {
// delete the texture and make a new one // delete the texture and make a new one
delete entry; FreeTexture(entry);
entry = nullptr; entry = nullptr;
} }
@ -478,7 +478,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
config.width = width; config.width = width;
config.height = height; config.height = height;
config.levels = texLevels; config.levels = texLevels;
textures[texID] = entry = g_texture_cache->CreateTexture(config); textures[texID] = entry = AllocateTexture(config);
entry->type = TCET_NORMAL; entry->type = TCET_NORMAL;
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
@ -553,7 +553,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage)
} }
} }
INCSTAT(stats.numTexturesCreated); INCSTAT(stats.numTexturesUploaded);
SETSTAT(stats.numTexturesAlive, textures.size()); SETSTAT(stats.numTexturesAlive, textures.size());
return ReturnEntry(stage, entry); return ReturnEntry(stage, entry);
@ -857,17 +857,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
} }
else if (!(entry->type == TCET_EC_VRAM && entry->config.width == scaled_tex_w && entry->config.height == scaled_tex_h && entry->config.layers == efb_layers)) else if (!(entry->type == TCET_EC_VRAM && entry->config.width == scaled_tex_w && entry->config.height == scaled_tex_h && entry->config.layers == efb_layers))
{ {
if (entry->type == TCET_EC_VRAM) // try to re-use this texture later
{ FreeTexture(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;
} }
} }
@ -875,7 +866,13 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
if (nullptr == entry) if (nullptr == entry)
{ {
// create the texture // create the texture
textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h, FramebufferManagerBase::GetEFBLayers()); TCacheEntryConfig config;
config.rendertarget = true;
config.width = scaled_tex_w;
config.height = scaled_tex_h;
config.layers = FramebufferManagerBase::GetEFBLayers();
textures[dstAddr] = entry = AllocateTexture(config);
// TODO: Using the wrong dstFormat, dumb... // TODO: Using the wrong dstFormat, dumb...
entry->SetGeneralParameters(dstAddr, 0, dstFormat); entry->SetGeneralParameters(dstAddr, 0, dstFormat);
@ -889,31 +886,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, unsigned int layers) TextureCache::TCacheEntryBase* TextureCache::AllocateTexture(const TCacheEntryConfig& config)
{ {
for (size_t i = 0; i < render_target_pool.size(); ++i) for (size_t i = 0; i < texture_pool.size(); ++i)
{ {
auto rt = render_target_pool[i]; auto rt = texture_pool[i];
if (rt->config.width != width || rt->config.height != height || rt->config.layers != layers) if (rt->config == config)
continue; {
texture_pool[i] = texture_pool.back();
render_target_pool[i] = render_target_pool.back(); texture_pool.pop_back();
render_target_pool.pop_back();
return rt; return rt;
} }
}
TCacheEntryConfig config; INCSTAT(stats.numTexturesCreated);
config.rendertarget = true;
config.width = width;
config.height = height;
config.layers = layers;
return g_texture_cache->CreateTexture(config); return g_texture_cache->CreateTexture(config);
} }
void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) void TextureCache::FreeTexture(TCacheEntryBase* entry)
{ {
render_target_pool.push_back(entry); texture_pool.push_back(entry);
} }

View File

@ -32,6 +32,11 @@ public:
u32 width, height; u32 width, height;
u32 levels, layers; u32 levels, layers;
bool rendertarget; bool rendertarget;
bool operator == (const TCacheEntryConfig& b) const
{
return width == b.width && height == b.height && levels == b.levels && layers == b.layers && rendertarget == b.rendertarget;
}
}; };
struct TCacheEntryBase struct TCacheEntryBase
@ -125,14 +130,14 @@ private:
static void DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level); static void DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level);
static void CheckTempSize(size_t required_size); static void CheckTempSize(size_t required_size);
static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height, unsigned int layers); static TCacheEntryBase* AllocateTexture(const TCacheEntryConfig& config);
static void FreeRenderTarget(TCacheEntryBase* entry); static void FreeTexture(TCacheEntryBase* entry);
typedef std::map<u32, TCacheEntryBase*> TexCache; typedef std::map<u32, TCacheEntryBase*> TexCache;
typedef std::vector<TCacheEntryBase*> RenderTargetPool; typedef std::vector<TCacheEntryBase*> TexturePool;
static TexCache textures; static TexCache textures;
static RenderTargetPool render_target_pool; static TexturePool texture_pool;
// Backup configuration values // Backup configuration values
static struct BackupConfig static struct BackupConfig