ASTMetadataHLSL: handle WebGL2 gradient builtins

BUG=angleproject:1915

Change-Id: Id54e6dd417a1a288c71355e74184366d1492e92b
Reviewed-on: https://chromium-review.googlesource.com/446521
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/ASTMetadataHLSL.cpp b/src/compiler/translator/ASTMetadataHLSL.cpp
index d37b3dc..e0de596 100644
--- a/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -32,6 +32,19 @@
           mDag(dag)
     {
         ASSERT(index < metadataList->size());
+
+        // ESSL 100 builtin gradient functions
+        mGradientBuiltinFunctions.insert("texture2D");
+        mGradientBuiltinFunctions.insert("texture2DProj");
+        mGradientBuiltinFunctions.insert("textureCube");
+
+        // ESSL 300 builtin gradient functions
+        mGradientBuiltinFunctions.insert("texture");
+        mGradientBuiltinFunctions.insert("textureProj");
+        mGradientBuiltinFunctions.insert("textureOffset");
+        mGradientBuiltinFunctions.insert("textureProjOffset");
+
+        // ESSL 310 doesn't add builtin gradient functions
     }
 
     void traverse(TIntermFunctionDefinition *node)
@@ -89,6 +102,7 @@
             {
                 case EOpDFdx:
                 case EOpDFdy:
+                case EOpFwidth:
                     onGradient();
                 default:
                     break;
@@ -116,7 +130,7 @@
             {
                 TString name = TFunction::unmangleName(node->getFunctionSymbolInfo()->getName());
 
-                if (name == "texture2D" || name == "texture2DProj" || name == "textureCube")
+                if (mGradientBuiltinFunctions.find(name) != mGradientBuiltinFunctions.end())
                 {
                     onGradient();
                 }
@@ -135,6 +149,9 @@
     // Contains a stack of the control flow nodes that are parents of the node being
     // currently visited. It is used to mark control flows using a gradient.
     std::vector<TIntermNode *> mParents;
+
+    // A list of builtin functions that use gradients
+    std::set<TString> mGradientBuiltinFunctions;
 };
 
 // Traverses the AST of a function definition to compute the the discontinuous loops