spirv-reader: Add interpolate(flat) to integral pipeline IO

This is now required in WGSL, and will soon become an error in Tint.

Bug: tint:1224
Change-Id: Ide98c4c0b7aac86a2b43f7e02abde3d8a297dce4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68920
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 0ace622..15fed61 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1777,9 +1777,9 @@
 bool ParserImpl::ConvertPipelineDecorations(const Type* store_type,
                                             const DecorationList& decorations,
                                             ast::DecorationList* ast_decos) {
-  bool has_interpolate_no_perspective = false;
-  bool has_interpolate_sampling_centroid = false;
-  bool has_interpolate_sampling_sample = false;
+  // Vulkan defaults to perspective-correct interpolation.
+  ast::InterpolationType type = ast::InterpolationType::kPerspective;
+  ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
 
   for (const auto& deco : decorations) {
     TINT_ASSERT(Reader, deco.size() > 0);
@@ -1793,22 +1793,14 @@
                     create<ast::LocationDecoration>(Source{}, deco[1]));
         break;
       case SpvDecorationFlat:
-        // In WGSL, integral types are always flat, and so the decoration
-        // is never specified.
-        if (!store_type->IsIntegerScalarOrVector()) {
-          ast_decos->emplace_back(create<ast::InterpolateDecoration>(
-              Source{}, ast::InterpolationType::kFlat,
-              ast::InterpolationSampling::kNone));
-          // Only one interpolate attribute is allowed.
-          return true;
-        }
+        type = ast::InterpolationType::kFlat;
         break;
       case SpvDecorationNoPerspective:
         if (store_type->IsIntegerScalarOrVector()) {
           // This doesn't capture the array or struct case.
           return Fail() << "NoPerspective is invalid on integral IO";
         }
-        has_interpolate_no_perspective = true;
+        type = ast::InterpolationType::kLinear;
         break;
       case SpvDecorationCentroid:
         if (store_type->IsIntegerScalarOrVector()) {
@@ -1816,7 +1808,7 @@
           return Fail()
                  << "Centroid interpolation sampling is invalid on integral IO";
         }
-        has_interpolate_sampling_centroid = true;
+        sampling = ast::InterpolationSampling::kCentroid;
         break;
       case SpvDecorationSample:
         if (store_type->IsIntegerScalarOrVector()) {
@@ -1824,33 +1816,19 @@
           return Fail()
                  << "Sample interpolation sampling is invalid on integral IO";
         }
-        has_interpolate_sampling_sample = true;
+        sampling = ast::InterpolationSampling::kSample;
         break;
       default:
         break;
     }
   }
 
-  // Apply non-integral interpolation.
-  if (has_interpolate_no_perspective || has_interpolate_sampling_centroid ||
-      has_interpolate_sampling_sample) {
-    const ast::InterpolationType type =
-        has_interpolate_no_perspective ? ast::InterpolationType::kLinear
-                                       : ast::InterpolationType::kPerspective;
-    const ast::InterpolationSampling sampling =
-        has_interpolate_sampling_centroid
-            ? ast::InterpolationSampling::kCentroid
-            : (has_interpolate_sampling_sample
-                   ? ast::InterpolationSampling::kSample
-                   : ast::InterpolationSampling::
-                         kNone /* Center is the default */);
-    if (type == ast::InterpolationType::kPerspective &&
-        sampling == ast::InterpolationSampling::kNone) {
-      // This is the default. Don't add a decoration.
-    } else {
-      ast_decos->emplace_back(
-          create<ast::InterpolateDecoration>(type, sampling));
-    }
+  // Apply interpolation.
+  if (type == ast::InterpolationType::kPerspective &&
+      sampling == ast::InterpolationSampling::kNone) {
+    // This is the default. Don't add a decoration.
+  } else {
+    ast_decos->emplace_back(create<ast::InterpolateDecoration>(type, sampling));
   }
 
   return success();
diff --git a/src/reader/spirv/parser_impl_module_var_test.cc b/src/reader/spirv/parser_impl_module_var_test.cc
index 27bca8b..9d12fcd 100644
--- a/src/reader/spirv/parser_impl_module_var_test.cc
+++ b/src/reader/spirv/parser_impl_module_var_test.cc
@@ -4813,7 +4813,7 @@
 };
 
 [[stage(vertex)]]
-fn main([[location(1)]] x_1_param : u32, [[location(2)]] x_2_param : vec2<u32>, [[location(3)]] x_3_param : i32, [[location(4)]] x_4_param : vec2<i32>, [[location(5), interpolate(flat)]] x_5_param : f32, [[location(6), interpolate(flat)]] x_6_param : vec2<f32>) -> main_out {
+fn main([[location(1), interpolate(flat)]] x_1_param : u32, [[location(2), interpolate(flat)]] x_2_param : vec2<u32>, [[location(3), interpolate(flat)]] x_3_param : i32, [[location(4), interpolate(flat)]] x_4_param : vec2<i32>, [[location(5), interpolate(flat)]] x_5_param : f32, [[location(6), interpolate(flat)]] x_6_param : vec2<f32>) -> main_out {
   x_1 = x_1_param;
   x_2 = x_2_param;
   x_3 = x_3_param;
@@ -4893,13 +4893,13 @@
 }
 
 struct main_out {
-  [[location(1)]]
+  [[location(1), interpolate(flat)]]
   x_1_1 : u32;
-  [[location(2)]]
+  [[location(2), interpolate(flat)]]
   x_2_1 : vec2<u32>;
-  [[location(3)]]
+  [[location(3), interpolate(flat)]]
   x_3_1 : i32;
-  [[location(4)]]
+  [[location(4), interpolate(flat)]]
   x_4_1 : vec2<i32>;
   [[location(5), interpolate(flat)]]
   x_5_1 : f32;