From 2b7d2fdc4b385fd8edec7ea55d5975d960daa3d3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 29 Mar 2014 10:01:15 -0700 Subject: [PATCH] Optimize > and != 0 alpha tests. There's no need to do rounding in this case. These are very common. Also, if the test was !=, convert it to >, which may work better on PowerVR. --- GPU/GLES/FragmentShaderGenerator.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 91316b986b..7225dfefa4 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -284,6 +284,7 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled(); bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough(); bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !g_Config.bDisableAlphaTest; + bool alphaTestAgainstZero = gstate.getAlphaTestRef() == 0; bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue(); bool alphaToColorDoubling = AlphaToColorDoubling(); bool enableColorDoubling = (gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled()) || alphaToColorDoubling; @@ -321,6 +322,7 @@ void ComputeFragmentShaderID(FragmentShaderID *id) { // 3 bits id->d[0] |= ReplaceAlphaWithStencilType() << 21; } + id->d[0] |= (alphaTestAgainstZero & 1) << 24; if (enableAlphaTest) gpuStats.numAlphaTestedDraws++; else @@ -391,6 +393,7 @@ void GenerateFragmentShader(char *buffer) { bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear(); bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear(); bool enableAlphaTest = gstate.isAlphaTestEnabled() && !IsAlphaTestTriviallyTrue() && !gstate.isModeClear() && !g_Config.bDisableAlphaTest; + bool alphaTestAgainstZero = gstate.getAlphaTestRef() == 0; bool enableColorTest = gstate.isColorTestEnabled() && !IsColorTestTriviallyTrue() && !gstate.isModeClear(); bool alphaToColorDoubling = AlphaToColorDoubling(); bool enableColorDoubling = (gstate.isColorDoublingEnabled() && gstate.isTextureMapEnabled()) || alphaToColorDoubling; @@ -429,7 +432,7 @@ void GenerateFragmentShader(char *buffer) { WRITE(p, "%s mediump vec2 v_texcoord;\n", varying); } - if (enableAlphaTest) { + if (enableAlphaTest && !alphaTestAgainstZero) { if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n"); else @@ -535,9 +538,18 @@ void GenerateFragmentShader(char *buffer) { GEComparison alphaTestFunc = gstate.getAlphaTestFunction(); const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " }; // never/always don't make sense if (alphaTestFuncs[alphaTestFunc][0] != '#') { - if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { + if (alphaTestAgainstZero) { + // When testing against 0 (extremely common), we can avoid some math. + // 0.002 is approximately half of 1.0 / 255.0. + if (alphaTestFunc == GE_COMP_NOTEQUAL || alphaTestFunc == GE_COMP_GREATER) { + WRITE(p, " if (v.a < 0.002) discard;\n"); + } else { + // Anything else is a test for == 0. Happens sometimes, actually... + WRITE(p, " if (v.a > 0.002) discard;\n"); + } + } else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) { // Work around bad PVR driver problem where equality check + discard just doesn't work. - if (alphaTestFunc != 3) + if (alphaTestFunc != GE_COMP_NOTEQUAL) WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]); } else { WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);