mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-22 10:49:05 +02:00
GLES: Actually apply anisotropic filtering
TextureCacheGLES passed a hardcoded 0.0f instead of key.aniso, so the
Anisotropic Filtering setting did nothing at all on the OpenGL backend, even
though GPU_USE_ANISOTROPY was advertised and D3D11/Vulkan both honor it. Looks
like it was left behind by the 2017 render manager refactor.
The queue runner now clamps to the device maximum it already queried into
maxAnisotropyLevel_ (until now unused), and only touches the parameter when the
extension is actually supported - the anisotropy branch there has been dead
since every caller passed 0.0f, so this is the first time it runs.
0.0f keeps its meaning of "don't care" for the CLUT/fragment-test/thin3d
callers; the texture cache now passes 1.0f when the setting is off, so turning
it off takes effect on already-uploaded textures instead of only new ones.
TexCache: Never use anisotropic filtering for CLUT8-indexed textures
What gets sampled for those is palette indices, depalettized by the shader
afterwards - averaging indices across an anisotropic footprint produces garbage
colors. Affects all backends, not just the GL one that just started honoring
key.aniso.
TexCache: Clear key.aniso wherever filtering is forced to nearest
It was only cleared in the two places inside the AUTO_MAX_QUALITY branch, so the
TEX_FILTER_AUTO path (pixel-mapped textures, the ugly color test heuristic), the
FORCE_NEAREST setting and the replacement-texture override could all end up
requesting nearest filtering with anisotropy still on.
Doing it in the switch that applies forceFiltering covers every path, so it
can't drift apart again.
GLES: Only record the applied anisotropy, and log skipped draws
The queue runner updated tex->anisotropy even when it skipped the call because
the value was 0.0f ("don't care") - harmless while nothing ever set anisotropy,
but now it would make the tracked state disagree with GL, so a later request for
the value it thinks is set would be wrongly skipped.
Also log when a draw is skipped for a missing vertex shader. The failure is
cached per shader ID, so without it geometry silently disappears for the rest of
the session after the one-shot OSD message.
This commit is contained in:
1 parent
388eef9d88
commit
89ebb8acc6
4 files changed
+26
-11
No files matched your search
@@ -1281,10 +1281,12 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
|
||||
tex->minFilter = c.textureSampler.minFilter;
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (tex->anisotropy != c.textureSampler.anisotropy) {
|
||||
if (c.textureSampler.anisotropy != 0.0f) {
|
||||
glTexParameterf(tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
|
||||
}
|
||||
// 0.0f means "don't care", used by callers that never want anisotropy. Note that we must
|
||||
// only record the value when we actually set it, or we'd think we had reset the texture
|
||||
// to something we never applied.
|
||||
if (tex->anisotropy != c.textureSampler.anisotropy && c.textureSampler.anisotropy != 0.0f && caps_.anisoSupported) {
|
||||
// Values above the device maximum are not allowed, and the minimum is 1.0.
|
||||
glTexParameterf(tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, std::max(1.0f, std::min(c.textureSampler.anisotropy, maxAnisotropyLevel_)));
|
||||
tex->anisotropy = c.textureSampler.anisotropy;
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
|
||||
@@ -195,6 +195,11 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
key.aniso = false;
|
||||
key.texture3d = gstate_c.curTextureIs3D;
|
||||
|
||||
// Anisotropic filtering must stay off for CLUT8-indexed textures - what gets sampled there are
|
||||
// palette indices that the shader depalettizes afterwards, and averaging indices gives garbage.
|
||||
const bool canUseAniso = gstate_c.Use(GPU_USE_ANISOTROPY) && !flatZ &&
|
||||
!(entry && (entry->status & TexStatus::CLUT8_INDEXED));
|
||||
|
||||
GETexLevelMode mipMode = gstate.getTexLevelMode();
|
||||
bool autoMip = mipMode == GE_TEXLEVEL_MODE_AUTO;
|
||||
|
||||
@@ -224,7 +229,7 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
key.maxLevel = maxLevel * 256;
|
||||
key.minLevel = 0;
|
||||
key.lodBias = (int)(lodBias * 256.0f);
|
||||
if (gstate_c.Use(GPU_USE_ANISOTROPY) && !flatZ) {
|
||||
if (canUseAniso) {
|
||||
key.aniso = true;
|
||||
}
|
||||
break;
|
||||
@@ -260,7 +265,7 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
key.mipEnable = true;
|
||||
key.mipFilt = 1;
|
||||
key.maxLevel = 9 * 256;
|
||||
if (gstate_c.Use(GPU_USE_ANISOTROPY) && !flatZ) {
|
||||
if (canUseAniso) {
|
||||
key.aniso = true;
|
||||
}
|
||||
}
|
||||
@@ -293,19 +298,17 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
case TEX_FILTER_AUTO_MAX_QUALITY:
|
||||
default:
|
||||
forceFiltering = TEX_FILTER_AUTO_MAX_QUALITY;
|
||||
if (gstate_c.Use(GPU_USE_ANISOTROPY) && !flatZ) {
|
||||
if (canUseAniso) {
|
||||
key.aniso = true;
|
||||
}
|
||||
if (gstate.isModeThrough() && g_Config.iInternalResolution != 1) {
|
||||
bool uglyColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && gstate.getColorTestRef() != 0;
|
||||
if (uglyColorTest) {
|
||||
forceFiltering = TEX_FILTER_FORCE_NEAREST;
|
||||
key.aniso = false;
|
||||
}
|
||||
}
|
||||
if (pixelMapped) {
|
||||
forceFiltering = TEX_FILTER_FORCE_NEAREST;
|
||||
key.aniso = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -322,6 +325,10 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
case TEX_FILTER_FORCE_NEAREST:
|
||||
key.magFilt = 0;
|
||||
key.minFilt = 0;
|
||||
// Anisotropic filtering is meaningless without minification filtering, and every path that
|
||||
// forces nearest does so to keep the texels exact - so clear it here rather than at each
|
||||
// of the places that can set forceFiltering to nearest.
|
||||
key.aniso = false;
|
||||
break;
|
||||
case TEX_FILTER_AUTO_MAX_QUALITY:
|
||||
// NOTE: We do not override magfilt here. If a game should have pixellated filtering,
|
||||
|
||||
@@ -266,7 +266,10 @@ void DrawEngineGLES::Flush() {
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(useHWTransform, dec_->VertexType(), clipInfoFlags_, &vsid);
|
||||
if (!vshader) {
|
||||
// Both the requested shader and the software transform fallback failed to compile.
|
||||
// Not much we can do here, let's skip drawing.
|
||||
// Not much we can do here, let's skip drawing. Note that the failure is cached, so this
|
||||
// will keep happening for this shader ID - hence the log, or geometry would just silently
|
||||
// disappear for the rest of the session.
|
||||
WARN_LOG_N_TIMES(novshader, 5, Log::G3D, "Skipping draw, no vertex shader");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "Common/GPU/OpenGL/GLRenderManager.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/GPUDefinitions.h"
|
||||
@@ -99,7 +101,8 @@ void TextureCacheGLES::ApplySamplerByKey(const SamplerCacheKey &key) {
|
||||
render_->SetTextureLod(0, minLod, maxLod, lodBias);
|
||||
}
|
||||
|
||||
float aniso = 0.0f;
|
||||
// 1.0 means no anisotropic filtering. The queue runner clamps to the device maximum.
|
||||
float aniso = key.aniso ? (float)(1 << g_Config.iAnisotropyLevel) : 1.0f;
|
||||
int minKey = ((int)key.mipEnable << 2) | ((int)key.mipFilt << 1) | ((int)key.minFilt);
|
||||
render_->SetTextureSampler(0,
|
||||
key.sClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT, key.tClamp ? GL_CLAMP_TO_EDGE : GL_REPEAT,
|
||||
|
||||
Reference in new issue
Block a user