diff options
| author | Markus Wick <markus+github@selfnet.de> | 2015-01-13 22:45:49 +0100 |
|---|---|---|
| committer | Markus Wick <markus+github@selfnet.de> | 2015-01-13 22:45:49 +0100 |
| commit | 7069450ce570dea3e9a286f7f3538122f5d0f99c (patch) | |
| tree | 203d2ae24edde90b5e0fd383e897e51b879f0350 /Source/Core/VideoCommon/TextureCacheBase.cpp | |
| parent | 0932282caf926347c60f49af60c17612fc9624b5 (diff) | |
| parent | 22e06daf5c41c3d201edba8c22c85df5bafee63b (diff) | |
Merge pull request #1872 from degasus/texcache
Texcache cleanup 2
Diffstat (limited to 'Source/Core/VideoCommon/TextureCacheBase.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/TextureCacheBase.cpp | 122 |
1 files changed, 61 insertions, 61 deletions
diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ce9b724b8f..a2b32410f9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -13,17 +13,17 @@ #include "Core/HW/Memmap.h" #include "VideoCommon/Debugger.h" +#include "VideoCommon/FramebufferManagerBase.h" #include "VideoCommon/HiresTextures.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/TextureCacheBase.h" #include "VideoCommon/VideoConfig.h" -enum -{ - TEXTURE_KILL_THRESHOLD = 200, - RENDER_TARGET_KILL_THRESHOLD = 3, -}; +static const u64 TEXHASH_INVALID = 0; +static const int TEXTURE_KILL_THRESHOLD = 200; +static const int RENDER_TARGET_KILL_THRESHOLD = 3; +static const u64 FRAMECOUNT_INVALID = 0; TextureCache *g_texture_cache; @@ -116,11 +116,7 @@ void TextureCache::OnConfigChanged(VideoConfig& config) } // TODO: Probably shouldn't clear all render targets here, just mark them dirty or something. - if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed? - config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture || - config.bCopyEFBScaled != backup_config.s_copy_efb_scaled || - config.bEFBCopyEnable != backup_config.s_copy_efb || - config.iEFBScale != backup_config.s_efb_scale) + if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable) // TODO: not sure if this is needed? { g_texture_cache->ClearRenderTargets(); } @@ -134,10 +130,6 @@ void TextureCache::OnConfigChanged(VideoConfig& config) } backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; - backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture; - backup_config.s_copy_efb_scaled = config.bCopyEFBScaled; - backup_config.s_copy_efb = config.bEFBCopyEnable; - backup_config.s_efb_scale = config.iEFBScale; backup_config.s_texfmt_overlay = config.bTexFmtOverlayEnable; backup_config.s_texfmt_overlay_center = config.bTexFmtOverlayCenter; backup_config.s_hires_textures = config.bHiresTextures; @@ -146,18 +138,22 @@ void TextureCache::OnConfigChanged(VideoConfig& config) backup_config.s_efb_mono_depth = config.bStereoEFBMonoDepth; } -void TextureCache::Cleanup() +void TextureCache::Cleanup(int _frameCount) { TexCache::iterator iter = textures.begin(); TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && + if(iter->second->frameCount == FRAMECOUNT_INVALID) + { + iter->second->frameCount = _frameCount; + } + if (_frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount && // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted !iter->second->IsEfbCopy()) { delete iter->second; - textures.erase(iter++); + iter = textures.erase(iter); } else { @@ -169,7 +165,7 @@ void TextureCache::Cleanup() { auto rt = render_target_pool[i]; - if (frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) + if (_frameCount > RENDER_TARGET_KILL_THRESHOLD + rt->frameCount) { delete rt; render_target_pool[i] = render_target_pool.back(); @@ -189,8 +185,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) tcend = textures.end(); while (iter != tcend) { - const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); - if (0 == rangePosition) + if (iter->second->OverlapsMemoryRange(start_address, size)) { delete iter->second; textures.erase(iter++); @@ -213,8 +208,7 @@ void TextureCache::MakeRangeDynamic(u32 start_address, u32 size) for (; iter != tcend; ++iter) { - const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); - if (0 == rangePosition) + if (iter->second->OverlapsMemoryRange(start_address, size)) { iter->second->SetHashes(TEXHASH_INVALID); } @@ -231,15 +225,15 @@ bool TextureCache::Find(u32 start_address, u64 hash) return false; } -int TextureCache::TCacheEntryBase::IntersectsMemoryRange(u32 range_address, u32 range_size) const +bool TextureCache::TCacheEntryBase::OverlapsMemoryRange(u32 range_address, u32 range_size) const { if (addr + size_in_bytes < range_address) - return -1; + return false; if (addr >= range_address + range_size) - return 1; + return false; - return 0; + return true; } void TextureCache::ClearRenderTargets() @@ -289,7 +283,7 @@ static u32 CalculateLevelSize(u32 level_0_size, u32 level) // Used by TextureCache::Load static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry) { - entry->frameCount = frameCount; + entry->frameCount = FRAMECOUNT_INVALID; entry->Bind(stage); GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); @@ -297,10 +291,20 @@ static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCac return entry; } -TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, - u32 const address, unsigned int width, unsigned int height, int const texformat, - unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) +TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) { + const FourTexUnits &tex = bpmem.tex[stage >> 2]; + const u32 id = stage & 3; + const u32 address = (tex.texImage3[id].image_base/* & 0x1FFFFF*/) << 5; + u32 width = tex.texImage0[id].width + 1; + u32 height = tex.texImage0[id].height + 1; + const int texformat = tex.texImage0[id].format; + const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9; + const u32 tlutfmt = tex.texTlut[id].tlut_format; + const bool use_mipmaps = (tex.texMode0[id].min_filter & 3) != 0; + u32 tex_levels = (tex.texMode1[id].max_lod + 0xf) / 0x10 + 1; + const bool from_tmem = tex.texImage1[id].image_type != 0; + if (0 == address) return nullptr; @@ -354,10 +358,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, tex_hash ^= tlut_hash; } - // D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain - // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there - while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> maxlevel == 0) - --maxlevel; + // GPUs don't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain + // e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,0x0, so we limit the mipmap count to 6 there + tex_levels = std::min<u32>(IntLog2(std::max(width, height)) + 1, tex_levels); TCacheEntryBase *entry = textures[texID]; if (entry) @@ -380,7 +383,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // 2. b) For normal textures, all texture parameters need to match if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && - entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) + entry->native_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -391,14 +394,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, // TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies? // TODO: Actually, it should be enough if the internal texture format matches... if (((entry->type == TCET_NORMAL && - width == entry->virtual_width && - height == entry->virtual_height && + width == entry->config.width && + height == entry->config.height && full_format == entry->format && - entry->num_mipmaps > maxlevel) || + entry->config.levels >= tex_levels) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) && - entry->num_layers == 1) + entry->config.layers == 1) { // reuse the texture } @@ -457,33 +460,30 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, } } - u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1; + u32 texLevels = use_mipmaps ? tex_levels : 1; const bool using_custom_lods = hires_tex && hires_tex->m_levels.size() >= texLevels; // Only load native mips if their dimensions fit to our virtual texture dimensions const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR) + if (entry && entry->config.levels != texLevels) + { + // delete the texture and make a new one + delete entry; + entry = nullptr; + } + // create the entry/texture if (nullptr == entry) { textures[texID] = entry = g_texture_cache->CreateTexture(width, height, texLevels, pcfmt); - - // Sometimes, we can get around recreating a texture if only the number of mip levels changes - // e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states - // Thus, we don't update this member for every Load, but just whenever the texture gets recreated - - // TODO: This is the wrong value. We should be storing the number of levels our actual texture has. - // But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after. - // Currently, we might try to reuse a texture which appears to have more levels than actual, maybe.. - entry->num_mipmaps = maxlevel + 1; - entry->num_layers = 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps, entry->num_layers); - entry->SetDimensions(nativeW, nativeH, width, height); + entry->SetGeneralParameters(address, texture_size, full_format); + entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash; // load texture @@ -851,12 +851,12 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat TCacheEntryBase *entry = textures[dstAddr]; if (entry) { - if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->num_layers == efb_layers) + if (entry->type == TCET_EC_DYNAMIC && entry->native_width == tex_w && entry->native_height == tex_h && entry->config.layers == efb_layers) { scaled_tex_w = tex_w; scaled_tex_h = tex_h; } - else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h && entry->num_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) { @@ -876,27 +876,27 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat if (nullptr == entry) { // create the texture - textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h); + textures[dstAddr] = entry = AllocateRenderTarget(scaled_tex_w, scaled_tex_h, FramebufferManagerBase::GetEFBLayers()); // TODO: Using the wrong dstFormat, dumb... - entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1, efb_layers); - entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); + entry->SetGeneralParameters(dstAddr, 0, dstFormat); + entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; } - entry->frameCount = frameCount; + entry->frameCount = FRAMECOUNT_INVALID; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } -TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height) +TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int width, unsigned int height, unsigned int layers) { 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) + if (rt->config.width != width || rt->config.height != height || rt->config.layers != layers) continue; render_target_pool[i] = render_target_pool.back(); @@ -905,7 +905,7 @@ TextureCache::TCacheEntryBase* TextureCache::AllocateRenderTarget(unsigned int w return rt; } - return g_texture_cache->CreateRenderTargetTexture(width, height); + return g_texture_cache->CreateRenderTargetTexture(width, height, layers); } void TextureCache::FreeRenderTarget(TCacheEntryBase* entry) |
