Add sampler2DMSArray support to HLSL output

This is done with small adjustments to TextureFunctionHLSL. Most of
the functionality was already in place before.

This changes the categorization of sampler types in BasicTypes.h
helper functions: 2D array samplers are no longer treated as 2D
samplers, but the two categories are now entirely disjoint. This
makes TextureFunctionHLSL a little bit simpler.

BUG=angleproject:2775
TEST=angle_unittests, angle_end2end_tests

Change-Id: I84d9b56c37b1aaa01ee5921b6f17f8a78698fce2
Reviewed-on: https://chromium-review.googlesource.com/1188562
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/TextureFunctionHLSL.cpp b/src/compiler/translator/TextureFunctionHLSL.cpp
index 333d246..1666004 100644
--- a/src/compiler/translator/TextureFunctionHLSL.cpp
+++ b/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -169,14 +169,23 @@
         switch (hlslCoords)
         {
             case 2:
-                if (textureFunction.sampler == EbtSampler2DMS ||
-                    textureFunction.sampler == EbtISampler2DMS ||
-                    textureFunction.sampler == EbtUSampler2DMS)
+                if (IsSampler2DMS(textureFunction.sampler))
+                {
                     return "int2";
+                }
                 else
+                {
                     return "int3";
+                }
             case 3:
-                return "int4";
+                if (IsSampler2DMSArray(textureFunction.sampler))
+                {
+                    return "int3";
+                }
+                else
+                {
+                    return "int4";
+                }
             default:
                 UNREACHABLE();
         }
@@ -234,49 +243,13 @@
     }
     else
     {
-        switch (textureFunction.sampler)
+        if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
+            IsSamplerCube(textureFunction.sampler))
         {
-            case EbtSampler2D:
-                return 2;
-            case EbtSampler2DMS:
-                return 2;
-            case EbtSampler3D:
-                return 3;
-            case EbtSamplerCube:
-                return 3;
-            case EbtSampler2DArray:
-                return 3;
-            case EbtSamplerExternalOES:
-                return 2;
-            case EbtISampler2D:
-                return 2;
-            case EbtISampler2DMS:
-                return 2;
-            case EbtISampler3D:
-                return 3;
-            case EbtISamplerCube:
-                return 3;
-            case EbtISampler2DArray:
-                return 3;
-            case EbtUSampler2D:
-                return 2;
-            case EbtUSampler2DMS:
-                return 2;
-            case EbtUSampler3D:
-                return 3;
-            case EbtUSamplerCube:
-                return 3;
-            case EbtUSampler2DArray:
-                return 3;
-            case EbtSampler2DShadow:
-                return 2;
-            case EbtSamplerCubeShadow:
-                return 3;
-            case EbtSampler2DArrayShadow:
-                return 3;
-            default:
-                UNREACHABLE();
+            return 3;
         }
+        ASSERT(IsSampler2D(textureFunction.sampler));
+        return 2;
     }
     return 0;
 }
@@ -400,9 +373,8 @@
         case TextureFunctionHLSL::TextureFunction::SIZE:
             break;
         case TextureFunctionHLSL::TextureFunction::FETCH:
-            if (textureFunction.sampler == EbtSampler2DMS ||
-                textureFunction.sampler == EbtISampler2DMS ||
-                textureFunction.sampler == EbtUSampler2DMS)
+            if (IsSampler2DMS(textureFunction.sampler) ||
+                IsSampler2DMSArray(textureFunction.sampler))
                 out << ", int index";
             else
                 out << ", int mip";
@@ -430,13 +402,11 @@
             case EbtUSampler2DArray:
             case EbtSampler2DShadow:
             case EbtSampler2DArrayShadow:
-            case EbtSampler2DMS:
-            case EbtISampler2DMS:
-            case EbtUSampler2DMS:
             case EbtSamplerExternalOES:
                 out << ", int2 offset";
                 break;
             default:
+                // Offset is not supported for multisampled textures.
                 UNREACHABLE();
         }
     }
@@ -508,6 +478,11 @@
         out << "    uint width; uint height; uint samples;\n"
             << "    " << textureReference << ".GetDimensions(width, height, samples);\n";
     }
+    else if (IsSampler2DMSArray(textureFunction.sampler))
+    {
+        out << "    uint width; uint height; uint depth; uint samples;\n"
+            << "    " << textureReference << ".GetDimensions(width, height, depth, samples);\n";
+    }
     else
     {
         if (getDimensionsIgnoresBaseLevel)
@@ -697,98 +672,93 @@
     }
     else if (textureFunction.method != TextureFunctionHLSL::TextureFunction::FETCH)
     {
-        if (IsSampler2D(textureFunction.sampler))
+        if (IsSamplerArray(textureFunction.sampler))
         {
-            if (IsSamplerArray(textureFunction.sampler))
+            out << "    float width; float height; float layers; float levels;\n";
+
+            if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
             {
-                out << "    float width; float height; float layers; float levels;\n";
-
-                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
-                {
-                    out << "    uint mip = 0;\n";
-                }
-                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
-                {
-                    out << "    uint mip = bias;\n";
-                }
-                else
-                {
-
-                    out << "    " << textureReference
-                        << ".GetDimensions(0, width, height, layers, levels);\n";
-                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
-                        textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
-                    {
-                        out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
-                               "    float dx = length(ddx(tSized));\n"
-                               "    float dy = length(ddy(tSized));\n"
-                               "    float lod = log2(max(dx, dy));\n";
-
-                        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
-                        {
-                            out << "    lod += bias;\n";
-                        }
-                    }
-                    else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
-                    {
-                        out << "    float2 sizeVec = float2(width, height);\n"
-                               "    float2 sizeDdx = ddx * sizeVec;\n"
-                               "    float2 sizeDdy = ddy * sizeVec;\n"
-                               "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
-                               "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
-                    }
-
-                    out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
-                }
-
-                out << "    " << textureReference
-                    << ".GetDimensions(mip, width, height, layers, levels);\n";
+                out << "    uint mip = 0;\n";
+            }
+            else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+            {
+                out << "    uint mip = bias;\n";
             }
             else
             {
-                out << "    float width; float height; float levels;\n";
-
-                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
-                {
-                    out << "    uint mip = 0;\n";
-                }
-                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
-                {
-                    out << "    uint mip = bias;\n";
-                }
-                else
-                {
-                    out << "    " << textureReference
-                        << ".GetDimensions(0, width, height, levels);\n";
-
-                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
-                        textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
-                    {
-                        out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
-                               "    float dx = length(ddx(tSized));\n"
-                               "    float dy = length(ddy(tSized));\n"
-                               "    float lod = log2(max(dx, dy));\n";
-
-                        if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
-                        {
-                            out << "    lod += bias;\n";
-                        }
-                    }
-                    else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
-                    {
-                        out << "    float2 sizeVec = float2(width, height);\n"
-                               "    float2 sizeDdx = ddx * sizeVec;\n"
-                               "    float2 sizeDdy = ddy * sizeVec;\n"
-                               "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
-                               "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
-                    }
-
-                    out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
-                }
 
                 out << "    " << textureReference
-                    << ".GetDimensions(mip, width, height, levels);\n";
+                    << ".GetDimensions(0, width, height, layers, levels);\n";
+                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+                    textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                {
+                    out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                           "    float dx = length(ddx(tSized));\n"
+                           "    float dy = length(ddy(tSized));\n"
+                           "    float lod = log2(max(dx, dy));\n";
+
+                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                    {
+                        out << "    lod += bias;\n";
+                    }
+                }
+                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+                {
+                    out << "    float2 sizeVec = float2(width, height);\n"
+                           "    float2 sizeDdx = ddx * sizeVec;\n"
+                           "    float2 sizeDdy = ddy * sizeVec;\n"
+                           "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
+                           "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+                }
+
+                out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
             }
+
+            out << "    " << textureReference
+                << ".GetDimensions(mip, width, height, layers, levels);\n";
+        }
+        else if (IsSampler2D(textureFunction.sampler))
+        {
+            out << "    float width; float height; float levels;\n";
+
+            if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0)
+            {
+                out << "    uint mip = 0;\n";
+            }
+            else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::LOD0BIAS)
+            {
+                out << "    uint mip = bias;\n";
+            }
+            else
+            {
+                out << "    " << textureReference << ".GetDimensions(0, width, height, levels);\n";
+
+                if (textureFunction.method == TextureFunctionHLSL::TextureFunction::IMPLICIT ||
+                    textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                {
+                    out << "    float2 tSized = float2(t.x * width, t.y * height);\n"
+                           "    float dx = length(ddx(tSized));\n"
+                           "    float dy = length(ddy(tSized));\n"
+                           "    float lod = log2(max(dx, dy));\n";
+
+                    if (textureFunction.method == TextureFunctionHLSL::TextureFunction::BIAS)
+                    {
+                        out << "    lod += bias;\n";
+                    }
+                }
+                else if (textureFunction.method == TextureFunctionHLSL::TextureFunction::GRAD)
+                {
+                    out << "    float2 sizeVec = float2(width, height);\n"
+                           "    float2 sizeDdx = ddx * sizeVec;\n"
+                           "    float2 sizeDdy = ddy * sizeVec;\n"
+                           "    float lod = log2(max(dot(sizeDdx, sizeDdx), "
+                           "dot(sizeDdy, sizeDdy))) * 0.5f;\n";
+                }
+
+                out << "    uint mip = uint(min(max(round(lod), 0), levels - 1));\n";
+            }
+
+            out << "    " << textureReference << ".GetDimensions(mip, width, height, levels);\n";
         }
         else if (IsSampler3D(textureFunction.sampler))
         {
@@ -991,9 +961,8 @@
         else if (IsIntegerSampler(textureFunction.sampler) ||
                  textureFunction.method == TextureFunctionHLSL::TextureFunction::FETCH)
         {
-            if (textureFunction.sampler == EbtSampler2DMS ||
-                textureFunction.sampler == EbtISampler2DMS ||
-                textureFunction.sampler == EbtUSampler2DMS)
+            if (IsSampler2DMS(textureFunction.sampler) ||
+                IsSampler2DMSArray(textureFunction.sampler))
                 out << "), index";
             else
                 out << ", mip)";
@@ -1141,6 +1110,9 @@
             case EbtSampler2DArray:
             case EbtISampler2DArray:
             case EbtUSampler2DArray:
+            case EbtSampler2DMSArray:
+            case EbtISampler2DMSArray:
+            case EbtUSampler2DMSArray:
             case EbtSampler2DArrayShadow:
                 return "int3";
             default:
@@ -1153,6 +1125,7 @@
         {
             case EbtSampler2D:
             case EbtSampler2DMS:
+            case EbtSampler2DMSArray:
             case EbtSampler3D:
             case EbtSamplerCube:
             case EbtSampler2DArray:
@@ -1160,12 +1133,14 @@
                 return "float4";
             case EbtISampler2D:
             case EbtISampler2DMS:
+            case EbtISampler2DMSArray:
             case EbtISampler3D:
             case EbtISamplerCube:
             case EbtISampler2DArray:
                 return "int4";
             case EbtUSampler2D:
             case EbtUSampler2DMS:
+            case EbtUSampler2DMSArray:
             case EbtUSampler3D:
             case EbtUSamplerCube:
             case EbtUSampler2DArray: