D3D11: Add support to compile and link compute shaders

This is a reland of 2cd9d7e032fb412b539a907c58342060340387a1.

BUG=angleproject:1442
TEST=angle_end2end_tests

Change-Id: I5be0032b97617c31cdd4c66a823e8eb3b518867a
Reviewed-on: https://chromium-review.googlesource.com/430199
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 03f043d..25d46f8 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());