[spirv-reader][ir] Handle PointSize applied to an `OpVariable`.

We previously handled `PointSize` when applied to a structure member,
but not when applied to an `OpVariable`. In this case, we can just not
emit the member into the output structure (because WGSL has no
PointSize) and set the initializer to `1.0f` to emulate the value for
any usage internal to the shader.

Bug: 42250952
Change-Id: Icc5e6a6e22ceac0156e13c7a79e6161de1a7cf84
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/246754
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/lower/shader_io.cc b/src/tint/lang/spirv/reader/lower/shader_io.cc
index 0bf4231..dbe23a5 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io.cc
@@ -38,7 +38,8 @@
 
 namespace {
 
-using namespace tint::core::fluent_types;  // NOLINT
+using namespace tint::core::number_suffixes;  // NOLINT
+using namespace tint::core::fluent_types;     // NOLINT
 
 /// PIMPL state for the transform.
 struct State {
@@ -236,6 +237,14 @@
                     }
                 }
             } else {
+                // Don't want to emit point size as it doesn't exist in WGSL.
+                if (var->Attributes().builtin == core::BuiltinValue::kPointSize) {
+                    // TODO(dsinclair): Validate that all accesses of this variable are then used
+                    // only to assign the value of 1.0.
+                    var->SetInitializer(b.Constant(1.0_f));
+                    continue;
+                }
+
                 // Load the final result from the original variable.
                 b.Append(wrapper->Block(), [&] {
                     results.Push(b.Load(var)->Result());
@@ -254,6 +263,7 @@
                         var_type = ty.u32();
                     }
                 });
+
                 add_output(ir.NameOf(var), var_type, std::move(var_attributes));
             }
         }
diff --git a/src/tint/lang/spirv/reader/lower/shader_io_test.cc b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
index ec60cb9..f2c1d06 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io_test.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io_test.cc
@@ -3159,7 +3159,7 @@
     EXPECT_EQ(expect, str());
 }
 
-TEST_F(SpirvReader_ShaderIOTest, PointSize) {
+TEST_F(SpirvReader_ShaderIOTest, PointSize_Struct) {
     auto* builtin_str =
         ty.Struct(mod.symbols.New("Builtins"), Vector{
                                                    core::type::Manager::StructMemberDesc{
@@ -3240,6 +3240,74 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(SpirvReader_ShaderIOTest, PointSize_Var) {
+    auto* ps = b.Var("point_size", ty.ptr(core::AddressSpace::kOut, ty.f32()));
+    ps->SetBuiltin(core::BuiltinValue::kPointSize);
+    mod.root_block->Append(ps);
+
+    auto* o = b.Var("other", ty.ptr<private_, f32>());
+    mod.root_block->Append(o);
+
+    auto* pos = b.Var("position", ty.ptr(core::AddressSpace::kOut, ty.vec4<f32>()));
+    pos->SetBuiltin(core::BuiltinValue::kPosition);
+    mod.root_block->Append(pos);
+
+    auto* ep = b.Function("foo", ty.void_(), core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {  //
+        auto* v = b.Load(ps);
+        b.Store(o, v);
+
+        b.Store(pos, b.Zero(ty.vec4<f32>()));
+        b.Return(ep);
+    });
+
+    auto* src = R"(
+$B1: {  # root
+  %point_size:ptr<__out, f32, read_write> = var undef @builtin(__point_size)
+  %other:ptr<private, f32, read_write> = var undef
+  %position:ptr<__out, vec4<f32>, read_write> = var undef @builtin(position)
+}
+
+%foo = @vertex func():void {
+  $B2: {
+    %5:f32 = load %point_size
+    store %other, %5
+    store %position, vec4<f32>(0.0f)
+    ret
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+$B1: {  # root
+  %point_size:ptr<private, f32, read_write> = var 1.0f
+  %other:ptr<private, f32, read_write> = var undef
+  %position:ptr<private, vec4<f32>, read_write> = var undef
+}
+
+%foo_inner = func():void {
+  $B2: {
+    %5:f32 = load %point_size
+    store %other, %5
+    store %position, vec4<f32>(0.0f)
+    ret
+  }
+}
+%foo = @vertex func():vec4<f32> [@position] {
+  $B3: {
+    %7:void = call %foo_inner
+    %8:vec4<f32> = load %position
+    ret %8
+  }
+}
+)";
+
+    Run(ShaderIO);
+
+    EXPECT_EQ(expect, str());
+}
+
 TEST_F(SpirvReader_ShaderIOTest, Outputs_Struct_UnusedOutputs) {
     auto* builtin_str = ty.Struct(mod.symbols.New("Builtins"),
                                   Vector{
diff --git a/src/tint/lang/spirv/reader/reader_test.cc b/src/tint/lang/spirv/reader/reader_test.cc
index 4a1ef8a..236c03b 100644
--- a/src/tint/lang/spirv/reader/reader_test.cc
+++ b/src/tint/lang/spirv/reader/reader_test.cc
@@ -325,13 +325,12 @@
 tint_symbol = struct @align(16) {
   main_position_Output:vec4<f32> @offset(0), @builtin(position)
   main_clip_distances_Output:array<f32, 1> @offset(16), @builtin(clip_distances)
-  main___point_size_Output:f32 @offset(20), @builtin(__point_size)
 }
 
 $B1: {  # root
   %main_position_Output:ptr<private, vec4<f32>, read_write> = var undef
   %main_clip_distances_Output:ptr<private, array<f32, 1>, read_write> = var undef
-  %main___point_size_Output:ptr<private, f32, read_write> = var undef
+  %main___point_size_Output:ptr<private, f32, read_write> = var 1.0f
 }
 
 %main_inner = func():VertexOutputs {
@@ -355,9 +354,8 @@
     %10:void = call %main_inner_1
     %11:vec4<f32> = load %main_position_Output
     %12:array<f32, 1> = load %main_clip_distances_Output
-    %13:f32 = load %main___point_size_Output
-    %14:tint_symbol = construct %11, %12, %13
-    ret %14
+    %13:tint_symbol = construct %11, %12
+    ret %13
   }
 }
 )");