diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 668db2a130..0df8d251e6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -146,19 +146,23 @@ static int TexLog2(float delta) { return useful - 127 * 256; } -void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel, u32 addr, GETexLevelMode &mode) { - minFilt = gstate.texfilter & 0x7; - magFilt = gstate.isMagnifyFilteringEnabled(); - sClamp = gstate.isTexCoordClampedS(); - tClamp = gstate.isTexCoordClampedT(); +SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) { + SamplerCacheKey key; + + int minFilt = gstate.texfilter & 0x7; + key.minFilt = minFilt & 1; + key.mipEnable = (minFilt >> 2) & 1; + key.mipFilt = (minFilt >> 1) & 1; + key.magFilt = gstate.isMagnifyFilteringEnabled(); + key.sClamp = gstate.isTexCoordClampedS(); + key.tClamp = gstate.isTexCoordClampedT(); + key.aniso = false; GETexLevelMode mipMode = gstate.getTexLevelMode(); - mode = mipMode; - bool autoMip = mipMode == GE_TEXLEVEL_MODE_AUTO; // TODO: Slope mipmap bias is still not well understood. - lodBias = (float)gstate.getTexLevelOffset16() * (1.0f / 16.0f); + float lodBias = (float)gstate.getTexLevelOffset16() * (1.0f / 16.0f); if (mipMode == GE_TEXLEVEL_MODE_SLOPE) { lodBias += 1.0f + TexLog2(gstate.getTextureLodSlope()) * (1.0f / 256.0f); } @@ -171,72 +175,18 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl if (noMip) { // Enforce no mip filtering, for safety. - minFilt &= 1; // no mipmaps yet + key.mipEnable = false; + key.mipFilt = 0; lodBias = 0.0f; } - if (!(magFilt & 1) && addr != 0 && g_Config.iTexFiltering != TEX_FILTER_FORCE_NEAREST) { - if (videos_.find(addr & 0x3FFFFFFF) != videos_.end()) { - // Enforce bilinear filtering on magnification. - magFilt |= 1; - } - } - - // Filtering overrides - switch (g_Config.iTexFiltering) { - case TEX_FILTER_AUTO: - // Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors - // in higher resolution (used by some games for sprites, and they accidentally have linear filter on). - if (gstate.isModeThrough() && g_Config.iInternalResolution != 1) { - bool uglyColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && gstate.getColorTestRef() != 0; - if (uglyColorTest) { - // Force to nearest. - magFilt &= ~1; - minFilt &= ~1; - } - } - break; - case TEX_FILTER_FORCE_LINEAR: - // Override to linear filtering if there's no alpha or color testing going on. - if ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) && - (!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue())) { - magFilt |= 1; - minFilt |= 1; - } - break; - case TEX_FILTER_FORCE_NEAREST: - default: - // Just force to nearest without checks. Safe (but ugly). - magFilt &= ~1; - minFilt &= ~1; - break; - } -} - -void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key) { - // TODO: Make GetSamplingParams write SamplerCacheKey directly - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, texAddr, mode); - key.minFilt = minFilt & 1; - key.mipEnable = (minFilt >> 2) & 1; - key.mipFilt = (minFilt >> 1) & 1; - key.magFilt = magFilt & 1; - key.sClamp = sClamp; - key.tClamp = tClamp; - key.aniso = false; - if (!key.mipEnable) { key.maxLevel = 0; key.minLevel = 0; key.lodBias = 0; + key.mipFilt = 0; } else { - switch (mode) { + switch (mipMode) { case GE_TEXLEVEL_MODE_AUTO: key.maxLevel = maxLevel * 256; key.minLevel = 0; @@ -261,6 +211,67 @@ void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, Sampler break; } } + + // Video bilinear override + if (!key.magFilt && texAddr != 0) { + if (videos_.find(texAddr & 0x3FFFFFFF) != videos_.end()) { + // Enforce bilinear filtering on magnification. + key.magFilt = 1; + } + } + + // Filtering overrides + switch (g_Config.iTexFiltering) { + case TEX_FILTER_AUTO: + // Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors + // in higher resolution (used by some games for sprites, and they accidentally have linear filter on). + if (gstate.isModeThrough() && g_Config.iInternalResolution != 1) { + bool uglyColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && gstate.getColorTestRef() != 0; + if (uglyColorTest) { + // Force to nearest. + key.magFilt = 0; + key.minFilt = 0; + } + } + break; + case TEX_FILTER_FORCE_LINEAR: + // Override to linear filtering if there's no alpha or color testing going on. + if ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) && + (!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue())) { + key.magFilt = 1; + key.minFilt = 1; + key.mipFilt = 1; + } + break; + case TEX_FILTER_FORCE_NEAREST: + default: + // Just force to nearest without checks. Safe (but ugly). + key.magFilt = 0; + key.minFilt = 0; + break; + } + + return key; +} + +SamplerCacheKey TextureCacheCommon::GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { + SamplerCacheKey key = GetSamplingParams(0, 0); + + // Kill any mipmapping settings. + key.mipEnable = false; + key.minFilt &= 1; + key.mipFilt = 0; + key.magFilt &= 1; + key.aniso = 0.0; + + // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. + int w = gstate.getTextureWidth(0); + int h = gstate.getTextureHeight(0); + if (w != bufferWidth || h != bufferHeight) { + key.sClamp = true; + key.tClamp = true; + } + return key; } void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 652eba6578..17a1aa4de7 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -284,8 +284,9 @@ protected: } u32 EstimateTexMemoryUsage(const TexCacheEntry *entry); - void GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, int maxLevel, u32 addr, GETexLevelMode &mode); - void UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key); // Used by D3D11 and Vulkan. + + SamplerCacheKey GetSamplingParams(int maxLevel, u32 texAddr); + SamplerCacheKey GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); void UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode); FramebufferMatchInfo MatchFramebuffer(const TextureDefinition &entry, VirtualFramebuffer *framebuffer, u32 texaddrOffset, FramebufferNotificationChannel channel) const; diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 0c1f1d3524..bf41243b88 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -17,19 +17,19 @@ #pragma once -#include -#include +#include +#include #include #include "GPU/GPUCommon.h" #include "GPU/D3D11/DrawEngineD3D11.h" -#include "GPU/D3D11/TextureCacheD3D11.h" #include "GPU/D3D11/DepalettizeShaderD3D11.h" #include "GPU/Common/VertexDecoderCommon.h" class FramebufferManagerD3D11; class ShaderManagerD3D11; class LinkedShaderD3D11; +class TextureCacheD3D11; class GPU_D3D11 : public GPUCommon { public: diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 01d102271a..2d3ec0f29f 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -156,31 +156,6 @@ void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) { } } -void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode); - - key.minFilt = minFilt & 1; - key.mipFilt = 0; - key.magFilt = magFilt & 1; - key.sClamp = sClamp; - key.tClamp = tClamp; - - // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. - // This happens whether we have OES_texture_npot or not. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - if (w != bufferWidth || h != bufferHeight) { - key.sClamp = true; - key.tClamp = true; - } -} - void TextureCacheD3D11::StartFrame() { InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; @@ -239,10 +214,9 @@ void TextureCacheD3D11::BindTexture(TexCacheEntry *entry) { context_->PSSetShaderResources(0, 1, &textureView); lastBoundTexture = textureView; } - SamplerCacheKey key{}; int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; - UpdateSamplingParams(maxLevel, entry->addr, key); - ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, key); + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey); context_->PSSetSamplers(0, 1, &state); } @@ -428,8 +402,8 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, gstate_c.SetTextureFullAlpha(gstate.getTextureFormat() == GE_TFMT_5650); framebufferManagerD3D11_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFramebuffer"); // Probably not necessary. } - SamplerCacheKey samplerKey{}; - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey); + + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey); context_->PSSetSamplers(0, 1, &state); diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index db154c5a77..6aa3bcda9e 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -60,7 +60,6 @@ public: void ForgetLastTexture() override; void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; protected: diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index aab20eabe1..6f33fcf90c 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -17,13 +17,12 @@ #pragma once -#include -#include +#include +#include #include "GPU/GPUCommon.h" #include "GPU/Directx9/FramebufferManagerDX9.h" #include "GPU/Directx9/DrawEngineDX9.h" -#include "GPU/Directx9/TextureCacheDX9.h" #include "GPU/Directx9/DepalettizeShaderDX9.h" #include "GPU/Common/VertexDecoderCommon.h" @@ -31,6 +30,7 @@ namespace DX9 { class ShaderManagerDX9; class LinkedShaderDX9; +class TextureCacheDX9; class GPU_DX9 : public GPUCommon { public: diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 667a972349..65480a8520 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -119,101 +119,24 @@ D3DFORMAT getClutDestFormat(GEPaletteFormat format) { return D3DFMT_A8R8G8B8; } -static const u8 MinFilt[8] = { - D3DTEXF_POINT, - D3DTEXF_LINEAR, - D3DTEXF_POINT, - D3DTEXF_LINEAR, - D3DTEXF_POINT, // GL_NEAREST_MIPMAP_NEAREST, - D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_NEAREST, - D3DTEXF_POINT, // GL_NEAREST_MIPMAP_LINEAR, - D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_LINEAR, -}; +void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) { + dxstate.texMinFilter.set(key.minFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT); + dxstate.texMipFilter.set(key.mipFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT); + dxstate.texMagFilter.set(key.magFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT); -static const u8 MipFilt[8] = { - D3DTEXF_NONE, - D3DTEXF_NONE, - D3DTEXF_NONE, - D3DTEXF_NONE, - D3DTEXF_POINT, // GL_NEAREST_MIPMAP_NEAREST, - D3DTEXF_POINT, // GL_LINEAR_MIPMAP_NEAREST, - D3DTEXF_LINEAR, // GL_NEAREST_MIPMAP_LINEAR, - D3DTEXF_LINEAR, // GL_LINEAR_MIPMAP_LINEAR, -}; + // DX9 mip levels are .. odd. The "max level" sets the LARGEST mip to use. + // We can enforce only the top mip level by setting a massive negative lod bias. -static const u8 MagFilt[2] = { - D3DTEXF_POINT, - D3DTEXF_LINEAR -}; - -void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, mode); - - if (maxLevel != 0) { - if (mode == GE_TEXLEVEL_MODE_AUTO) { - dxstate.texMaxMipLevel.set(0); - dxstate.texMipLodBias.set(lodBias); - } else if (mode == GE_TEXLEVEL_MODE_CONST) { - // TODO: This is just an approximation - texMaxMipLevel sets the lowest numbered mip to use. - // Unfortunately, this doesn't support a const 1.5 or etc. - dxstate.texMaxMipLevel.set(std::max(0, std::min((int)maxLevel, (int)lodBias))); - dxstate.texMipLodBias.set(-1000.0f); - } else { // if (mode == GE_TEXLEVEL_MODE_SLOPE{ - dxstate.texMaxMipLevel.set(0); - dxstate.texMipLodBias.set(0.0f); - } - } else { + if (!key.mipEnable) { dxstate.texMaxMipLevel.set(0); - dxstate.texMipLodBias.set(0.0f); + dxstate.texMipLodBias.set(-100.0f); + } else { + dxstate.texMipLodBias.set((float)key.lodBias / 256.0f); + dxstate.texMaxMipLevel.set(key.minLevel / 256); } - D3DTEXTUREFILTERTYPE minf = (D3DTEXTUREFILTERTYPE)MinFilt[minFilt]; - D3DTEXTUREFILTERTYPE mipf = (D3DTEXTUREFILTERTYPE)MipFilt[minFilt]; - D3DTEXTUREFILTERTYPE magf = (D3DTEXTUREFILTERTYPE)MagFilt[magFilt]; - - if (gstate_c.Supports(GPU_SUPPORTS_ANISOTROPY) && g_Config.iAnisotropyLevel > 0 && minf == D3DTEXF_LINEAR) { - minf = D3DTEXF_ANISOTROPIC; - } - - dxstate.texMinFilter.set(minf); - dxstate.texMipFilter.set(mipf); - dxstate.texMagFilter.set(magf); - dxstate.texAddressU.set(sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); - dxstate.texAddressV.set(tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); -} - -void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode); - - dxstate.texMinFilter.set(MinFilt[minFilt]); - dxstate.texMipFilter.set(MipFilt[minFilt]); - dxstate.texMagFilter.set(MagFilt[magFilt]); - dxstate.texMipLodBias.set(0.0f); - dxstate.texMaxMipLevel.set(0.0f); - - // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. - // This happens whether we have OES_texture_npot or not. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - if (w != bufferWidth || h != bufferHeight) { - return; - } - - dxstate.texAddressU.set(sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); - dxstate.texAddressV.set(tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); + dxstate.texAddressU.set(key.sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); + dxstate.texAddressV.set(key.tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); } void TextureCacheDX9::StartFrame() { @@ -236,7 +159,6 @@ void TextureCacheDX9::StartFrame() { DWORD anisotropyLevel = aniso > maxAnisotropyLevel ? maxAnisotropyLevel : aniso; device_->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, anisotropyLevel); } - } void TextureCacheDX9::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { @@ -281,7 +203,9 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { device_->SetTexture(0, texture); lastBoundTexture = texture; } - UpdateSamplingParams(*entry, false); + int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + ApplySamplingParams(samplerKey); } void TextureCacheDX9::Unbind() { @@ -467,7 +391,9 @@ void TextureCacheDX9::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, G } framebufferManagerDX9_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFromFramebuffer"); - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + ApplySamplingParams(samplerKey); } void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index a0d488c77b..3a0c291586 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -52,8 +52,6 @@ public: void ForgetLastTexture() override; void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); - bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; protected: @@ -62,7 +60,8 @@ protected: void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: - void UpdateSamplingParams(TexCacheEntry &entry, bool force); + void ApplySamplingParams(const SamplerCacheKey &key); + void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, int scaleFactor, u32 dstFmt); D3DFORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; TexCacheEntry::TexStatus CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 0775ec8d8b..5bb68e2ef3 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -17,17 +17,17 @@ #pragma once -#include -#include +#include +#include #include "GPU/GPUCommon.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/DrawEngineGLES.h" -#include "GPU/GLES/TextureCacheGLES.h" #include "GPU/GLES/DepalettizeShaderGLES.h" #include "GPU/GLES/FragmentTestCacheGLES.h" class ShaderManagerGLES; +class TextureCacheGLES; class LinkedShader; class GPU_GLES : public GPUCommon { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6ee2eabcd8..292fa20ba1 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -115,76 +115,19 @@ static const GLuint MagFiltGL[2] = { GL_LINEAR }; -// This should not have to be done per texture! OpenGL is silly yo -void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - u8 maxLevel = (entry.status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry.maxLevel; - GETexLevelMode mode; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, maxLevel, entry.addr, mode); - +void TextureCacheGLES::ApplySamplingParams(const SamplerCacheKey &key) { if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) { - float minLod = 0.0f; - float maxLod = 0.0f; - if (maxLevel != 0) { - // TODO: What about a swap of autoMip mode? - if (true) { - if (mode == GE_TEXLEVEL_MODE_AUTO) { - minLod = 0.0f; - maxLod = (float)maxLevel; - } else if (mode == GE_TEXLEVEL_MODE_CONST) { - minLod = std::max(0.0f, std::min((float)maxLevel, lodBias)); - maxLod = std::max(0.0f, std::min((float)maxLevel, lodBias)); - } else { // mode == GE_TEXLEVEL_MODE_SLOPE) { - // It's incorrect to use the slope as a bias. Instead it should be passed - // into the shader directly as an explicit lod level, with the bias on top. For now, we just kill the - // lodBias in this mode, working around #9772. -#ifndef USING_GLES2 - lodBias = 0.0f; -#endif - minLod = 0.0f; - maxLod = (float)maxLevel; - } - } - } else { - minLod = 0.0f; - maxLod = 0.0f; - } + float minLod = (float)key.minLevel / 256.0f; + float maxLod = (float)key.maxLevel / 256.0f; + float lodBias = (float)key.lodBias / 256.0f; render_->SetTextureLod(0, minLod, maxLod, lodBias); } float aniso = 0.0f; - render_->SetTextureSampler(0, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); -} - -void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode); - - minFilt &= 1; // framebuffers can't mipmap. - if (forcePoint) { - minFilt &= ~1; - magFilt &= ~1; - } - - // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. - // This happens whether we have OES_texture_npot or not. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - if (w != bufferWidth || h != bufferHeight) { - sClamp = true; - tClamp = true; - } - float aniso = 0.0f; - render_->SetTextureSampler(TEX_SLOT_PSP_TEXTURE, sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, MagFiltGL[magFilt], MinFiltGL[minFilt], aniso); + int magKey = ((int)key.mipEnable << 2) | ((int)key.mipFilt << 1) | ((int)key.magFilt); + render_->SetTextureSampler(0, + key.sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, key.tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, + MagFiltGL[magKey], key.minFilt ? GL_LINEAR : GL_NEAREST, aniso); } static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dstFmt, int numPixels) { @@ -287,7 +230,9 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { render_->BindTexture(0, entry->textureName); lastBoundTexture = entry->textureName; } - UpdateSamplingParams(*entry, false); + int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + ApplySamplingParams(samplerKey); gstate_c.SetUseShaderDepal(false); } @@ -415,7 +360,11 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, render_->BindTexture(TEX_SLOT_CLUT, clutTexture); render_->SetTextureSampler(TEX_SLOT_CLUT, GL_REPEAT, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f); framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV | BINDFBCOLOR_APPLY_TEX_OFFSET); - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, true); + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + samplerKey.magFilt = false; + samplerKey.minFilt = false; + samplerKey.mipEnable = false; + ApplySamplingParams(samplerKey); InvalidateLastTexture(); // Since we started/ended render passes, might need these. @@ -465,7 +414,9 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, } framebufferManagerGL_->RebindFramebuffer("ApplyTextureFramebuffer"); - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, false); + + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + ApplySamplingParams(samplerKey); // Since we started/ended render passes, might need these. gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); @@ -648,7 +599,9 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { // This will rebind it, but that's okay. // Need to actually bind it now - it might only have gotten bound in the init phase. render_->BindTexture(TEX_SLOT_PSP_TEXTURE, entry->textureName); - UpdateSamplingParams(*entry, true); + + SamplerCacheKey samplerKey = GetSamplingParams(entry->maxLevel, entry->addr); + ApplySamplingParams(samplerKey); } Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 36e203579f..7564b635b5 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -63,7 +63,6 @@ public: } } - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; void DeviceLost(); @@ -75,7 +74,7 @@ protected: void ReleaseTexture(TexCacheEntry *entry, bool delete_them) override; private: - void UpdateSamplingParams(TexCacheEntry &entry, bool force); + void ApplySamplingParams(const SamplerCacheKey &key); void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int scaleFactor, Draw::DataFormat dstFmt); Draw::DataFormat GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const; diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index 8f2cc381a4..023e840d56 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -25,6 +25,7 @@ #include "Common/Vulkan/VulkanImage.h" #include "GPU/Vulkan/GPU_Vulkan.h" #include "GPU/Vulkan/VulkanUtil.h" +#include "GPU/Vulkan/TextureCacheVulkan.h" #undef DrawText diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index a56304869b..894cc295b4 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -17,18 +17,18 @@ #pragma once -#include -#include +#include +#include #include "GPU/GPUCommon.h" #include "GPU/Vulkan/DrawEngineVulkan.h" #include "GPU/Vulkan/PipelineManagerVulkan.h" -#include "GPU/Vulkan/TextureCacheVulkan.h" #include "GPU/Vulkan/DepalettizeShaderVulkan.h" class FramebufferManagerVulkan; class ShaderManagerVulkan; class LinkedShader; +class TextureCacheVulkan; class GPU_Vulkan : public GPUCommon { public: diff --git a/GPU/Vulkan/StateMappingVulkan.cpp b/GPU/Vulkan/StateMappingVulkan.cpp index 56980441dc..596badb5c7 100644 --- a/GPU/Vulkan/StateMappingVulkan.cpp +++ b/GPU/Vulkan/StateMappingVulkan.cpp @@ -28,7 +28,6 @@ #include "Core/Reporting.h" #include "GPU/Vulkan/GPU_Vulkan.h" #include "GPU/Vulkan/PipelineManagerVulkan.h" -#include "GPU/Vulkan/TextureCacheVulkan.h" #include "GPU/Vulkan/FramebufferManagerVulkan.h" #include "GPU/Vulkan/ShaderManagerVulkan.h" #include "GPU/Vulkan/DrawEngineVulkan.h" diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 8627099be6..c015c498e1 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -439,31 +439,6 @@ static const VkFilter MagFiltVK[2] = { VK_FILTER_LINEAR }; -void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - int minFilt; - int magFilt; - bool sClamp; - bool tClamp; - float lodBias; - GETexLevelMode mode; - GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0, mode); - - key.minFilt = minFilt & 1; - key.mipFilt = 0; - key.magFilt = magFilt & 1; - key.sClamp = sClamp; - key.tClamp = tClamp; - - // Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case. - // This happens whether we have OES_texture_npot or not. - int w = gstate.getTextureWidth(0); - int h = gstate.getTextureHeight(0); - if (w != bufferWidth || h != bufferHeight) { - key.sClamp = true; - key.tClamp = true; - } -} - void TextureCacheVulkan::StartFrame() { InvalidateLastTexture(); depalShaderCache_->Decimate(); @@ -541,10 +516,9 @@ void TextureCacheVulkan::BindTexture(TexCacheEntry *entry) { entry->vkTex->Touch(); imageView_ = entry->vkTex->GetImageView(); - SamplerCacheKey key{}; int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; - UpdateSamplingParams(maxLevel, entry->addr, key); - curSampler_ = samplerCache_.GetOrCreateSampler(key); + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + curSampler_ = samplerCache_.GetOrCreateSampler(samplerKey); drawEngine_->SetDepalTexture(VK_NULL_HANDLE); gstate_c.SetUseShaderDepal(false); } @@ -556,8 +530,7 @@ void TextureCacheVulkan::Unbind() { } void TextureCacheVulkan::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, FramebufferNotificationChannel channel) { - SamplerCacheKey samplerKey{}; - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, samplerKey); + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); DepalShaderVulkan *depalShader = nullptr; uint32_t clutMode = gstate.clutformat & 0xFFFFFF; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 059b4be0ec..7aaa04d56e 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -100,7 +100,6 @@ public: imageView = imageView_; sampler = curSampler_; } - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;