From c859aaae84642ded91fe046ef91404431c84f48b Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 10 Aug 2012 12:36:19 +0200 Subject: [optimization] TextureCacheBase: Slightly loosen the requirements for reusing mipmapped textures --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index a5c390df3d..65407f2a0e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -363,8 +363,10 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } // 2. b) For normal textures, all texture parameters need to match + // NOTE: maxlevel is specified via render states, so it doesn't need to match exactly + // TODO: D3D9 doesn't support min_lod, so we should check for this here 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->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) { goto return_entry; } @@ -374,7 +376,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int 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->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps == maxlevel) + if ((entry->type == TCET_NORMAL && width == entry->native_width && height == entry->native_height && full_format == entry->format && entry->num_mipmaps > maxlevel) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture @@ -421,9 +423,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // 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: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels? - entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... + // TODO: D3D9 doesn't support min_lod. We should add a workaround for that here! + entry->num_mipmaps = maxlevel + 1; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); -- cgit v1.2.3 From ee3d6d66d77dd40cc69e0cf219833d0c0a3a5be3 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 10 Aug 2012 13:09:16 +0200 Subject: [cleanup] [bugfix] TextureCacheBase: Cleanup and simplify mipmapping logic. Possibly fixes a bug or two. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 65407f2a0e..21e4a9d989 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -211,6 +211,9 @@ void TextureCache::ClearRenderTargets() bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels) { + if (levels == 1) + return false; + // Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black char texBasePathTemp[MAX_PATH]; char texPathTemp[MAX_PATH]; @@ -293,7 +296,7 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, int texformat, - unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem) + unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem) { if (0 == address) return NULL; @@ -363,8 +366,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } // 2. b) For normal textures, all texture parameters need to match - // NOTE: maxlevel is specified via render states, so it doesn't need to match exactly - // TODO: D3D9 doesn't support min_lod, so we should check for this here if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format && entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) { @@ -406,15 +407,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, pcfmt = TexDecoder_Decode(temp, src_data, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); - // TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that) - bool isPow2; unsigned int texLevels; - isPow2 = !((width & (width - 1)) || (height & (height - 1))); - texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2; - texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels; + bool use_native_mips; + texLevels = use_mipmaps ? (maxlevel + 1) : 1; using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels); - UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions - texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2; + use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions + texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // create the entry/texture if (NULL == entry) { @@ -424,7 +422,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, // 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: D3D9 doesn't support min_lod. We should add a workaround for that here! - entry->num_mipmaps = maxlevel + 1; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage... + entry->num_mipmaps = maxlevel + 1; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); @@ -443,7 +441,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, DumpTexture(entry, 0); // load mips - TODO: Loading mipmaps from tmem is untested! - if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips) + if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && use_native_mips) { const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat); -- cgit v1.2.3 From 069d949a572ea2543e86819487c0ba34e5564af8 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Fri, 10 Aug 2012 13:13:51 +0200 Subject: [cleanup] TextureCache: Kill the autogen_mipmap parameter --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 21e4a9d989..dc80d98639 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -435,7 +435,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, else entry->type = TCET_NORMAL; // load texture - entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); + entry->Load(width, height, expandedWidth, 0); if (g_ActiveConfig.bDumpTextures && !using_custom_texture) DumpTexture(entry, 0); @@ -470,7 +470,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, expandedHeight = (currentHeight + bsh) & (~bsh); TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); - entry->Load(currentWidth, currentHeight, expandedWidth, level, false); + entry->Load(currentWidth, currentHeight, expandedWidth, level); if (g_ActiveConfig.bDumpTextures) DumpTexture(entry, level); @@ -493,7 +493,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight); - entry->Load(currentWidth, currentHeight, currentWidth, level, false); + entry->Load(currentWidth, currentHeight, currentWidth, level); mipWidth >>= 1; mipHeight >>= 1; -- cgit v1.2.3 From e7d5b274c02a02339bd2a5e3260b70867fed26b6 Mon Sep 17 00:00:00 2001 From: degasus Date: Sat, 19 Jan 2013 00:47:48 +0100 Subject: add stage parameter for texture load, so ogl can bind to the correct sampler --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 9fc18ef1bd..c2f1466be7 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -446,7 +446,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, else entry->type = TCET_NORMAL; // load texture - entry->Load(width, height, expandedWidth, 0, (texLevels == 0)); + entry->Load(stage, width, height, expandedWidth, 0, (texLevels == 0)); if (g_ActiveConfig.bDumpTextures && !using_custom_texture) DumpTexture(entry, 0); @@ -481,7 +481,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, expandedHeight = (currentHeight + bsh) & (~bsh); TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); - entry->Load(currentWidth, currentHeight, expandedWidth, level, false); + entry->Load(stage, currentWidth, currentHeight, expandedWidth, level, false); if (g_ActiveConfig.bDumpTextures) DumpTexture(entry, level); @@ -504,7 +504,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight); - entry->Load(currentWidth, currentHeight, currentWidth, level, false); + entry->Load(stage, currentWidth, currentHeight, currentWidth, level, false); mipWidth >>= 1; mipHeight >>= 1; -- cgit v1.2.3 From c5fa3e0f3dbb1fdc5f95e9e3fbfb7de62c718e9c Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 28 Jan 2013 18:16:03 +0100 Subject: move RestoreAPIState and ResetAPIState into backends it's a backend specific hack, so it should be here should give a small speedup in dx11 efb2tex --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 58b2fac341..e12ef5d67f 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -814,9 +814,5 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->frameCount = frameCount; - g_renderer->ResetAPIState(); // reset any game specific settings - entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); - - g_renderer->RestoreAPIState(); } -- cgit v1.2.3 From d994e56b60aa0f6fc2f1da333d0b320fcfbda018 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Fri, 15 Feb 2013 20:46:03 -0600 Subject: Changes/cleanup to TextureCache::Load and other mipmap related code. The significant change is what is now line 520 of TextureCacheBase.cpp: ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1) to TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); Fixes issue 5328. Fixes issue 5461. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 211 ++++++++++++----------- 1 file changed, 108 insertions(+), 103 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index f6e6911c12..d77caa94b3 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -84,35 +84,34 @@ TextureCache::~TextureCache() void TextureCache::OnConfigChanged(VideoConfig& config) { - if (!g_texture_cache) - goto skip_checks; - - // TODO: Invalidating texcache is really stupid in some of these cases - if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples || - config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay || - config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center || - config.bHiresTextures != backup_config.s_hires_textures) + if (g_texture_cache) { - g_texture_cache->Invalidate(); + // TODO: Invalidating texcache is really stupid in some of these cases + if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples || + config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay || + config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center || + config.bHiresTextures != backup_config.s_hires_textures) + { + g_texture_cache->Invalidate(); - if(g_ActiveConfig.bHiresTextures) - HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); + if(g_ActiveConfig.bHiresTextures) + HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); - SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); - TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); - } + SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); + TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); + } - // 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) - { - g_texture_cache->ClearRenderTargets(); + // 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) + { + g_texture_cache->ClearRenderTargets(); + } } - -skip_checks: + backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples; backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture; backup_config.s_copy_efb_scaled = config.bCopyEFBScaled; @@ -301,14 +300,30 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) entry->Save(szTemp, level); } -TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, - u32 address, unsigned int width, unsigned int height, int texformat, - unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem) +static u32 CalculateLevelSize(u32 level_0_size, u32 level) +{ + return (level_0_size + ((1 << level) - 1)) >> level; +} + +// Used by TextureCache::Load +static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry) +{ + entry->frameCount = frameCount; + entry->Bind(stage); + + GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); + + 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 const maxlevel, bool const from_tmem) { if (0 == address) return NULL; - // TexelSizeInNibbles(format)*width*height/16; + // TexelSizeInNibbles(format) * width * height / 16; const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1; const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1; @@ -317,11 +332,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, const unsigned int nativeW = width; const unsigned int nativeH = height; - bool using_custom_texture = false; - bool using_custom_lods = false; - u32 texID = address; - u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) + // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup) + u64 tex_hash = TEXHASH_INVALID; u64 tlut_hash = TEXHASH_INVALID; u32 full_format = texformat; @@ -332,9 +345,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, full_format = texformat | (tlutfmt << 16); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - u8* src_data; - if (from_tmem) src_data = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE]; - else src_data = Memory::GetPointer(address); + + const u8* src_data; + if (from_tmem) + src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE]; + else + src_data = Memory::GetPointer(address); // TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data from the low tmem bank than it should) tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples); @@ -369,15 +385,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, { entry->type = TCET_EC_VRAM; - // TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) - goto return_entry; + // TODO: Print a warning if the format changes! In this case, + // we could reinterpret the internal texture object data to the new pixel format + // (similiar to what is already being done in Renderer::ReinterpretPixelFormat()) + return ReturnEntry(stage, entry); } // 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) { - goto return_entry; + return ReturnEntry(stage, entry); } // 3. If we reach this line, we'll have to upload the new texture data to VRAM. @@ -385,7 +403,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int 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 && full_format == entry->format && entry->num_mipmaps > maxlevel) + if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height + && full_format == entry->format && entry->num_mipmaps > maxlevel) || (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height)) { // reuse the texture @@ -398,9 +417,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } + bool using_custom_texture = false; if (g_ActiveConfig.bHiresTextures) { + // This function may modify width/height. pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height); if (pcfmt != PC_TEX_FMT_NONE) { @@ -431,21 +452,25 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } - unsigned int texLevels; - bool use_native_mips; - texLevels = use_mipmaps ? (maxlevel + 1) : 1; - using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels); - use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions + u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1; + const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, 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; // create the entry/texture - if (NULL == entry) { + if (NULL == entry) + { textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, 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: D3D9 doesn't support min_lod. We should add a workaround for that here! + + // 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->type = TCET_NORMAL; @@ -464,78 +489,58 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, if (g_ActiveConfig.bDumpTextures && !using_custom_texture) DumpTexture(entry, 0); + u32 level = 1; // load mips - TODO: Loading mipmaps from tmem is untested! - if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && use_native_mips) + if (pcfmt != PC_TEX_FMT_NONE) { - const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat); - - unsigned int level = 1; - unsigned int mipWidth = (width + 1) >> 1; - unsigned int mipHeight = (height + 1) >> 1; - - u8* ptr_even = NULL, *ptr_odd = NULL; - if (from_tmem) - { - ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; - ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; - } - src_data += texture_size; - - while ((mipHeight || mipWidth) && (level < texLevels)) + if (use_native_mips) { - u8** ptr; - if (from_tmem) ptr = (level % 2) ? &ptr_odd : &ptr_even; - else ptr = &src_data; - - const unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1; - const unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; - - expandedWidth = (currentWidth + bsw) & (~bsw); - expandedHeight = (currentHeight + bsh) & (~bsh); - - TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); - entry->Load(currentWidth, currentHeight, expandedWidth, level); + src_data += texture_size; + + const u8* ptr_even = NULL; + const u8* ptr_odd = NULL; + if (from_tmem) + { + ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size]; + ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE]; + } - if (g_ActiveConfig.bDumpTextures) - DumpTexture(entry, level); + for (; level != texLevels; ++level) + { + const u32 mip_width = CalculateLevelSize(width, level); + const u32 mip_height = CalculateLevelSize(height, level); + const u32 expanded_mip_width = (mip_width + bsw) & (~bsw); + const u32 expanded_mip_height = (mip_height + bsh) & (~bsh); + + const u8*& mip_src_data = from_tmem + ? ((level % 2) ? ptr_odd : ptr_even) + : src_data; + TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures); + mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat); + + entry->Load(mip_width, mip_height, expanded_mip_width, level); - *ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1); - mipWidth >>= 1; - mipHeight >>= 1; - ++level; + if (g_ActiveConfig.bDumpTextures) + DumpTexture(entry, level); + } } - } - else if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && using_custom_lods) - { - unsigned int level = 1; - unsigned int mipWidth = (width + 1) >> 1; - unsigned int mipHeight = (height + 1) >> 1; - - while ((mipHeight || mipWidth) && (level < texLevels)) + else if (using_custom_lods) { - unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1; - unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1; - - LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight); - entry->Load(currentWidth, currentHeight, currentWidth, level); + for (; level != texLevels; ++level) + { + unsigned int mip_width = CalculateLevelSize(width, level); + unsigned int mip_height = CalculateLevelSize(height, level); - mipWidth >>= 1; - mipHeight >>= 1; - ++level; + LoadCustomTexture(tex_hash, texformat, level, mip_width, mip_height); + entry->Load(mip_width, mip_height, mip_width, level); + } } } INCSTAT(stats.numTexturesCreated); SETSTAT(stats.numTexturesAlive, textures.size()); -return_entry: - - entry->frameCount = frameCount; - entry->Bind(stage); - - GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true); - - return entry; + return ReturnEntry(stage, entry); } void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, -- cgit v1.2.3 From 19ab5bf50d511f9e73a896c9c610e8521fe7b583 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 18 Feb 2013 17:14:56 +0100 Subject: TextureCache: Fix D3D backends crashing when a game uses multiple 1x1-sized LODs. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index d77caa94b3..fd935de342 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -318,7 +318,7 @@ static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCac 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 const maxlevel, bool const from_tmem) + unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem) { if (0 == address) return NULL; @@ -345,7 +345,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, full_format = texformat | (tlutfmt << 16); const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat); - + const u8* src_data; if (from_tmem) src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE]; @@ -372,6 +372,11 @@ 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 && max(expandedWidth, expandedHeight) >> maxlevel == 0) + --maxlevel; + TCacheEntryBase *entry = textures[texID]; if (entry) { @@ -456,7 +461,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, 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; + 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) // create the entry/texture if (NULL == entry) -- cgit v1.2.3 From 6e6d8af6ddaddeeaf89be2f8b6920b913488f0c6 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Wed, 20 Feb 2013 05:37:01 -0600 Subject: Revert "Don't load level 0 twice for 1-level textures in DX11." and fix it properly. All backend TextureCaches now load level 0 in CreateTexture. This reverts commit 294cb165ba3449cc4fd96eabb5272e2984a58eb8. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index fd935de342..fda4f21a7e 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -481,15 +481,20 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); } + else + { + // load texture (CreateTexture also loads level 0) + entry->Load(width, height, expandedWidth, 0); + } entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps); entry->SetDimensions(nativeW, nativeH, width, height); entry->hash = tex_hash; - if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_EC_DYNAMIC; - else entry->type = TCET_NORMAL; - - // load texture - entry->Load(width, height, expandedWidth, 0); + + if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) + entry->type = TCET_EC_DYNAMIC; + else + entry->type = TCET_NORMAL; if (g_ActiveConfig.bDumpTextures && !using_custom_texture) DumpTexture(entry, 0); -- cgit v1.2.3 From 1141af64f64b801fc1509bb9c1eff92436f340e6 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 25 Feb 2013 12:36:50 +0000 Subject: TextureCacheBase: Do not assume EFB copies can safely be deleted when we think they're "unused". Fixes issue 6040. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index fda4f21a7e..46aaf79bd4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -129,8 +129,13 @@ void TextureCache::Cleanup() TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here... + if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) { + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted + // TODO: encoding the texture back to RAM here might be a good idea + if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) + continue; + delete iter->second; textures.erase(iter++); } -- cgit v1.2.3 From 73a0bdd379672c4f218b92788002dbc39815fb85 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 25 Feb 2013 12:42:52 +0000 Subject: Build fixing. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 46aaf79bd4..d261d9d6d2 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -133,7 +133,7 @@ void TextureCache::Cleanup() { // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted // TODO: encoding the texture back to RAM here might be a good idea - if (g_ActiveConfig.bCopyEFBToTexture && entry->IsEfbCopy()) + if (g_ActiveConfig.bCopyEFBToTexture && iter->second->IsEfbCopy()) continue; delete iter->second; -- cgit v1.2.3 From d173d646de18bc9e158651989045fef8ddd1523f Mon Sep 17 00:00:00 2001 From: degasus Date: Mon, 25 Feb 2013 16:11:24 +0100 Subject: fix last commit by neobrain --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index d261d9d6d2..6871c411fa 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -129,13 +129,12 @@ void TextureCache::Cleanup() TexCache::iterator tcend = textures.end(); while (iter != tcend) { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) - { + if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount + // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted // TODO: encoding the texture back to RAM here might be a good idea - if (g_ActiveConfig.bCopyEFBToTexture && iter->second->IsEfbCopy()) - continue; - + && ! (g_ActiveConfig.bCopyEFBToTexture && iter->second->IsEfbCopy()) ) + { delete iter->second; textures.erase(iter++); } -- cgit v1.2.3 From ef7083d78cdeb9eb8881a0d1593164ad1dd04225 Mon Sep 17 00:00:00 2001 From: degasus Date: Fri, 1 Mar 2013 11:31:52 +0100 Subject: also don't cleanup efb copys on efb2ram these may be upscaled and this high res textures would be lost --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 6871c411fa..dcd3fbdd90 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -132,8 +132,7 @@ void TextureCache::Cleanup() if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted - // TODO: encoding the texture back to RAM here might be a good idea - && ! (g_ActiveConfig.bCopyEFBToTexture && iter->second->IsEfbCopy()) ) + && ! iter->second->IsEfbCopy() ) { delete iter->second; textures.erase(iter++); -- cgit v1.2.3 From edd9d0e0ef6898a0528ac6389e93e9fca6132ff6 Mon Sep 17 00:00:00 2001 From: lioncash Date: Tue, 19 Mar 2013 21:51:12 -0400 Subject: Clean up more space/tab mismatches in AudioCommon, Common, and VideoCommon. Not planning to touch Core since it's the most actively changed part of the project. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/Src/TextureCacheBase.cpp') diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index c9c455b874..319c014f22 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -56,7 +56,7 @@ TextureCache::TextureCache() if (!temp) temp = (u8*)AllocateAlignedMemory(temp_size, 16); TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter); - if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) + if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures) HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str()); SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures); } @@ -725,7 +725,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat case 1: // R8 case 8: // R8 colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1; - cbufid = 13; + cbufid = 13; break; case 2: // RA4 @@ -746,11 +746,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat case 9: // G8 colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f; - cbufid = 17; + cbufid = 17; break; case 10: // B8 colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f; - cbufid = 18; + cbufid = 18; break; case 11: // RG8 @@ -759,7 +759,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat break; case 12: // GB8 - colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; + colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f; cbufid = 20; break; -- cgit v1.2.3