D3D11: Add support to compile and link compute shaders.

BUG=angleproject:1442

Change-Id: I13240e931e6f121d175d2cd6b41324d38bb39a5c
Reviewed-on: https://chromium-review.googlesource.com/405831
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index eda90a0..ebc5de6 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -115,6 +115,11 @@
     mUsesInstanceID              = false;
     mUsesVertexID                = false;
     mUsesFragDepth               = false;
+    mUsesNumWorkGroups           = false;
+    mUsesWorkGroupID             = false;
+    mUsesLocalInvocationID       = false;
+    mUsesGlobalInvocationID      = false;
+    mUsesLocalInvocationIndex    = false;
     mUsesXor                     = false;
     mUsesDiscardRewriting        = false;
     mUsesNestedBreak             = false;
@@ -540,7 +545,7 @@
             out << "#define GL_USES_FRAG_DATA\n";
         }
     }
-    else  // Vertex shader
+    else if (mShaderType == GL_VERTEX_SHADER)
     {
         out << "// Attributes\n";
         out << attributes;
@@ -631,6 +636,40 @@
             out << "\n";
         }
     }
+    else  // Compute shader
+    {
+        ASSERT(mShaderType == GL_COMPUTE_SHADER);
+        if (mUsesNumWorkGroups)
+        {
+            out << "cbuffer DriverConstants : register(b1)\n"
+                   "{\n";
+            out << "    uint3 gl_NumWorkGroups : packoffset(c0);\n";
+            out << "};\n";
+        }
+
+        // Follow built-in variables would be initialized in
+        // DynamicHLSL::generateComputeShaderLinkHLSL, if they
+        // are used in compute shader.
+        if (mUsesWorkGroupID)
+        {
+            out << "static uint3 gl_WorkGroupID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesLocalInvocationID)
+        {
+            out << "static uint3 gl_LocalInvocationID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesGlobalInvocationID)
+        {
+            out << "static uint3 gl_GlobalInvocationID = uint3(0, 0, 0);\n";
+        }
+
+        if (mUsesLocalInvocationIndex)
+        {
+            out << "static uint gl_LocalInvocationIndex = uint(0);\n";
+        }
+    }
 
     bool getDimensionsIgnoresBaseLevel =
         (mCompileOptions & SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL) != 0;
@@ -666,6 +705,31 @@
         out << "#define GL_USES_DEPTH_RANGE\n";
     }
 
+    if (mUsesNumWorkGroups)
+    {
+        out << "#define GL_USES_NUM_WORK_GROUPS\n";
+    }
+
+    if (mUsesWorkGroupID)
+    {
+        out << "#define GL_USES_WORK_GROUP_ID\n";
+    }
+
+    if (mUsesLocalInvocationID)
+    {
+        out << "#define GL_USES_LOCAL_INVOCATION_ID\n";
+    }
+
+    if (mUsesGlobalInvocationID)
+    {
+        out << "#define GL_USES_GLOBAL_INVOCATION_ID\n";
+    }
+
+    if (mUsesLocalInvocationIndex)
+    {
+        out << "#define GL_USES_LOCAL_INVOCATION_INDEX\n";
+    }
+
     if (mUsesXor)
     {
         out << "bool xor(bool p, bool q)\n"
@@ -779,6 +843,31 @@
             mUsesFragDepth = true;
             out << "gl_Depth";
         }
+        else if (qualifier == EvqNumWorkGroups)
+        {
+            mUsesNumWorkGroups = true;
+            out << name;
+        }
+        else if (qualifier == EvqWorkGroupID)
+        {
+            mUsesWorkGroupID = true;
+            out << name;
+        }
+        else if (qualifier == EvqLocalInvocationID)
+        {
+            mUsesLocalInvocationID = true;
+            out << name;
+        }
+        else if (qualifier == EvqGlobalInvocationID)
+        {
+            mUsesGlobalInvocationID = true;
+            out << name;
+        }
+        else if (qualifier == EvqLocalInvocationIndex)
+        {
+            mUsesLocalInvocationIndex = true;
+            out << name;
+        }
         else
         {
             out << DecorateIfNeeded(node->getName());