[spirv-reader][ir] Fixup interpolation values.

When coming from SPIR-V all fragment sharder integer inputs are
decorated as `flat`. We need to strip these off when coming to WGSL if
they don't have a `location` attached as well.

The default value of `perspective,center` is stripped off as well.

Bug: 42250952
Change-Id: Ie817fe59329dcd45f2bb893322d44e8232aebee5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/246334
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 45482cf..b79b4f9 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -3293,7 +3293,9 @@
             // Create the interpolation field with the default values on first call.
             if (!io_attributes.interpolation.has_value()) {
                 io_attributes.interpolation = core::Interpolation{
-                    core::InterpolationType::kPerspective, core::InterpolationSampling::kCenter};
+                    .type = core::InterpolationType::kPerspective,
+                    .sampling = core::InterpolationSampling::kCenter,
+                };
             }
             return io_attributes.interpolation.value();
         };
@@ -3342,6 +3344,22 @@
             }
         }
 
+        if (io_attributes.interpolation.has_value()) {
+            // WGSL requires that '@interpolate(flat)' needs to be paired with '@location', however
+            // SPIR-V requires all fragment shader integer Inputs are 'flat'. If the decorations do
+            // not contain a spv::Decoration::Location, then remove the interpolation decoration.
+            //
+            // The `perspective,center` interpolation is the default value if one isn't provided.
+            // Just strip it off. This keeps us from accidentally applying interpolation where it
+            // isn't permitted, and it isn't necessary.
+            if ((io_attributes.interpolation->type == core::InterpolationType::kFlat &&
+                 !io_attributes.location.has_value()) ||
+                (io_attributes.interpolation->type == core::InterpolationType::kPerspective &&
+                 io_attributes.interpolation->sampling == core::InterpolationSampling::kCenter)) {
+                io_attributes.interpolation = std::nullopt;
+            }
+        }
+
         auto* element_ty = Type(inst.type_id(), access_mode)->As<core::type::Pointer>();
         auto* var = b_.Var(element_ty);
         if (inst.NumOperands() > 3) {
diff --git a/src/tint/lang/spirv/reader/parser/var_test.cc b/src/tint/lang/spirv/reader/parser/var_test.cc
index d1e845c..a45acb2 100644
--- a/src/tint/lang/spirv/reader/parser/var_test.cc
+++ b/src/tint/lang/spirv/reader/parser/var_test.cc
@@ -1328,5 +1328,41 @@
 )");
 }
 
+TEST_F(SpirvParserTest, InterpolationFlatNoLocation) {
+    EXPECT_IR(R"(
+             OpCapability Shader
+             OpCapability SampleRateShading
+             OpMemoryModel Logical Simple
+             OpEntryPoint Fragment %3 "main" %gl_SampleID
+             OpExecutionMode %3 OriginUpperLeft
+             OpDecorate %gl_SampleID BuiltIn SampleId
+             OpDecorate %gl_SampleID Flat
+     %void = OpTypeVoid
+        %5 = OpTypeFunction %void
+    %float = OpTypeFloat 32
+     %uint = OpTypeInt 32 0
+      %int = OpTypeInt 32 1
+%_ptr_Input_uint = OpTypePointer Input %uint
+%gl_SampleID = OpVariable %_ptr_Input_uint Input
+        %3 = OpFunction %void None %5
+       %10 = OpLabel
+        %2 = OpLoad %uint %gl_SampleID
+             OpReturn
+             OpFunctionEnd
+)",
+              R"(
+$B1: {  # root
+  %1:ptr<__in, u32, read> = var undef @builtin(sample_index)
+}
+
+%main = @fragment func():void {
+  $B2: {
+    %3:u32 = load %1
+    ret
+  }
+}
+)");
+}
+
 }  // namespace
 }  // namespace tint::spirv::reader