[glsl][ir] Support multisampled texture types

This CL adds support for the `MultisampledTexture` type.

Bug: 42251044
Change-Id: I20060f8fe63e135750a06183e2fcec7a439f9370
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204516
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/glsl/writer/printer/printer.cc b/src/tint/lang/glsl/writer/printer/printer.cc
index 6e0ad47..f70583e 100644
--- a/src/tint/lang/glsl/writer/printer/printer.cc
+++ b/src/tint/lang/glsl/writer/printer/printer.cc
@@ -59,6 +59,7 @@
 #include "src/tint/lang/core/type/f32.h"
 #include "src/tint/lang/core/type/i32.h"
 #include "src/tint/lang/core/type/matrix.h"
+#include "src/tint/lang/core/type/multisampled_texture.h"
 #include "src/tint/lang/core/type/pointer.h"
 #include "src/tint/lang/core/type/sampled_texture.h"
 #include "src/tint/lang/core/type/storage_texture.h"
@@ -450,6 +451,7 @@
 
         auto* storage = t->As<core::type::StorageTexture>();
         auto* sampled = t->As<core::type::SampledTexture>();
+        auto* ms = t->As<core::type::MultisampledTexture>();
 
         out << "highp ";
 
@@ -480,7 +482,10 @@
                     TINT_UNREACHABLE();
             }
         }
-        auto* subtype = sampled ? sampled->Type() : storage ? storage->Type() : nullptr;
+        auto* subtype = sampled   ? sampled->Type()
+                        : storage ? storage->Type()
+                        : ms      ? ms->Type()
+                                  : nullptr;
 
         if (subtype) {
             tint::Switch(
@@ -499,9 +504,16 @@
                 break;
             case core::type::TextureDimension::k2d:
                 out << "2D";
+                if (ms) {
+                    out << "MS";
+                }
                 break;
             case core::type::TextureDimension::k2dArray:
-                out << "2DArray";
+                out << "2D";
+                if (ms) {
+                    out << "MS";
+                }
+                out << "Array";
                 break;
             case core::type::TextureDimension::k3d:
                 out << "3D";
diff --git a/src/tint/lang/glsl/writer/type_test.cc b/src/tint/lang/glsl/writer/type_test.cc
index 68e62c6..9e73ee5 100644
--- a/src/tint/lang/glsl/writer/type_test.cc
+++ b/src/tint/lang/glsl/writer/type_test.cc
@@ -716,22 +716,98 @@
         GlslTextureData{core::type::TextureDimension::kCubeArray, TextureDataType::kU32,
                         "usamplerCubeArray"}));
 
-// TODO(dsinclair): Add multisampled texture support
-TEST_F(GlslWriterTest, DISABLED_EmitType_MultisampledTexture) {
-    auto* ms = ty.Get<core::type::MultisampledTexture>(core::type::TextureDimension::k2d, ty.u32());
-    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+using GlslWriterMultisampledTextureESTest = GlslWriterTestWithParam<GlslTextureData>;
+TEST_P(GlslWriterMultisampledTextureESTest, Emit) {
+    auto params = GetParam();
+
+    const core::type::Type* subtype = nullptr;
+    switch (params.datatype) {
+        case TextureDataType::kF32:
+            subtype = ty.f32();
+            break;
+        case TextureDataType::kI32:
+            subtype = ty.i32();
+            break;
+        case TextureDataType::kU32:
+            subtype = ty.u32();
+            break;
+    }
+
+    auto* ms = ty.Get<core::type::MultisampledTexture>(params.dim, subtype);
+    auto* func = b.Function("foo", ty.void_());
     auto* param = b.FunctionParam("a", ms);
     func->SetParams({param});
-    func->SetWorkgroupSize(1, 1, 1);
     b.Append(func->Block(), [&] { b.Return(func); });
 
     ASSERT_TRUE(Generate()) << err_ << output_.glsl;
-    EXPECT_EQ(output_.glsl, R"(
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(
+void foo(highp )" + params.result +
+                                R"( a) {
+}
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
-void main(usampler2DMS a) {
+void main() {
 }
 )");
 }
+INSTANTIATE_TEST_SUITE_P(GlslWriterTest,
+                         GlslWriterMultisampledTextureESTest,
+                         testing::Values(GlslTextureData{core::type::TextureDimension::k2d,
+                                                         TextureDataType::kF32, "sampler2DMS"},
+                                         GlslTextureData{core::type::TextureDimension::k2d,
+                                                         TextureDataType::kI32, "isampler2DMS"},
+                                         GlslTextureData{core::type::TextureDimension::k2d,
+                                                         TextureDataType::kU32, "usampler2DMS"}));
+
+using GlslWriterMultisampledTextureNonESTest = GlslWriterTestWithParam<GlslTextureData>;
+TEST_P(GlslWriterMultisampledTextureNonESTest, Emit) {
+    auto params = GetParam();
+
+    const core::type::Type* subtype = nullptr;
+    switch (params.datatype) {
+        case TextureDataType::kF32:
+            subtype = ty.f32();
+            break;
+        case TextureDataType::kI32:
+            subtype = ty.i32();
+            break;
+        case TextureDataType::kU32:
+            subtype = ty.u32();
+            break;
+    }
+    auto* ms = ty.Get<core::type::MultisampledTexture>(params.dim, subtype);
+    auto* func = b.Function("foo", ty.void_());
+    auto* param = b.FunctionParam("a", ms);
+    func->SetParams({param});
+    b.Append(func->Block(), [&] { b.Return(func); });
+
+    Options opts{};
+    opts.version = Version(Version::Standard::kDesktop, 4, 6);
+    ASSERT_TRUE(Generate(opts)) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, R"(#version 460
+
+void foo(highp )" + params.result +
+                                R"( a) {
+}
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void main() {
+}
+)");
+}
+INSTANTIATE_TEST_SUITE_P(
+    GlslWriterTest,
+    GlslWriterMultisampledTextureNonESTest,
+    testing::Values(
+        GlslTextureData{core::type::TextureDimension::k2d, TextureDataType::kF32, "sampler2DMS"},
+        GlslTextureData{core::type::TextureDimension::k2dArray, TextureDataType::kF32,
+                        "sampler2DMSArray"},
+
+        GlslTextureData{core::type::TextureDimension::k2d, TextureDataType::kI32, "isampler2DMS"},
+        GlslTextureData{core::type::TextureDimension::k2dArray, TextureDataType::kI32,
+                        "isampler2DMSArray"},
+
+        GlslTextureData{core::type::TextureDimension::k2d, TextureDataType::kU32, "usampler2DMS"},
+        GlslTextureData{core::type::TextureDimension::k2dArray, TextureDataType::kU32,
+                        "usampler2DMSArray"}));
 
 struct GlslStorageTextureData {
     core::type::TextureDimension dim;