From 19ab5bf50d511f9e73a896c9c610e8521fe7b583 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Mon, 18 Feb 2013 17:14:56 +0100 Subject: [PATCH] TextureCache: Fix D3D backends crashing when a game uses multiple 1x1-sized LODs. --- Source/Core/VideoCommon/Src/TextureCacheBase.cpp | 11 ++++++++--- Source/Core/VideoCommon/Src/VideoConfig.cpp | 1 + Source/Core/VideoCommon/Src/VideoConfig.h | 1 + Source/Plugins/Plugin_VideoDX11/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 1 + Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 1 + 6 files changed, 13 insertions(+), 3 deletions(-) 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) diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index 7418d60741..a76514a10c 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -42,6 +42,7 @@ VideoConfig::VideoConfig() // disable all features by default backend_info.APIType = API_NONE; backend_info.bUseRGBATextures = false; + backend_info.bUseMinimalMipCount = false; backend_info.bSupports3DVision = false; } diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 4364bea6ea..183fcf784c 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -157,6 +157,7 @@ struct VideoConfig std::vector PPShaders; // post-processing shaders bool bUseRGBATextures; // used for D3D11 in TextureCache + bool bUseMinimalMipCount; bool bSupports3DVision; bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL bool bSupportsFormatReinterpretation; diff --git a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp index cb348b8684..b7dd9101d3 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/main.cpp @@ -90,6 +90,7 @@ void InitBackendInfo() g_Config.backend_info.APIType = API_D3D11; g_Config.backend_info.bUseRGBATextures = true; // the GX formats barely match any D3D11 formats + g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsDualSourceBlend = true; g_Config.backend_info.bSupportsFormatReinterpretation = true; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index 5a80100a08..3c00e1d619 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -93,6 +93,7 @@ void InitBackendInfo() const int maxConstants = (shaderModel < 3) ? 32 : ((shaderModel < 4) ? 224 : 65536); g_Config.backend_info.APIType = shaderModel < 3 ? API_D3D9_SM20 :API_D3D9_SM30; g_Config.backend_info.bUseRGBATextures = false; + g_Config.backend_info.bUseMinimalMipCount = true; g_Config.backend_info.bSupports3DVision = true; g_Config.backend_info.bSupportsDualSourceBlend = false; g_Config.backend_info.bSupportsFormatReinterpretation = true; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index e57e3e210a..05f21beed1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -130,6 +130,7 @@ void InitBackendInfo() { g_Config.backend_info.APIType = API_OPENGL; g_Config.backend_info.bUseRGBATextures = false; + g_Config.backend_info.bUseMinimalMipCount = false; g_Config.backend_info.bSupports3DVision = false; g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken g_Config.backend_info.bSupportsFormatReinterpretation = false;