diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index e0fc11fe1b..f6e6911c12 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -218,6 +218,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]; @@ -300,7 +303,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; @@ -372,7 +375,7 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int 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->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH) { goto return_entry; } @@ -382,7 +385,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->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 @@ -428,15 +431,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage, } } - // 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) { @@ -445,9 +445,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; entry->type = TCET_NORMAL; GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true); @@ -460,13 +459,13 @@ 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); // 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); @@ -495,7 +494,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); @@ -518,7 +517,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; diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index 1f8d9ebbd9..40441c2d70 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -89,7 +89,7 @@ public: virtual bool Save(const char filename[], unsigned int level) = 0; virtual void Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0; + unsigned int expanded_width, unsigned int level) = 0; virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf, unsigned int cbufid, @@ -116,7 +116,7 @@ public: virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0; static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height, - int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem); + int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem); static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); diff --git a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp index 57812aa067..a6cb52c40f 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/Render.cpp @@ -1420,7 +1420,7 @@ void Renderer::SetSamplerState(int stage, int texindex) // When mipfilter is set to "none", just disable mipmapping altogether gx_state.sampdc[stage].MaxLOD = (mip == TEXF_NONE) ? 0.0f : (float)tm1.max_lod/16.f; gx_state.sampdc[stage].MinLOD = (float)tm1.min_lod/16.f; - gx_state.sampdc[stage].MipLODBias = (float)tm0.lod_bias/32.0f; + gx_state.sampdc[stage].MipLODBias = (s32)tm0.lod_bias/32.0f; } void Renderer::SetInterlacingMode() diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index 5f82a18fc0..844cf24b47 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -59,12 +59,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips) + unsigned int expanded_width, unsigned int level) { D3D::ReplaceRGBATexture2D(texture->GetTex(), TextureCache::temp, width, height, expanded_width, level, usage); - - if (autogen_mips) - PD3DX11FilterTexture(D3D::context, texture->GetTex(), 0, D3DX11_DEFAULT); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h index 59d343017c..7876cb79ee 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.h @@ -41,7 +41,7 @@ private: ~TCacheEntry(); void Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int levels, bool autogen_mips = false); + unsigned int expanded_width, unsigned int levels); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, diff --git a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp index 7026522cf6..4bcb4befb8 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp @@ -237,8 +237,8 @@ void VertexManager::vFlush() 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) && (tex.texMode0[i&3].min_filter != 8), - tex.texMode1[i&3].max_lod >> 4, + (tex.texMode0[i&3].min_filter & 3), + ceil(tex.texMode1[i&3].max_lod / 16.f), tex.texImage1[i&3].image_type); if (tentry) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 0ff4f4f99a..0f0432e96b 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -1333,9 +1333,10 @@ void Renderer::SetSamplerState(int stage, int texindex) D3D::SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]); D3D::SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]); - float lodbias = tm0.lod_bias / 32.0f; + + float lodbias = (s32)tm0.lod_bias / 32.0f; D3D::SetSamplerState(stage, D3DSAMP_MIPMAPLODBIAS, *(DWORD*)&lodbias); - D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.min_lod >> 4); + D3D::SetSamplerState(stage, D3DSAMP_MAXMIPLEVEL, tm1.max_lod >> 4); } void Renderer::SetInterlacingMode() diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 2be29048d3..660fad7379 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -72,10 +72,9 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips) + unsigned int expanded_width, unsigned int level) { D3D::ReplaceTexture2D(texture, temp, width, height, expanded_width, d3d_fmt, swap_r_b, level); - // D3D9 will automatically generate mip maps if necessary } void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFormat, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h index 4a7cddd575..fc338e623f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h @@ -44,7 +44,7 @@ private: ~TCacheEntry(); void Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int levels, bool autogen_mips = false); + unsigned int expanded_width, unsigned int levels); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index 17a7aa1498..d8e2462f51 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -333,8 +333,8 @@ void VertexManager::vFlush() 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) && (tex.texMode0[i&3].min_filter != 8), - tex.texMode1[i&3].max_lod >> 4, + (tex.texMode0[i&3].min_filter & 3), + ceil(tex.texMode1[i&3].max_lod / 16.f), tex.texImage1[i&3].image_type); if (tentry) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp index a21333e534..bf6f6d1ef2 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp @@ -183,7 +183,7 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips) + unsigned int expanded_width, unsigned int level) { //glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture); @@ -194,16 +194,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, if (expanded_width != width) glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width); - if (bHaveMipMaps && autogen_mips) - { - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); - } - else - { - glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp); - } + glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp); if (expanded_width != width) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); @@ -358,17 +349,16 @@ void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, co GL_REPEAT, }; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - int filt = newmode.min_filter; - if (g_ActiveConfig.bForceFiltering && filt < 4) + if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) filt += 4; // take equivalent forced linear - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f); - glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, newmode.lod_bias / 32.0f); + glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); @@ -376,7 +366,7 @@ void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, co // TODO: Reset anisotrop when changed to 1 if (g_Config.iMaxAnisotropy >= 1) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (float)(1 << g_ActiveConfig.iMaxAnisotropy)); + (float)(1 << g_ActiveConfig.iMaxAnisotropy)); } TextureCache::~TextureCache() diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h index 30f44b797d..a26aa4049e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureCache.h @@ -54,7 +54,7 @@ private: ~TCacheEntry(); void Load(unsigned int width, unsigned int height, - unsigned int expanded_width, unsigned int level, bool autogen_mips = false); + unsigned int expanded_width, unsigned int level); void FromRenderTarget(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, const EFBRectangle& srcRect, diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index ce33247d7c..8e9feb2c39 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -164,8 +164,8 @@ void VertexManager::vFlush() 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) && (tex.texMode0[i&3].min_filter != 8), - tex.texMode1[i&3].max_lod >> 4, + (tex.texMode0[i&3].min_filter & 3), + ceil(tex.texMode1[i&3].max_lod / 16.f), tex.texImage1[i&3].image_type); if (tentry)