Reland "Remove invariant qualifier for input in fragment shader"
This relands https://chromium-review.googlesource.com/#/c/400005/.
ESSL and GLSL are not consistent on invariant matching in vertex shader
and fragment shader. See the following rules:
ESSL 1.00 - input and output must match
ESSL 3.00 - only output, inputs cannot be declared as invariant.
GLSL 1.10.59 - does not exist
GLSL 1.20.8 - input and output must match
GLSL 1.30.10 - input and output must match
GLSL 1.40.8 - input and output must match
GLSL 1.50.11 - input and output must match
GLSL 3.30.6 - input and output must match
GLSL 4.00.9 - input and output must match
GLSL 4.10.6 - input and output must match
GLSL 4.20.11 - input can omit invariant
GLSL 4.30.8 - input can omit invariant
GLSL 4.40.9 - input can omit invariant
GLSL 4.50.5 - input can omit invariant
Since GLSL 4.20, invariant qualifier description were changed to:
"
Only variables output from a shader (including those that are then input
to a subsequent shader) can be candidates for invariance. This includes
user-defined output variables and the built-in output variables. As only
outputs need be declared with invariant, an output from one shader stage
will still match an input of a subsequent stage without the input being
declared as invariant.
"
It's not very clear if input in fragment can be declared as invariant.
Mesa driver disallows use of input declared as invariant in fragment
shader, while other drivers may allow it. This CL removes invariant
declaration for input in fragment shader except AMD driver in Linux.
AMD's driver obviously contradicts the spec by forcing invariance to
match between vertex and fragment shaders.
BUG=chromium:639760, chromium:659326
TEST=conformance/glsl/misc/shaders-with-invariance.html and
conformance/glsl/bugs/invariant-does-not-leak-across-shaders.html
Change-Id: I0aa9be14f0cee7a11a249c91fba27c570c52ca1b
Reviewed-on: https://chromium-review.googlesource.com/404228
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 8e1fc19..c3812f9 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -23,6 +23,7 @@
#include "compiler/translator/ParseContext.h"
#include "compiler/translator/PruneEmptyDeclarations.h"
#include "compiler/translator/RegenerateStructNames.h"
+#include "compiler/translator/RemoveInvariantDeclaration.h"
#include "compiler/translator/RemovePow.h"
#include "compiler/translator/RewriteDoWhile.h"
#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
@@ -91,6 +92,14 @@
output == SH_GLSL_450_CORE_OUTPUT);
}
+bool IsGLSL420OrNewer(ShShaderOutput output)
+{
+ return (output == SH_GLSL_420_CORE_OUTPUT ||
+ output == SH_GLSL_430_CORE_OUTPUT ||
+ output == SH_GLSL_440_CORE_OUTPUT ||
+ output == SH_GLSL_450_CORE_OUTPUT);
+}
+
size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
{
// WebGL defines a max token legnth of 256, while ES2 leaves max token
@@ -382,6 +391,10 @@
(outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
initializeGLPosition(root);
+ if (success && !(compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) &&
+ shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
+ sh::RemoveInvariantDeclaration(root);
+
// This pass might emit short circuits so keep it before the short circuit unfolding
if (success && (compileOptions & SH_REWRITE_DO_WHILE_LOOPS))
RewriteDoWhile(root, getTemporaryIndex());