Fix multisample texture operations crashing HLSL generation

This includes a partial implementation of multisample texture
operations on the HLSL backend. It can't be fully tested yet, since
the API side isn't implemented.

BUG=angleproject:1442
TEST=dEQP-GLES31.functional.shaders.builtin_functions.texture_size.*
     (successfully compiles instead of crashing)

Change-Id: Ief782db28388a3f8fd8113cc86ce3c4f500f322a
Reviewed-on: https://chromium-review.googlesource.com/443264
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
diff --git a/src/compiler/translator/BaseTypes.h b/src/compiler/translator/BaseTypes.h
index abf392b..6914b8d 100644
--- a/src/compiler/translator/BaseTypes.h
+++ b/src/compiler/translator/BaseTypes.h
@@ -235,6 +235,19 @@
     return false;
 }
 
+inline bool IsSampler2DMS(TBasicType type)
+{
+    switch (type)
+    {
+        case EbtSampler2DMS:
+        case EbtISampler2DMS:
+        case EbtUSampler2DMS:
+            return true;
+        default:
+            return false;
+    }
+}
+
 inline bool IsFloatImage(TBasicType type)
 {
     switch (type)
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 60dcfd3..87a7767 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1790,7 +1790,11 @@
             {
                 TString name = TFunction::unmangleName(node->getFunctionSymbolInfo()->getName());
                 TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType();
-                int coords             = (*arguments)[1]->getAsTyped()->getNominalSize();
+                int coords = 0;  // textureSize(gsampler2DMS) doesn't have a second argument.
+                if (arguments->size() > 1)
+                {
+                    coords = (*arguments)[1]->getAsTyped()->getNominalSize();
+                }
                 TString textureFunctionName = mTextureFunctionHLSL->useTextureFunction(
                     name, samplerType, coords, arguments->size(), lod0, mShaderType);
                 out << textureFunctionName << "(";
diff --git a/src/compiler/translator/TextureFunctionHLSL.cpp b/src/compiler/translator/TextureFunctionHLSL.cpp
index 33d0985..1f3de5f 100644
--- a/src/compiler/translator/TextureFunctionHLSL.cpp
+++ b/src/compiler/translator/TextureFunctionHLSL.cpp
@@ -319,6 +319,8 @@
     {
         switch (textureFunction.coords)
         {
+            case 0:
+                break;  // textureSize(gSampler2DMS sampler)
             case 1:
                 out << ", int lod";
                 break;  // textureSize()
@@ -457,48 +459,56 @@
                                    const TString &textureReference,
                                    bool getDimensionsIgnoresBaseLevel)
 {
-    if (getDimensionsIgnoresBaseLevel)
+    if (IsSampler2DMS(textureFunction.sampler))
     {
-        out << "int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
+        out << "    uint width; uint height; uint samples;\n"
+            << "    " << textureReference << ".GetDimensions(width, height, samples);\n";
     }
     else
     {
-        out << "int baseLevel = 0;\n";
-    }
-
-    if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
-        (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
-    {
-        // "depth" stores either the number of layers in an array texture or 3D depth
-        out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
-            << "    " << textureReference
-            << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
-            << "    width = max(width >> lod, 1);\n"
-            << "    height = max(height >> lod, 1);\n";
-
-        if (!IsSamplerArray(textureFunction.sampler))
+        if (getDimensionsIgnoresBaseLevel)
         {
-            out << "    depth = max(depth >> lod, 1);\n";
+            out << "    int baseLevel = samplerMetadata[samplerIndex].baseLevel;\n";
         }
+        else
+        {
+            out << "    int baseLevel = 0;\n";
+        }
+
+        if (IsSampler3D(textureFunction.sampler) || IsSamplerArray(textureFunction.sampler) ||
+            (IsIntegerSampler(textureFunction.sampler) && IsSamplerCube(textureFunction.sampler)))
+        {
+            // "depth" stores either the number of layers in an array texture or 3D depth
+            out << "    uint width; uint height; uint depth; uint numberOfLevels;\n"
+                << "    " << textureReference
+                << ".GetDimensions(baseLevel, width, height, depth, numberOfLevels);\n"
+                << "    width = max(width >> lod, 1);\n"
+                << "    height = max(height >> lod, 1);\n";
+
+            if (!IsSamplerArray(textureFunction.sampler))
+            {
+                out << "    depth = max(depth >> lod, 1);\n";
+            }
+        }
+        else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
+        {
+            out << "    uint width; uint height; uint numberOfLevels;\n"
+                << "    " << textureReference
+                << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
+                << "    width = max(width >> lod, 1);\n"
+                << "    height = max(height >> lod, 1);\n";
+        }
+        else
+            UNREACHABLE();
     }
-    else if (IsSampler2D(textureFunction.sampler) || IsSamplerCube(textureFunction.sampler))
-    {
-        out << "    uint width; uint height; uint numberOfLevels;\n"
-            << "    " << textureReference
-            << ".GetDimensions(baseLevel, width, height, numberOfLevels);\n"
-            << "    width = max(width >> lod, 1);\n"
-            << "    height = max(height >> lod, 1);\n";
-    }
-    else
-        UNREACHABLE();
 
     if (strcmp(textureFunction.getReturnType(), "int3") == 0)
     {
-        out << "    return int3(width, height, depth);";
+        out << "    return int3(width, height, depth);\n";
     }
     else
     {
-        out << "    return int2(width, height);";
+        out << "    return int2(width, height);\n";
     }
 }
 
@@ -1048,6 +1058,9 @@
             case EbtUSamplerCube:
             case EbtSamplerCubeShadow:
             case EbtSamplerExternalOES:
+            case EbtSampler2DMS:
+            case EbtISampler2DMS:
+            case EbtUSampler2DMS:
                 return "int2";
             case EbtSampler3D:
             case EbtISampler3D:
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index 0a4e066..e3be724 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -53,6 +53,8 @@
             return HLSL_TEXTURE_2D_ARRAY;
         case EbtSampler3D:
             return HLSL_TEXTURE_3D;
+        case EbtSampler2DMS:
+            return HLSL_TEXTURE_2D_MS;
         case EbtISampler2D:
             return HLSL_TEXTURE_2D_INT4;
         case EbtISampler3D:
@@ -61,6 +63,8 @@
             return HLSL_TEXTURE_2D_ARRAY_INT4;
         case EbtISampler2DArray:
             return HLSL_TEXTURE_2D_ARRAY_INT4;
+        case EbtISampler2DMS:
+            return HLSL_TEXTURE_2D_MS_INT4;
         case EbtUSampler2D:
             return HLSL_TEXTURE_2D_UINT4;
         case EbtUSampler3D:
@@ -69,6 +73,8 @@
             return HLSL_TEXTURE_2D_ARRAY_UINT4;
         case EbtUSampler2DArray:
             return HLSL_TEXTURE_2D_ARRAY_UINT4;
+        case EbtUSampler2DMS:
+            return HLSL_TEXTURE_2D_MS_UINT4;
         case EbtSampler2DShadow:
             return HLSL_TEXTURE_2D_COMPARISON;
         case EbtSamplerCubeShadow:
@@ -93,18 +99,24 @@
             return "Texture2DArray";
         case HLSL_TEXTURE_3D:
             return "Texture3D";
+        case HLSL_TEXTURE_2D_MS:
+            return "Texture2DMS<float4>";
         case HLSL_TEXTURE_2D_INT4:
             return "Texture2D<int4>";
         case HLSL_TEXTURE_3D_INT4:
             return "Texture3D<int4>";
         case HLSL_TEXTURE_2D_ARRAY_INT4:
             return "Texture2DArray<int4>";
+        case HLSL_TEXTURE_2D_MS_INT4:
+            return "Texture2DMS<int4>";
         case HLSL_TEXTURE_2D_UINT4:
             return "Texture2D<uint4>";
         case HLSL_TEXTURE_3D_UINT4:
             return "Texture3D<uint4>";
         case HLSL_TEXTURE_2D_ARRAY_UINT4:
             return "Texture2DArray<uint4>";
+        case HLSL_TEXTURE_2D_MS_UINT4:
+            return "Texture2DMS<uint4>";
         case HLSL_TEXTURE_2D_COMPARISON:
             return "Texture2D";
         case HLSL_TEXTURE_CUBE_COMPARISON:
@@ -135,18 +147,24 @@
             return "2DArray";
         case HLSL_TEXTURE_3D:
             return "3D";
+        case HLSL_TEXTURE_2D_MS:
+            return "2DMS";
         case HLSL_TEXTURE_2D_INT4:
             return "2D_int4_";
         case HLSL_TEXTURE_3D_INT4:
             return "3D_int4_";
         case HLSL_TEXTURE_2D_ARRAY_INT4:
             return "2DArray_int4_";
+        case HLSL_TEXTURE_2D_MS_INT4:
+            return "2DMS_int4_";
         case HLSL_TEXTURE_2D_UINT4:
             return "2D_uint4_";
         case HLSL_TEXTURE_3D_UINT4:
             return "3D_uint4_";
         case HLSL_TEXTURE_2D_ARRAY_UINT4:
             return "2DArray_uint4_";
+        case HLSL_TEXTURE_2D_MS_UINT4:
+            return "2DMS_uint4_";
         case HLSL_TEXTURE_2D_COMPARISON:
             return "2D_comparison";
         case HLSL_TEXTURE_CUBE_COMPARISON:
diff --git a/src/compiler/translator/UtilsHLSL.h b/src/compiler/translator/UtilsHLSL.h
index e5ece0a..61fd1ef 100644
--- a/src/compiler/translator/UtilsHLSL.h
+++ b/src/compiler/translator/UtilsHLSL.h
@@ -31,12 +31,15 @@
     HLSL_TEXTURE_CUBE,
     HLSL_TEXTURE_2D_ARRAY,
     HLSL_TEXTURE_3D,
+    HLSL_TEXTURE_2D_MS,
     HLSL_TEXTURE_2D_INT4,
     HLSL_TEXTURE_3D_INT4,
     HLSL_TEXTURE_2D_ARRAY_INT4,
+    HLSL_TEXTURE_2D_MS_INT4,
     HLSL_TEXTURE_2D_UINT4,
     HLSL_TEXTURE_3D_UINT4,
     HLSL_TEXTURE_2D_ARRAY_UINT4,
+    HLSL_TEXTURE_2D_MS_UINT4,
 
     // Comparison samplers