Remove invariant declaration in vertex shader for translation from ESSL 3.00 to GLSL <= 4.1

This is a follow-up patch of
https://chromium-review.googlesource.com/408569. This CL removes
invariant declaration in ESSL 3.00 vertex shader, such like:
"
out vec4 foo;
invariant foo;
"

This CL also adds the workarounds in libANGLE.

BUG=chromium:639760
TEST=webgl2_conformance

Change-Id: I568ab51a9a2f5da10d1aff0b63aae8805097e081
Reviewed-on: https://chromium-review.googlesource.com/409157
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
index 08806bc..53b021a 100644
--- a/src/compiler/translator/Compiler.cpp
+++ b/src/compiler/translator/Compiler.cpp
@@ -103,6 +103,22 @@
             output == SH_GLSL_400_CORE_OUTPUT || output == SH_GLSL_410_CORE_OUTPUT);
 }
 
+bool RemoveInvariant(sh::GLenum shaderType,
+                     int shaderVersion,
+                     ShShaderOutput outputType,
+                     ShCompileOptions compileOptions)
+{
+    if ((compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) == 0 &&
+        shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
+        return true;
+
+    if ((compileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0 &&
+        shaderVersion >= 300 && shaderType == GL_VERTEX_SHADER && IsGLSL410OrOlder(outputType))
+        return true;
+
+    return false;
+}
+
 size_t GetGlobalMaxTokenSize(ShShaderSpec spec)
 {
     // WebGL defines a max token legnth of 256, while ES2 leaves max token
@@ -394,8 +410,7 @@
              (outputType == SH_GLSL_COMPATIBILITY_OUTPUT)))
             initializeGLPosition(root);
 
-        if (success && !(compileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT) &&
-            shaderType == GL_FRAGMENT_SHADER && IsGLSL420OrNewer(outputType))
+        if (success && RemoveInvariant(shaderType, shaderVersion, outputType, compileOptions))
             sh::RemoveInvariantDeclaration(root);
 
         // This pass might emit short circuits so keep it before the short circuit unfolding
diff --git a/src/compiler/translator/Compiler.h b/src/compiler/translator/Compiler.h
index 42983a4..42b4f8f 100644
--- a/src/compiler/translator/Compiler.h
+++ b/src/compiler/translator/Compiler.h
@@ -45,6 +45,14 @@
 bool IsGLSL410OrOlder(ShShaderOutput output);
 
 //
+// Helper function to check if the invariant qualifier can be removed.
+//
+bool RemoveInvariant(sh::GLenum shaderType,
+                     int shaderVersion,
+                     ShShaderOutput outputType,
+                     ShCompileOptions compileOptions);
+
+//
 // The base class used to back handles returned to the driver.
 //
 class TShHandleBase {
diff --git a/src/compiler/translator/OutputESSL.cpp b/src/compiler/translator/OutputESSL.cpp
index 2223b03..e55d6c5 100644
--- a/src/compiler/translator/OutputESSL.cpp
+++ b/src/compiler/translator/OutputESSL.cpp
@@ -14,6 +14,7 @@
                          ShHashFunction64 hashFunction,
                          NameMap &nameMap,
                          TSymbolTable &symbolTable,
+                         sh::GLenum shaderType,
                          int shaderVersion,
                          bool forceHighp,
                          ShCompileOptions compileOptions)
@@ -22,6 +23,7 @@
                       hashFunction,
                       nameMap,
                       symbolTable,
+                      shaderType,
                       shaderVersion,
                       SH_ESSL_OUTPUT,
                       compileOptions),
diff --git a/src/compiler/translator/OutputESSL.h b/src/compiler/translator/OutputESSL.h
index 0ef37ae..5b2cb94 100644
--- a/src/compiler/translator/OutputESSL.h
+++ b/src/compiler/translator/OutputESSL.h
@@ -14,20 +14,21 @@
 
 class TOutputESSL : public TOutputGLSLBase
 {
-public:
-    TOutputESSL(TInfoSinkBase& objSink,
+  public:
+    TOutputESSL(TInfoSinkBase &objSink,
                 ShArrayIndexClampingStrategy clampingStrategy,
                 ShHashFunction64 hashFunction,
-                NameMap& nameMap,
-                TSymbolTable& symbolTable,
+                NameMap &nameMap,
+                TSymbolTable &symbolTable,
+                sh::GLenum shaderType,
                 int shaderVersion,
                 bool forceHighp,
                 ShCompileOptions compileOptions);
 
-protected:
-  bool writeVariablePrecision(TPrecision precision) override;
+  protected:
+    bool writeVariablePrecision(TPrecision precision) override;
 
-private:
+  private:
     bool mForceHighp;
 };
 
diff --git a/src/compiler/translator/OutputGLSL.cpp b/src/compiler/translator/OutputGLSL.cpp
index 6b2d59f..fc2b184 100644
--- a/src/compiler/translator/OutputGLSL.cpp
+++ b/src/compiler/translator/OutputGLSL.cpp
@@ -9,11 +9,12 @@
 namespace sh
 {
 
-TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
+TOutputGLSL::TOutputGLSL(TInfoSinkBase &objSink,
                          ShArrayIndexClampingStrategy clampingStrategy,
                          ShHashFunction64 hashFunction,
-                         NameMap& nameMap,
-                         TSymbolTable& symbolTable,
+                         NameMap &nameMap,
+                         TSymbolTable &symbolTable,
+                         sh::GLenum shaderType,
                          int shaderVersion,
                          ShShaderOutput output,
                          ShCompileOptions compileOptions)
@@ -22,6 +23,7 @@
                       hashFunction,
                       nameMap,
                       symbolTable,
+                      shaderType,
                       shaderVersion,
                       output,
                       compileOptions)
diff --git a/src/compiler/translator/OutputGLSL.h b/src/compiler/translator/OutputGLSL.h
index a825a93..d910c00 100644
--- a/src/compiler/translator/OutputGLSL.h
+++ b/src/compiler/translator/OutputGLSL.h
@@ -15,11 +15,12 @@
 class TOutputGLSL : public TOutputGLSLBase
 {
   public:
-    TOutputGLSL(TInfoSinkBase& objSink,
+    TOutputGLSL(TInfoSinkBase &objSink,
                 ShArrayIndexClampingStrategy clampingStrategy,
                 ShHashFunction64 hashFunction,
-                NameMap& nameMap,
-                TSymbolTable& symbolTable,
+                NameMap &nameMap,
+                TSymbolTable &symbolTable,
+                sh::GLenum shaderType,
                 int shaderVersion,
                 ShShaderOutput output,
                 ShCompileOptions compileOptions);
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 14cb16b..964f1e2 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -85,6 +85,7 @@
                                  ShHashFunction64 hashFunction,
                                  NameMap &nameMap,
                                  TSymbolTable &symbolTable,
+                                 sh::GLenum shaderType,
                                  int shaderVersion,
                                  ShShaderOutput output,
                                  ShCompileOptions compileOptions)
@@ -95,6 +96,7 @@
       mHashFunction(hashFunction),
       mNameMap(nameMap),
       mSymbolTable(symbolTable),
+      mShaderType(shaderType),
       mShaderVersion(shaderVersion),
       mOutput(output),
       mCompileOptions(compileOptions)
@@ -103,11 +105,7 @@
 
 void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
 {
-    bool removeInvariant = ((type.getQualifier() == EvqVaryingIn && sh::IsGLSL420OrNewer(mOutput) &&
-                             !(mCompileOptions & SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT)) ||
-                            (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
-                             !!(mCompileOptions & SH_REMOVE_INVARIANT_FOR_ESSL3)));
-    if (!removeInvariant)
+    if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
     {
         TInfoSinkBase &out = objSink();
         out << "invariant ";
@@ -165,7 +163,7 @@
 const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
 {
     if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
-        !!(mCompileOptions & SH_REMOVE_CENTROID_FOR_ESSL3))
+        (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
     {
         switch (qualifier)
         {
@@ -960,8 +958,7 @@
             ASSERT(sequence && sequence->size() == 1);
             const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode();
             ASSERT(symbol);
-            writeInvariantQualifier(symbol->getType());
-            out << hashVariableName(symbol->getName());
+            out << "invariant " << hashVariableName(symbol->getName());
         }
         visitChildren = false;
         break;
diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h
index a1d2f83..ede4c49 100644
--- a/src/compiler/translator/OutputGLSLBase.h
+++ b/src/compiler/translator/OutputGLSLBase.h
@@ -23,7 +23,8 @@
                     ShArrayIndexClampingStrategy clampingStrategy,
                     ShHashFunction64 hashFunction,
                     NameMap &nameMap,
-                    TSymbolTable& symbolTable,
+                    TSymbolTable &symbolTable,
+                    sh::GLenum shaderType,
                     int shaderVersion,
                     ShShaderOutput output,
                     ShCompileOptions compileOptions);
@@ -102,6 +103,8 @@
 
     TSymbolTable &mSymbolTable;
 
+    sh::GLenum mShaderType;
+
     const int mShaderVersion;
 
     ShShaderOutput mOutput;
diff --git a/src/compiler/translator/RemoveInvariantDeclaration.cpp b/src/compiler/translator/RemoveInvariantDeclaration.cpp
index ea24766..f6f0163 100644
--- a/src/compiler/translator/RemoveInvariantDeclaration.cpp
+++ b/src/compiler/translator/RemoveInvariantDeclaration.cpp
@@ -15,7 +15,7 @@
 {
 
 // An AST traverser that removes invariant declaration for input in fragment shader
-// when GLSL >= 4.20.
+// when GLSL >= 4.20 and for output in vertex shader when GLSL < 4.2.
 class RemoveInvariantDeclarationTraverser : public TIntermTraverser
 {
   public:
@@ -26,17 +26,10 @@
     {
         if (node->getOp() == EOpInvariantDeclaration)
         {
-            for (TIntermNode *&child : *node->getSequence())
-            {
-                TIntermTyped *typed = child->getAsTyped();
-                if (typed && typed->getQualifier() == EvqVaryingIn)
-                {
-                    TIntermSequence emptyReplacement;
-                    mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(
-                        getParentNode()->getAsBlock(), node, emptyReplacement));
-                    return false;
-                }
-            }
+            TIntermSequence emptyReplacement;
+            mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(),
+                                                                      node, emptyReplacement));
+            return false;
         }
         return true;
     }
diff --git a/src/compiler/translator/TranslatorESSL.cpp b/src/compiler/translator/TranslatorESSL.cpp
index 55c1b67..43bce74 100644
--- a/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/compiler/translator/TranslatorESSL.cpp
@@ -81,7 +81,8 @@
 
     // Write translated shader.
     TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
-                           getSymbolTable(), shaderVer, precisionEmulation, compileOptions);
+                           getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
+                           compileOptions);
     root->traverse(&outputESSL);
 }
 
diff --git a/src/compiler/translator/TranslatorGLSL.cpp b/src/compiler/translator/TranslatorGLSL.cpp
index 4bbff97..1d6582b 100644
--- a/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/compiler/translator/TranslatorGLSL.cpp
@@ -188,13 +188,8 @@
     }
 
     // Write translated shader.
-    TOutputGLSL outputGLSL(sink,
-                           getArrayIndexClampingStrategy(),
-                           getHashFunction(),
-                           getNameMap(),
-                           getSymbolTable(),
-                           getShaderVersion(),
-                           getOutputType(),
+    TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
+                           getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
                            compileOptions);
     root->traverse(&outputGLSL);
 }