[glsl][ir] Emit vector types.

Add vector type emission to the GLSL IR backend.

Bug: 42251044
Change-Id: Iea6eacc4d871545e44ecd4aeb9a81c241ae8ef96
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204254
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/glsl/writer/printer/printer.cc b/src/tint/lang/glsl/writer/printer/printer.cc
index 3c59959..958ca60 100644
--- a/src/tint/lang/glsl/writer/printer/printer.cc
+++ b/src/tint/lang/glsl/writer/printer/printer.cc
@@ -30,6 +30,7 @@
 #include <string>
 #include <utility>
 
+#include "src/tint/lang/core/constant/splat.h"
 #include "src/tint/lang/core/ir/access.h"
 #include "src/tint/lang/core/ir/bitcast.h"
 #include "src/tint/lang/core/ir/construct.h"
@@ -55,6 +56,7 @@
 #include "src/tint/lang/core/type/i32.h"
 #include "src/tint/lang/core/type/pointer.h"
 #include "src/tint/lang/core/type/u32.h"
+#include "src/tint/lang/core/type/vector.h"
 #include "src/tint/lang/core/type/void.h"
 #include "src/tint/lang/glsl/writer/common/printer_support.h"
 #include "src/tint/lang/glsl/writer/common/version.h"
@@ -302,11 +304,28 @@
             [&](const core::type::Pointer* p) {
                 EmitType(out, p->StoreType(), name, name_printed);
             },
+            [&](const core::type::Vector* v) { EmitVectorType(out, v); },
 
             // TODO(dsinclair): Handle remaining types
             TINT_ICE_ON_NO_MATCH);
     }
 
+    void EmitVectorType(StringStream& out, const core::type::Vector* v) {
+        tint::Switch(
+            v->Type(),                       //
+            [&](const core::type::F32*) {},  //
+            [&](const core::type::F16*) {
+                EmitExtension(kAMDGpuShaderHalfFloat);
+                out << "f16";
+            },
+            [&](const core::type::I32*) { out << "i"; },
+            [&](const core::type::U32*) { out << "u"; },
+            [&](const core::type::Bool*) { out << "b"; },  //
+            TINT_ICE_ON_NO_MATCH);
+
+        out << "vec" << v->Width();
+    }
+
     void EmitArrayType(StringStream& out,
                        const core::type::Array* ary,
                        const std::string& name,
@@ -416,11 +435,32 @@
             [&](const core::type::U32*) { out << c->ValueAs<AInt>() << "u"; },
             [&](const core::type::F32*) { PrintF32(out, c->ValueAs<f32>()); },
             [&](const core::type::F16*) { PrintF16(out, c->ValueAs<f16>()); },
+            [&](const core::type::Vector* v) { EmitConstantVector(out, v, c); },
 
             // TODO(dsinclair): Emit remaining constant types
             TINT_ICE_ON_NO_MATCH);
     }
 
+    void EmitConstantVector(StringStream& out,
+                            const core::type::Vector* v,
+                            const core::constant::Value* c) {
+        EmitType(out, v);
+
+        ScopedParen sp(out);
+
+        if (auto* splat = c->As<core::constant::Splat>()) {
+            EmitConstant(out, splat->el);
+            return;
+        }
+
+        for (size_t i = 0; i < v->Width(); ++i) {
+            if (i > 0) {
+                out << ", ";
+            }
+            EmitConstant(out, c->Index(i));
+        }
+    }
+
     void EmitConstantArray(StringStream& out,
                            const core::type::Array* ary,
                            const core::constant::Value* c) {
diff --git a/src/tint/lang/glsl/writer/type_test.cc b/src/tint/lang/glsl/writer/type_test.cc
index 2a179be..ae4f717 100644
--- a/src/tint/lang/glsl/writer/type_test.cc
+++ b/src/tint/lang/glsl/writer/type_test.cc
@@ -250,8 +250,7 @@
 )");
 }
 
-// TODO(dsinclair): Add vector support
-TEST_F(GlslWriterTest, DISABLED_EmitType_Vector_F32) {
+TEST_F(GlslWriterTest, EmitType_Vector_F32) {
     auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
     func->SetWorkgroupSize(1, 1, 1);
     b.Append(func->Block(), [&] {
@@ -263,13 +262,12 @@
     EXPECT_EQ(output_.glsl, GlslHeader() + R"(
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void foo() {
-  vec3 a = 0.0f;
+  vec3 a = vec3(0.0f);
 }
 )");
 }
 
-// TODO(dsinclair): Add vector support
-TEST_F(GlslWriterTest, DISABLED_EmitType_Vector_F16) {
+TEST_F(GlslWriterTest, EmitType_Vector_F16) {
     auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
     func->SetWorkgroupSize(1, 1, 1);
     b.Append(func->Block(), [&] {
@@ -278,10 +276,62 @@
     });
 
     ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(#extension GL_AMD_gpu_shader_half_float: require
+
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void foo() {
+  f16vec3 a = f16vec3(0.0hf);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, EmitType_Vector_I32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+    func->SetWorkgroupSize(1, 1, 1);
+    b.Append(func->Block(), [&] {
+        b.Var("a", ty.ptr(core::AddressSpace::kPrivate, ty.vec2<i32>()));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
     EXPECT_EQ(output_.glsl, GlslHeader() + R"(
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 void foo() {
-  f16vec3 a = 0.0h;
+  ivec2 a = ivec2(0);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, EmitType_Vector_U32) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+    func->SetWorkgroupSize(1, 1, 1);
+    b.Append(func->Block(), [&] {
+        b.Var("a", ty.ptr(core::AddressSpace::kPrivate, ty.vec4<u32>()));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void foo() {
+  uvec4 a = uvec4(0u);
+}
+)");
+}
+
+TEST_F(GlslWriterTest, EmitType_Vector_bool) {
+    auto* func = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kCompute);
+    func->SetWorkgroupSize(1, 1, 1);
+    b.Append(func->Block(), [&] {
+        b.Var("a", ty.ptr(core::AddressSpace::kPrivate, ty.vec3<bool>()));
+        b.Return(func);
+    });
+
+    ASSERT_TRUE(Generate()) << err_ << output_.glsl;
+    EXPECT_EQ(output_.glsl, GlslHeader() + R"(
+layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
+void foo() {
+  bvec3 a = bvec3(false);
 }
 )");
 }