From dddcea5a9a38ae4832ccf9544d4b097e80df2e34 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 16 May 2014 18:41:01 +0200 Subject: [PATCH 01/12] TexCache: don't invalidate efb copys because of config changes We'll loose data on invalidating them. So just keep them until a new copy is done. A wrong scaled copy is better than no copy if the game doesn't creates a new one. --- Source/Core/VideoCommon/TextureCacheBase.cpp | 10 +--------- Source/Core/VideoCommon/TextureCacheBase.h | 4 ---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index ce9b724b8f..70e8f0433f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -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; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 0b8cf48918..cea35816fe 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -134,10 +134,6 @@ private: static struct BackupConfig { int s_colorsamples; - bool s_copy_efb_to_texture; - bool s_copy_efb_scaled; - bool s_copy_efb; - int s_efb_scale; bool s_texfmt_overlay; bool s_texfmt_overlay_center; bool s_hires_textures; From 774596dbed35c2d69d8b70d58c4190cb1b42d1ac Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 16 May 2014 21:57:14 +0200 Subject: [PATCH 02/12] TexCache: rename OverlapsMemoryRange --- Source/Core/VideoCommon/TextureCacheBase.cpp | 14 ++++++-------- Source/Core/VideoCommon/TextureCacheBase.h | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 70e8f0433f..94ac0d2848 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -181,8 +181,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++); @@ -205,8 +204,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); } @@ -223,15 +221,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() diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index cea35816fe..93345b9617 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -81,7 +81,7 @@ public: bool isIntensity, bool scaleByHalf, unsigned int cbufid, const float *colmat) = 0; - int IntersectsMemoryRange(u32 range_address, u32 range_size) const; + bool OverlapsMemoryRange(u32 range_address, u32 range_size) const; bool IsEfbCopy() { return (type == TCET_EC_VRAM || type == TCET_EC_DYNAMIC); } }; From 6ba613fbd3e7ecca0357adaab2e7fac422480a54 Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 19 May 2014 18:27:59 +0200 Subject: [PATCH 03/12] TexCache: unify global variables --- Source/Core/VideoCommon/TextureCacheBase.cpp | 8 +++----- Source/Core/VideoCommon/TextureCacheBase.h | 2 -- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 94ac0d2848..870e79552b 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -19,11 +19,9 @@ #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; TextureCache *g_texture_cache; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 93345b9617..1fbcd49356 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -27,8 +27,6 @@ public: struct TCacheEntryBase { -#define TEXHASH_INVALID 0 - // common members u32 addr; u32 size_in_bytes; From 1c98a43203263b73da32c19085492c94214a56cb Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 19 May 2014 18:31:38 +0200 Subject: [PATCH 04/12] TexCache: clean up frameCount handling --- Source/Core/VideoBackends/D3D/Render.cpp | 2 +- Source/Core/VideoBackends/OGL/Render.cpp | 2 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 15 ++++++++++----- Source/Core/VideoCommon/TextureCacheBase.h | 5 ++++- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index fd8e406ff2..92c41bfcea 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -851,7 +851,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co OSD::DrawMessages(); D3D::EndFrame(); - TextureCache::Cleanup(); + TextureCache::Cleanup(frameCount); // Enable configuration changes UpdateActiveConfig(); diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 3fecbac10d..5a64fb3c00 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1715,7 +1715,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co } // Clean out old stuff from caches. It's not worth it to clean out the shader caches. - TextureCache::Cleanup(); + TextureCache::Cleanup(frameCount); // Render to the framebuffer. FramebufferManager::SetFramebuffer(0); diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 870e79552b..d963727232 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -22,6 +22,7 @@ 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; @@ -136,13 +137,17 @@ 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()) { @@ -159,7 +164,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(); @@ -277,7 +282,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); @@ -873,7 +878,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->type = TCET_EC_VRAM; } - entry->frameCount = frameCount; + entry->frameCount = FRAMECOUNT_INVALID; entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 1fbcd49356..ae5e3be1ea 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -87,7 +87,10 @@ public: virtual ~TextureCache(); // needs virtual for DX11 dtor static void OnConfigChanged(VideoConfig& config); - static void Cleanup(); + + // Removes textures which aren't used for more than TEXTURE_KILL_THRESHOLD frames, + // frameCount is the current frame number. + static void Cleanup(int frameCount); static void Invalidate(); static void InvalidateRange(u32 start_address, u32 size); From 2b47df07b6e256e04f28e6b28faaa45b9fccf17c Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 31 May 2014 12:40:22 +0200 Subject: [PATCH 05/12] TexCache: use c++11 syntax for std::map::erase --- Source/Core/VideoCommon/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index d963727232..88737a1e95 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -152,7 +152,7 @@ void TextureCache::Cleanup(int _frameCount) !iter->second->IsEfbCopy()) { delete iter->second; - textures.erase(iter++); + iter = textures.erase(iter); } else { From 1261f5f7f4f15fba126119eda0d0639568e2b101 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 12:48:04 +0100 Subject: [PATCH 06/12] TextureCache: inline arguments into texture cache --- Source/Core/VideoCommon/TextureCacheBase.cpp | 16 +++++++++++++--- Source/Core/VideoCommon/TextureCacheBase.h | 3 +-- Source/Core/VideoCommon/VertexManagerBase.cpp | 10 +--------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 88737a1e95..561c3e24ea 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -290,10 +290,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 maxlevel = (tex.texMode1[id].max_lod + 0xf) / 0x10; + const bool from_tmem = tex.texImage1[id].image_type != 0; + if (0 == address) return nullptr; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index ae5e3be1ea..c803546d37 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -105,8 +105,7 @@ public: virtual void CompileShaders() = 0; // currently only implemented by OGL virtual void DeleteShaders() = 0; // currently only implemented by OGL - static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, - int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem); + static TCacheEntryBase* Load(const u32 stage); static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index c6191a587f..38cfd19630 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -202,15 +202,7 @@ void VertexManager::Flush() for (unsigned int i : usedtextures) { g_renderer->SetSamplerState(i & 3, i >> 2); - const FourTexUnits &tex = bpmem.tex[i >> 2]; - const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i, - (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, - tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, - tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, - tex.texTlut[i&3].tlut_format, - ((tex.texMode0[i&3].min_filter & 3) != 0), - (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - (tex.texImage1[i&3].image_type != 0)); + const TextureCache::TCacheEntryBase* tentry = TextureCache::Load(i); if (tentry) { From d640453274099f2cead75df3f137f4b06522d92c Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 12:58:27 +0100 Subject: [PATCH 07/12] TexCache: cleanup max texture level --- Source/Core/VideoCommon/TextureCacheBase.cpp | 16 ++++++++-------- Source/Core/VideoCommon/TextureCacheBase.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 561c3e24ea..99bac2b519 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -301,7 +301,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) 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 maxlevel = (tex.texMode1[id].max_lod + 0xf) / 0x10; + u32 tex_levels = (tex.texMode1[id].max_lod + 0xf) / 0x10 + 1; const bool from_tmem = tex.texImage1[id].image_type != 0; if (0 == address) @@ -359,8 +359,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 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; + while (g_ActiveConfig.backend_info.bUseMinimalMipCount && std::max(width, height) >> (tex_levels - 1) == 0) + --tex_levels; TCacheEntryBase *entry = textures[texID]; if (entry) @@ -383,7 +383,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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->tex_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -397,7 +397,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && - entry->num_mipmaps > maxlevel) || + entry->tex_levels >= tex_levels) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) && @@ -460,7 +460,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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); @@ -478,14 +478,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) // 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->tex_levels = tex_levels; 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->SetGeneralParameters(address, texture_size, full_format, entry->tex_levels, entry->num_layers); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index c803546d37..0d0bc90314 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -35,7 +35,7 @@ public: enum TexCacheEntryType type; - unsigned int num_mipmaps; + unsigned int tex_levels; unsigned int num_layers; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies @@ -44,12 +44,12 @@ public: int frameCount; - void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _num_mipmaps, unsigned int _num_layers) + void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _tex_levels, unsigned int _num_layers) { addr = _addr; size_in_bytes = _size; format = _format; - num_mipmaps = _num_mipmaps; + tex_levels = _tex_levels; num_layers = _num_layers; } From d95e5e2b6fdbdcc7af201a4fc1fa1389bbdf0ad5 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 15:03:41 +0100 Subject: [PATCH 08/12] TexCache: create a const Config struct --- .../Core/VideoBackends/D3D/TextureCache.cpp | 21 +++++++--- Source/Core/VideoBackends/D3D/TextureCache.h | 4 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 28 +++++++++---- Source/Core/VideoBackends/OGL/TextureCache.h | 4 +- Source/Core/VideoCommon/TextureCacheBase.cpp | 41 ++++++++----------- Source/Core/VideoCommon/TextureCacheBase.h | 28 +++++++------ 6 files changed, 72 insertions(+), 54 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/TextureCache.cpp b/Source/Core/VideoBackends/D3D/TextureCache.cpp index 0b0eea50b1..23da4a1352 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/TextureCache.cpp @@ -100,7 +100,12 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, u const HRESULT hr = D3D::device->CreateTexture2D(&texdesc, nullptr, &pTexture); CHECK(SUCCEEDED(hr), "Create texture of the TextureCache"); - TCacheEntry* const entry = new TCacheEntry(new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE)); + TCacheEntryConfig config; + config.width = width; + config.height = height; + config.levels = tex_levels; + + TCacheEntry* const entry = new TCacheEntry(config, new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE)); entry->usage = usage; // TODO: better debug names @@ -122,7 +127,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo g_renderer->ResetAPIState(); // stretch picture with increased internal resolution - const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)virtual_width, (float)virtual_height); + const D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)config.width, (float)config.height); D3D::context->RSSetViewports(1, &vp); // set transformation @@ -188,11 +193,17 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo } TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture( - unsigned int scaled_tex_w, unsigned int scaled_tex_h) + unsigned int scaled_tex_w, unsigned int scaled_tex_h, unsigned int layers) { - return new TCacheEntry(D3DTexture2D::Create(scaled_tex_w, scaled_tex_h, + TCacheEntryConfig config; + config.width = scaled_tex_w; + config.height = scaled_tex_h; + config.layers = layers; + config.rendertarget = true; + + return new TCacheEntry(config, D3DTexture2D::Create(scaled_tex_w, scaled_tex_h, (D3D11_BIND_FLAG)((int)D3D11_BIND_RENDER_TARGET | (int)D3D11_BIND_SHADER_RESOURCE), - D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, FramebufferManager::GetEFBLayers())); + D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, layers)); } TextureCache::TextureCache() diff --git a/Source/Core/VideoBackends/D3D/TextureCache.h b/Source/Core/VideoBackends/D3D/TextureCache.h index 3845165ad5..08ce4008f9 100644 --- a/Source/Core/VideoBackends/D3D/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/TextureCache.h @@ -23,7 +23,7 @@ private: D3D11_USAGE usage; - TCacheEntry(D3DTexture2D *_tex) : texture(_tex) {} + TCacheEntry(const TCacheEntryConfig& config, D3DTexture2D *_tex) : TCacheEntryBase(config), texture(_tex) {} ~TCacheEntry(); void Load(unsigned int width, unsigned int height, @@ -41,7 +41,7 @@ private: TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, unsigned int tex_levels, PC_TexFormat pcfmt) override; - TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) override; + TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h, unsigned int layers) override; u64 EncodeToRamFromTexture(u32 address, void* source_texture, u32 SourceW, u32 SourceH, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle& source) {return 0;}; void CompileShaders() override { } diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index bb80b863e8..4bf70271d1 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -81,7 +81,8 @@ TextureCache::TCacheEntry::~TCacheEntry() } } -TextureCache::TCacheEntry::TCacheEntry() +TextureCache::TCacheEntry::TCacheEntry(const TCacheEntryConfig& _config) +: TCacheEntryBase(_config) { glGenTextures(1, &texture); @@ -105,7 +106,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) bool TextureCache::TCacheEntry::Save(const std::string& filename, unsigned int level) { - return SaveTexture(filename, GL_TEXTURE_2D_ARRAY, texture, virtual_width, virtual_height, level); + return SaveTexture(filename, GL_TEXTURE_2D_ARRAY, texture, config.width, config.height, level); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, unsigned int height, @@ -164,7 +165,12 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, u } } - TCacheEntry &entry = *new TCacheEntry; + TCacheEntryConfig config; + config.width = width; + config.height = height; + config.levels = tex_levels; + + TCacheEntry &entry = *new TCacheEntry(config); entry.gl_format = gl_format; entry.gl_iformat = gl_iformat; entry.gl_type = gl_type; @@ -205,9 +211,15 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, } TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture( - unsigned int scaled_tex_w, unsigned int scaled_tex_h) + unsigned int scaled_tex_w, unsigned int scaled_tex_h, unsigned int layers) { - TCacheEntry *const entry = new TCacheEntry; + TCacheEntryConfig config; + config.width = scaled_tex_w; + config.height = scaled_tex_h; + config.layers = layers; + config.rendertarget = true; + TCacheEntry *const entry = new TCacheEntry(config); + glActiveTexture(GL_TEXTURE0+9); glBindTexture(GL_TEXTURE_2D_ARRAY, entry->texture); @@ -217,7 +229,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateRenderTargetTexture( gl_type = GL_UNSIGNED_BYTE; glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 0); - glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, gl_iformat, scaled_tex_w, scaled_tex_h, FramebufferManager::GetEFBLayers(), 0, gl_format, gl_type, nullptr); + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, gl_iformat, scaled_tex_w, scaled_tex_h, layers, 0, gl_format, gl_type, nullptr); glBindTexture(GL_TEXTURE_2D_ARRAY, 0); glGenFramebuffers(1, &entry->framebuffer); @@ -250,7 +262,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo glActiveTexture(GL_TEXTURE0+9); glBindTexture(GL_TEXTURE_2D_ARRAY, read_texture); - glViewport(0, 0, virtual_width, virtual_height); + glViewport(0, 0, config.width, config.height); GLuint uniform_location; if (srcFormat == PEControl::Z24) @@ -308,7 +320,7 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo { static int count = 0; SaveTexture(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++), GL_TEXTURE_2D_ARRAY, texture, virtual_width, virtual_height, 0); + count++), GL_TEXTURE_2D_ARRAY, texture, config.width, config.height, 0); } g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/TextureCache.h b/Source/Core/VideoBackends/OGL/TextureCache.h index c2001d4bca..270e0d6f1a 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/TextureCache.h @@ -36,7 +36,7 @@ private: //TexMode0 mode; // current filter and clamp modes that texture is set to //TexMode1 mode1; // current filter and clamp modes that texture is set to - TCacheEntry(); + TCacheEntry(const TCacheEntryConfig& config); ~TCacheEntry(); void Load(unsigned int width, unsigned int height, @@ -56,7 +56,7 @@ private: TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, unsigned int tex_levels, PC_TexFormat pcfmt) override; - TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) override; + TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h, unsigned int layers) override; void CompileShaders() override; void DeleteShaders() override; diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 99bac2b519..fd64f9b701 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -13,6 +13,7 @@ #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" @@ -383,7 +384,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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->tex_levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) + entry->config.levels >= tex_levels && entry->native_width == nativeW && entry->native_height == nativeH) { return ReturnEntry(stage, entry); } @@ -394,14 +395,14 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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->tex_levels >= tex_levels) || + 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 } @@ -470,23 +471,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) 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->tex_levels = tex_levels; - entry->num_layers = 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } - entry->SetGeneralParameters(address, texture_size, full_format, entry->tex_levels, entry->num_layers); - entry->SetDimensions(nativeW, nativeH, width, height); + entry->SetGeneralParameters(address, texture_size, full_format); + entry->SetDimensions(nativeW, nativeH); entry->hash = tex_hash; // load texture @@ -854,12 +845,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) { @@ -879,11 +870,11 @@ 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); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; } @@ -893,13 +884,13 @@ 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) +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(); @@ -908,7 +899,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) diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 0d0bc90314..94acccdc5f 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -25,8 +25,19 @@ public: TCET_EC_DYNAMIC, // EFB copy which sits in RAM and needs to be decoded before being used }; + struct TCacheEntryConfig + { + TCacheEntryConfig() : width(0), height(0), levels(1), layers(1), rendertarget(false) {} + + u32 width, height; + u32 levels, layers; + bool rendertarget; + }; + struct TCacheEntryBase { + const TCacheEntryConfig config; + // common members u32 addr; u32 size_in_bytes; @@ -35,30 +46,23 @@ public: enum TexCacheEntryType type; - unsigned int tex_levels; - unsigned int num_layers; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view - unsigned int virtual_width, virtual_height; // Texture dimensions from OUR point of view - for hires textures or scaled EFB copies // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; - void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _tex_levels, unsigned int _num_layers) + void SetGeneralParameters(u32 _addr, u32 _size, u32 _format) { addr = _addr; size_in_bytes = _size; format = _format; - tex_levels = _tex_levels; - num_layers = _num_layers; } - void SetDimensions(unsigned int _native_width, unsigned int _native_height, unsigned int _virtual_width, unsigned int _virtual_height) + void SetDimensions(unsigned int _native_width, unsigned int _native_height) { native_width = _native_width; native_height = _native_height; - virtual_width = _virtual_width; - virtual_height = _virtual_height; } void SetHashes(u64 _hash) @@ -66,7 +70,7 @@ public: hash = _hash; } - + TCacheEntryBase(const TCacheEntryConfig& c) : config(c) {} virtual ~TCacheEntryBase(); virtual void Bind(unsigned int stage) = 0; @@ -100,7 +104,7 @@ public: virtual TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, unsigned int tex_levels, PC_TexFormat pcfmt) = 0; - virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0; + virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h, unsigned int layers) = 0; virtual void CompileShaders() = 0; // currently only implemented by OGL virtual void DeleteShaders() = 0; // currently only implemented by OGL @@ -121,7 +125,7 @@ private: static void DumpTexture(TCacheEntryBase* entry, std::string basename, unsigned int level); static void CheckTempSize(size_t required_size); - static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height); + static TCacheEntryBase* AllocateRenderTarget(unsigned int width, unsigned int height, unsigned int layers); static void FreeRenderTarget(TCacheEntryBase* entry); typedef std::map TexCache; From 744b1c162441b296e0af121d5ca6e95761587b6e Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 15:15:14 +0100 Subject: [PATCH 09/12] TexCache: rewrite level calculation --- Source/Core/VideoBackends/D3D/main.cpp | 1 - Source/Core/VideoBackends/OGL/main.cpp | 1 - Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++---- Source/Core/VideoCommon/VideoConfig.cpp | 1 - Source/Core/VideoCommon/VideoConfig.h | 1 - 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 6652d6bc57..9e8d0661ed 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -75,7 +75,6 @@ void InitBackendInfo() } g_Config.backend_info.APIType = API_D3D; - g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupportsExclusiveFullscreen = true; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsPrimitiveRestart = true; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 6969b97ba4..d3b1842cd8 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -133,7 +133,6 @@ static void GetShaders(std::vector &shaders) static void InitBackendInfo() { g_Config.backend_info.APIType = API_OPENGL; - g_Config.backend_info.bUseMinimalMipCount = false; g_Config.backend_info.bSupportsExclusiveFullscreen = false; //g_Config.backend_info.bSupportsDualSourceBlend = true; // is gpu dependent and must be set in renderer //g_Config.backend_info.bSupportsEarlyZ = true; // is gpu dependent and must be set in renderer diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index fd64f9b701..885c78e9a9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -358,10 +358,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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) >> (tex_levels - 1) == 0) - --tex_levels; + // 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(IntLog2(std::max(width, height)) + 1, tex_levels); TCacheEntryBase *entry = textures[texID]; if (entry) diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 5448d0c4b0..71f5ec22d0 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -36,7 +36,6 @@ VideoConfig::VideoConfig() // disable all features by default backend_info.APIType = API_NONE; - backend_info.bUseMinimalMipCount = false; backend_info.bSupportsExclusiveFullscreen = false; // Game-specific stereoscopy settings diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index d868ae5293..1f3865959f 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -146,7 +146,6 @@ struct VideoConfig final std::vector AAModes; std::vector PPShaders; // post-processing shaders - bool bUseMinimalMipCount; bool bSupportsExclusiveFullscreen; bool bSupportsDualSourceBlend; bool bSupportsPrimitiveRestart; From a9eb08b85da62944c1cde1594239a19af4559d02 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 22:41:04 +0100 Subject: [PATCH 10/12] TexCache: Choose texture based on mipmap count --- Source/Core/VideoCommon/TextureCacheBase.cpp | 6 +++--- Source/Core/VideoCommon/TextureCacheBase.h | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index 885c78e9a9..b5418069ca 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -383,7 +383,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 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->config.levels >= tex_levels && 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); } @@ -476,7 +476,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) } entry->SetGeneralParameters(address, texture_size, full_format); - entry->SetDimensions(nativeW, nativeH); + entry->SetDimensions(nativeW, nativeH, tex_levels); entry->hash = tex_hash; // load texture @@ -873,7 +873,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat); - entry->SetDimensions(tex_w, tex_h); + entry->SetDimensions(tex_w, tex_h, 1); entry->SetHashes(TEXHASH_INVALID); entry->type = TCET_EC_VRAM; } diff --git a/Source/Core/VideoCommon/TextureCacheBase.h b/Source/Core/VideoCommon/TextureCacheBase.h index 94acccdc5f..0b58591939 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.h +++ b/Source/Core/VideoCommon/TextureCacheBase.h @@ -47,6 +47,7 @@ public: enum TexCacheEntryType type; unsigned int native_width, native_height; // Texture dimensions from the GameCube's point of view + unsigned int native_levels; // used to delete textures which haven't been used for TEXTURE_KILL_THRESHOLD frames int frameCount; @@ -59,10 +60,11 @@ public: format = _format; } - void SetDimensions(unsigned int _native_width, unsigned int _native_height) + void SetDimensions(unsigned int _native_width, unsigned int _native_height, unsigned int _native_levels) { native_width = _native_width; native_height = _native_height; + native_levels = _native_levels; } void SetHashes(u64 _hash) From 728431256853989b63b963fc4816cf255b6ec382 Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 22:47:40 +0100 Subject: [PATCH 11/12] OGL: Warn about wrong texture sizes --- Source/Core/VideoBackends/OGL/TextureCache.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 4bf70271d1..241b73f719 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -188,6 +188,12 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, u void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) { + if (level >= config.levels) + PanicAlert("Texture only has %d levels, can't update level %d", config.levels, level); + if (width != std::max(1u, config.width >> level) || height != std::max(1u, config.height >> level)) + PanicAlert("size of level %d must be %dx%d, but %dx%d requested", + level, std::max(1u, config.width >> level), std::max(1u, config.height >> level), width, height); + if (pcfmt != PC_TEX_FMT_DXT1) { glActiveTexture(GL_TEXTURE0+9); From 22e06daf5c41c3d201edba8c22c85df5bafee63b Mon Sep 17 00:00:00 2001 From: degasus Date: Sun, 11 Jan 2015 23:11:04 +0100 Subject: [PATCH 12/12] TexCache: recreate the entry on level missmatch --- Source/Core/VideoCommon/TextureCacheBase.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Core/VideoCommon/TextureCacheBase.cpp b/Source/Core/VideoCommon/TextureCacheBase.cpp index b5418069ca..a2b32410f9 100644 --- a/Source/Core/VideoCommon/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/TextureCacheBase.cpp @@ -466,6 +466,13 @@ TextureCache::TCacheEntryBase* TextureCache::Load(const u32 stage) 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) {