From b81e0669e6a6cfac09a2767a4ae3042cce2794a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 22:37:16 +0200 Subject: [PATCH 1/9] TextureCacheDX9: Use the already centralized sampler setup code from D3D11/Vulkan. --- GPU/D3D11/TextureCacheD3D11.cpp | 14 ++---- GPU/Directx9/TextureCacheDX9.cpp | 84 ++++++++------------------------ GPU/Directx9/TextureCacheDX9.h | 3 +- GPU/GLES/TextureCacheGLES.cpp | 2 + 4 files changed, 28 insertions(+), 75 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 01d102271a..8e4b72b338 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -157,19 +157,11 @@ 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); + UpdateSamplingParams(0, 0, key); - key.minFilt = minFilt & 1; + key.minFilt &= 1; key.mipFilt = 0; - key.magFilt = magFilt & 1; - key.sClamp = sClamp; - key.tClamp = tClamp; + key.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. diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 667a972349..89b294b763 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -146,74 +146,30 @@ static const u8 MagFilt[2] = { 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 { - dxstate.texMaxMipLevel.set(0); - dxstate.texMipLodBias.set(0.0f); - } - - 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); + SamplerCacheKey key; + UpdateSamplingParams(0, 0, key); - 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. + // 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) { - return; + key.sClamp = true; + key.tClamp = true; } - dxstate.texAddressU.set(sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); - dxstate.texAddressV.set(tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); + ApplySamplingParams(key); +} + +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); + dxstate.texMipLodBias.set((float)key.lodBias / 256.0f); + dxstate.texMaxMipLevel.set(key.maxLevel / 256); + + dxstate.texAddressU.set(key.sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); + dxstate.texAddressV.set(key.tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); } void TextureCacheDX9::StartFrame() { @@ -236,7 +192,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 +236,10 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { device_->SetTexture(0, texture); lastBoundTexture = texture; } - UpdateSamplingParams(*entry, false); + + SamplerCacheKey key; + UpdateSamplingParams(entry->maxLevel, entry->addr, key); + ApplySamplingParams(key); } void TextureCacheDX9::Unbind() { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index a0d488c77b..4e48ffc376 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -62,7 +62,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/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6ee2eabcd8..34294ca681 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -161,6 +161,8 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) { } void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint) { + SamplerCacheKey key; + UpdateSamplingParams(0, 0, key); int minFilt; int magFilt; bool sClamp; From 9ea295093bdd364d343b126218d3e1059b95ef12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 22:48:44 +0200 Subject: [PATCH 2/9] TextureCacheGLES: Also share the same sampler calculation for GLES. --- GPU/GLES/TextureCacheGLES.cpp | 78 +++++++++---------------------- GPU/GLES/TextureCacheGLES.h | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 15 ++---- 3 files changed, 27 insertions(+), 68 deletions(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 34294ca681..9a4b5df1ab 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -115,78 +115,39 @@ 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); + 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); } void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint) { SamplerCacheKey key; UpdateSamplingParams(0, 0, key); - 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. + key.mipEnable = false; // framebuffers can't mipmap. if (forcePoint) { - minFilt &= ~1; - magFilt &= ~1; + key.magFilt = false; + key.minFilt = false; } - // 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; + key.sClamp = true; + key.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); + key.aniso = 0.0f; + ApplySamplingParams(key); } static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dstFmt, int numPixels) { @@ -289,7 +250,9 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { render_->BindTexture(0, entry->textureName); lastBoundTexture = entry->textureName; } - UpdateSamplingParams(*entry, false); + SamplerCacheKey key; + UpdateSamplingParams(entry->maxLevel, entry->addr, key); + ApplySamplingParams(key); gstate_c.SetUseShaderDepal(false); } @@ -650,7 +613,10 @@ 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 key; + UpdateSamplingParams(entry->maxLevel, entry->addr, key); + ApplySamplingParams(key); } Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const { diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 36e203579f..0e85dc58c3 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -75,7 +75,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/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 8627099be6..0b3fa58544 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -440,24 +440,17 @@ static const VkFilter MagFiltVK[2] = { }; 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); + UpdateSamplingParams(0, 0, key); - key.minFilt = minFilt & 1; + key.minFilt &= 1; key.mipFilt = 0; - key.magFilt = magFilt & 1; - key.sClamp = sClamp; - key.tClamp = tClamp; + key.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) { key.sClamp = true; key.tClamp = true; From 46b3fb0821b43edfd6c86706b648474a2998f31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 23:10:43 +0200 Subject: [PATCH 3/9] Workarounds for D3D9's very limited mip level control. --- GPU/Common/TextureCacheCommon.cpp | 31 +++++++-------------- GPU/D3D11/TextureCacheD3D11.cpp | 1 + GPU/Directx9/TextureCacheDX9.cpp | 45 +++++++++++-------------------- GPU/Vulkan/TextureCacheVulkan.cpp | 1 + 4 files changed, 28 insertions(+), 50 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 668db2a130..1fedfa67d3 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -146,19 +146,18 @@ 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(); +void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key) { + int minFilt = gstate.texfilter & 0x7; + int magFilt = gstate.isMagnifyFilteringEnabled(); + bool sClamp = gstate.isTexCoordClampedS(); + bool tClamp = gstate.isTexCoordClampedT(); 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); } @@ -175,8 +174,8 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl lodBias = 0.0f; } - if (!(magFilt & 1) && addr != 0 && g_Config.iTexFiltering != TEX_FILTER_FORCE_NEAREST) { - if (videos_.find(addr & 0x3FFFFFFF) != videos_.end()) { + if (!(magFilt & 1) && texAddr != 0 && g_Config.iTexFiltering != TEX_FILTER_FORCE_NEAREST) { + if (videos_.find(texAddr & 0x3FFFFFFF) != videos_.end()) { // Enforce bilinear filtering on magnification. magFilt |= 1; } @@ -211,18 +210,7 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl 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; @@ -235,8 +223,9 @@ void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, Sampler 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; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 8e4b72b338..717a4b8119 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -159,6 +159,7 @@ void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) { void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { UpdateSamplingParams(0, 0, key); + key.mipEnable = false; key.minFilt &= 1; key.mipFilt = 0; key.magFilt &= 1; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 89b294b763..16272c3b84 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -119,37 +119,15 @@ 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, -}; - -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, -}; - -static const u8 MagFilt[2] = { - D3DTEXF_POINT, - D3DTEXF_LINEAR -}; - void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { SamplerCacheKey key; UpdateSamplingParams(0, 0, key); + key.mipEnable = false; + key.minFilt &= 1; + key.mipFilt = 0; + key.magFilt &= 1; + // 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); @@ -165,8 +143,17 @@ 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); - dxstate.texMipLodBias.set((float)key.lodBias / 256.0f); - dxstate.texMaxMipLevel.set(key.maxLevel / 256); + + // 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. + + if (!key.mipEnable) { + dxstate.texMaxMipLevel.set(0); + dxstate.texMipLodBias.set(-100.0f); + } else { + dxstate.texMipLodBias.set((float)key.lodBias / 256.0f); + dxstate.texMaxMipLevel.set(key.minLevel / 256); + } dxstate.texAddressU.set(key.sClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); dxstate.texAddressV.set(key.tClamp ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 0b3fa58544..6ecd34e419 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -442,6 +442,7 @@ static const VkFilter MagFiltVK[2] = { void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { UpdateSamplingParams(0, 0, key); + key.mipEnable = false; key.minFilt &= 1; key.mipFilt = 0; key.magFilt &= 1; From d8263d50f467061d34a8b72bcdf0df93eaea879b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 23:25:21 +0200 Subject: [PATCH 4/9] Make the signature of all the SetFramebufferSamplingParams the same --- GPU/D3D11/TextureCacheD3D11.cpp | 1 + GPU/Directx9/TextureCacheDX9.cpp | 10 +++++----- GPU/Directx9/TextureCacheDX9.h | 2 +- GPU/GLES/TextureCacheGLES.cpp | 20 +++++++++++--------- GPU/GLES/TextureCacheGLES.h | 2 +- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 717a4b8119..b9ceb5326e 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -421,6 +421,7 @@ 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); ID3D11SamplerState *state = samplerCache_.GetOrCreateSampler(device_, samplerKey); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 16272c3b84..cafe16f7d0 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -119,8 +119,7 @@ D3DFORMAT getClutDestFormat(GEPaletteFormat format) { return D3DFMT_A8R8G8B8; } -void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight) { - SamplerCacheKey key; +void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { UpdateSamplingParams(0, 0, key); key.mipEnable = false; @@ -135,8 +134,6 @@ void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHe key.sClamp = true; key.tClamp = true; } - - ApplySamplingParams(key); } void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) { @@ -412,7 +409,10 @@ void TextureCacheDX9::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, G } framebufferManagerDX9_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFromFramebuffer"); - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + + SamplerCacheKey key; + SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); + ApplySamplingParams(key); } void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 4e48ffc376..9b2d9315bc 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -52,7 +52,7 @@ public: void ForgetLastTexture() override; void InvalidateLastTexture(TexCacheEntry *entry = nullptr) override; - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); + void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 9a4b5df1ab..cb0ce93ef2 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -130,14 +130,9 @@ void TextureCacheGLES::ApplySamplingParams(const SamplerCacheKey &key) { MagFiltGL[magKey], key.minFilt ? GL_LINEAR : GL_NEAREST, aniso); } -void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint) { - SamplerCacheKey key; +void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { UpdateSamplingParams(0, 0, key); key.mipEnable = false; // framebuffers can't mipmap. - if (forcePoint) { - key.magFilt = false; - key.minFilt = false; - } // 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); @@ -147,7 +142,6 @@ void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferH key.tClamp = true; } key.aniso = 0.0f; - ApplySamplingParams(key); } static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dstFmt, int numPixels) { @@ -380,7 +374,12 @@ 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 key; + SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); + key.magFilt = false; + key.minFilt = false; + key.mipEnable = false; + ApplySamplingParams(key); InvalidateLastTexture(); // Since we started/ended render passes, might need these. @@ -430,7 +429,10 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, } framebufferManagerGL_->RebindFramebuffer("ApplyTextureFramebuffer"); - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, false); + + SamplerCacheKey key; + SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); + ApplySamplingParams(key); // Since we started/ended render passes, might need these. gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE); diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 0e85dc58c3..42329b57a2 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -63,7 +63,7 @@ public: } } - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, bool forcePoint); + void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; void DeviceLost(); From 5190f85c8e426c4e12d8ce4b9b810acd64ecb999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 23:34:00 +0200 Subject: [PATCH 5/9] Unify/centralize SetFramebufferSamplingParams. Some include cleanup. --- GPU/Common/TextureCacheCommon.cpp | 18 ++++++++++++++++++ GPU/Common/TextureCacheCommon.h | 3 ++- GPU/D3D11/GPU_D3D11.h | 6 +++--- GPU/D3D11/TextureCacheD3D11.cpp | 18 ------------------ GPU/D3D11/TextureCacheD3D11.h | 1 - GPU/Directx9/GPU_DX9.h | 6 +++--- GPU/Directx9/TextureCacheDX9.cpp | 17 ----------------- GPU/Directx9/TextureCacheDX9.h | 2 -- GPU/GLES/GPU_GLES.h | 6 +++--- GPU/GLES/TextureCacheGLES.cpp | 14 -------------- GPU/GLES/TextureCacheGLES.h | 1 - GPU/Vulkan/DebugVisVulkan.cpp | 1 + GPU/Vulkan/GPU_Vulkan.h | 6 +++--- GPU/Vulkan/StateMappingVulkan.cpp | 1 - GPU/Vulkan/TextureCacheVulkan.cpp | 19 ------------------- GPU/Vulkan/TextureCacheVulkan.h | 1 - 16 files changed, 33 insertions(+), 87 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 1fedfa67d3..04a8669ce1 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -252,6 +252,24 @@ void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, Sampler } } +void TextureCacheCommon::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { + UpdateSamplingParams(0, 0, key); + + 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; + } +} + void TextureCacheCommon::UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode) { // If the texture is >= 512 pixels tall... if (entry->dim >= 0x900) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 652eba6578..db75b9baba 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. + void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); 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 b9ceb5326e..3957b48c5c 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -156,24 +156,6 @@ void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) { } } -void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - UpdateSamplingParams(0, 0, key); - - key.mipEnable = false; - key.minFilt &= 1; - key.mipFilt = 0; - key.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) { - key.sClamp = true; - key.tClamp = true; - } -} - void TextureCacheD3D11::StartFrame() { InvalidateLastTexture(); timesInvalidatedAllThisFrame_ = 0; 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 cafe16f7d0..5343a3100b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -119,23 +119,6 @@ D3DFORMAT getClutDestFormat(GEPaletteFormat format) { return D3DFMT_A8R8G8B8; } -void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - UpdateSamplingParams(0, 0, key); - - key.mipEnable = false; - key.minFilt &= 1; - key.mipFilt = 0; - key.magFilt &= 1; - - // 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; - } -} - void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) { dxstate.texMinFilter.set(key.minFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT); dxstate.texMipFilter.set(key.mipFilt ? D3DTEXF_LINEAR : D3DTEXF_POINT); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 9b2d9315bc..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, SamplerCacheKey &key); - bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; protected: 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 cb0ce93ef2..1b7af5f044 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -130,20 +130,6 @@ void TextureCacheGLES::ApplySamplingParams(const SamplerCacheKey &key) { MagFiltGL[magKey], key.minFilt ? GL_LINEAR : GL_NEAREST, aniso); } -void TextureCacheGLES::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - UpdateSamplingParams(0, 0, key); - key.mipEnable = false; // framebuffers can't mipmap. - // 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; - } - key.aniso = 0.0f; -} - static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dstFmt, int numPixels) { const u32 *src = (const u32 *)srcBuf; u32 *dst = (u32 *)dstBuf; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 42329b57a2..7564b635b5 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -63,7 +63,6 @@ public: } } - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override; void DeviceLost(); 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 6ecd34e419..e17cbae949 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -439,25 +439,6 @@ static const VkFilter MagFiltVK[2] = { VK_FILTER_LINEAR }; -void TextureCacheVulkan::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - UpdateSamplingParams(0, 0, key); - - key.mipEnable = false; - key.minFilt &= 1; - key.mipFilt = 0; - key.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) { - key.sClamp = true; - key.tClamp = true; - } -} - void TextureCacheVulkan::StartFrame() { InvalidateLastTexture(); depalShaderCache_->Decimate(); 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; From a222b2017ecb6c587e3eab1ba3498b819cbc1807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 23:46:57 +0200 Subject: [PATCH 6/9] Switch to a returned value and rename these functions. --- GPU/Common/TextureCacheCommon.cpp | 12 +++++++++--- GPU/Common/TextureCacheCommon.h | 4 ++-- GPU/D3D11/TextureCacheD3D11.cpp | 8 +++----- GPU/Directx9/TextureCacheDX9.cpp | 12 +++++------- GPU/GLES/TextureCacheGLES.cpp | 27 ++++++++++++--------------- GPU/Vulkan/TextureCacheVulkan.cpp | 8 +++----- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 04a8669ce1..33ae0baa1b 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -146,7 +146,9 @@ static int TexLog2(float delta) { return useful - 127 * 256; } -void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key) { +SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) { + SamplerCacheKey key; + int minFilt = gstate.texfilter & 0x7; int magFilt = gstate.isMagnifyFilteringEnabled(); bool sClamp = gstate.isTexCoordClampedS(); @@ -250,11 +252,14 @@ void TextureCacheCommon::UpdateSamplingParams(int maxLevel, u32 texAddr, Sampler break; } } + + return key; } -void TextureCacheCommon::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key) { - UpdateSamplingParams(0, 0, 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; @@ -268,6 +273,7 @@ void TextureCacheCommon::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffe 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 db75b9baba..17a1aa4de7 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -285,8 +285,8 @@ protected: u32 EstimateTexMemoryUsage(const TexCacheEntry *entry); - void UpdateSamplingParams(int maxLevel, u32 texAddr, SamplerCacheKey &key); // Used by D3D11 and Vulkan. - void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight, SamplerCacheKey &key); + 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/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 3957b48c5c..2d3ec0f29f 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -214,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); } @@ -404,8 +403,7 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, 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/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 5343a3100b..65480a8520 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -203,10 +203,9 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { device_->SetTexture(0, texture); lastBoundTexture = texture; } - - SamplerCacheKey key; - UpdateSamplingParams(entry->maxLevel, entry->addr, key); - ApplySamplingParams(key); + int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + ApplySamplingParams(samplerKey); } void TextureCacheDX9::Unbind() { @@ -393,9 +392,8 @@ void TextureCacheDX9::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, G framebufferManagerDX9_->RebindFramebuffer("RebindFramebuffer - ApplyTextureFromFramebuffer"); - SamplerCacheKey key; - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); - ApplySamplingParams(key); + SamplerCacheKey samplerKey = GetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight); + ApplySamplingParams(samplerKey); } void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 1b7af5f044..292fa20ba1 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -230,9 +230,9 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { render_->BindTexture(0, entry->textureName); lastBoundTexture = entry->textureName; } - SamplerCacheKey key; - UpdateSamplingParams(entry->maxLevel, entry->addr, key); - ApplySamplingParams(key); + int maxLevel = (entry->status & TexCacheEntry::STATUS_BAD_MIPS) ? 0 : entry->maxLevel; + SamplerCacheKey samplerKey = GetSamplingParams(maxLevel, entry->addr); + ApplySamplingParams(samplerKey); gstate_c.SetUseShaderDepal(false); } @@ -360,12 +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); - SamplerCacheKey key; - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); - key.magFilt = false; - key.minFilt = false; - key.mipEnable = false; - ApplySamplingParams(key); + 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. @@ -416,9 +415,8 @@ void TextureCacheGLES::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, framebufferManagerGL_->RebindFramebuffer("ApplyTextureFramebuffer"); - SamplerCacheKey key; - SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight, key); - ApplySamplingParams(key); + 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); @@ -602,9 +600,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { // Need to actually bind it now - it might only have gotten bound in the init phase. render_->BindTexture(TEX_SLOT_PSP_TEXTURE, entry->textureName); - SamplerCacheKey key; - UpdateSamplingParams(entry->maxLevel, entry->addr, key); - ApplySamplingParams(key); + SamplerCacheKey samplerKey = GetSamplingParams(entry->maxLevel, entry->addr); + ApplySamplingParams(samplerKey); } Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index e17cbae949..c015c498e1 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -516,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); } @@ -531,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; From 0e464a61e02c3f23f47e70a9dfec2549e06f8d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 13 Sep 2020 23:59:26 +0200 Subject: [PATCH 7/9] Move overrides to the end of GetSamplingParams --- GPU/Common/TextureCacheCommon.cpp | 61 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 33ae0baa1b..a37d5fecb9 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -183,36 +183,6 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) } } - // 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; - } - key.minFilt = minFilt & 1; key.mipEnable = (minFilt >> 2) & 1; key.mipFilt = (minFilt >> 1) & 1; @@ -253,6 +223,37 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) } } + // 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; } From f3ce685b0e2bdb48403d5b0207aefbc3ca910cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 14 Sep 2020 00:00:52 +0200 Subject: [PATCH 8/9] Also move video filtering override. --- GPU/Common/TextureCacheCommon.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index a37d5fecb9..2ae3adc900 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -176,13 +176,6 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) lodBias = 0.0f; } - if (!(magFilt & 1) && texAddr != 0 && g_Config.iTexFiltering != TEX_FILTER_FORCE_NEAREST) { - if (videos_.find(texAddr & 0x3FFFFFFF) != videos_.end()) { - // Enforce bilinear filtering on magnification. - magFilt |= 1; - } - } - key.minFilt = minFilt & 1; key.mipEnable = (minFilt >> 2) & 1; key.mipFilt = (minFilt >> 1) & 1; @@ -223,6 +216,14 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) } } + // 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: From dce7dde5e6927229ebc1ef7f3fd58f76771062a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 14 Sep 2020 00:03:29 +0200 Subject: [PATCH 9/9] More moves --- GPU/Common/TextureCacheCommon.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 2ae3adc900..0df8d251e6 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -150,12 +150,15 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) SamplerCacheKey key; int minFilt = gstate.texfilter & 0x7; - int magFilt = gstate.isMagnifyFilteringEnabled(); - bool sClamp = gstate.isTexCoordClampedS(); - bool tClamp = gstate.isTexCoordClampedT(); + 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(); - bool autoMip = mipMode == GE_TEXLEVEL_MODE_AUTO; // TODO: Slope mipmap bias is still not well understood. @@ -172,18 +175,11 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, u32 texAddr) if (noMip) { // Enforce no mip filtering, for safety. - minFilt &= 1; // no mipmaps yet + key.mipEnable = false; + key.mipFilt = 0; lodBias = 0.0f; } - 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;