writer/hlsl: Implement interpolate attributes

Bug: tint:746
Change-Id: I3133a756d1fe830c0baf45a1251acea9511d92b1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56246
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 0c0c474..430f05f 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2212,6 +2212,35 @@
   return "";
 }
 
+std::string GeneratorImpl::interpolation_to_modifiers(
+    ast::InterpolationType type,
+    ast::InterpolationSampling sampling) const {
+  std::string modifiers;
+  switch (type) {
+    case ast::InterpolationType::kPerspective:
+      modifiers += "linear ";
+      break;
+    case ast::InterpolationType::kLinear:
+      modifiers += "noperspective ";
+      break;
+    case ast::InterpolationType::kFlat:
+      modifiers += "nointerpolation ";
+      break;
+  }
+  switch (sampling) {
+    case ast::InterpolationSampling::kCentroid:
+      modifiers += "centroid ";
+      break;
+    case ast::InterpolationSampling::kSample:
+      modifiers += "sample ";
+      break;
+    case ast::InterpolationSampling::kCenter:
+    case ast::InterpolationSampling::kNone:
+      break;
+  }
+  return modifiers;
+}
+
 bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
   auto* func_sem = builder_.Sem().Get(func);
 
@@ -2737,10 +2766,8 @@
       auto* ty = mem->Type();
 
       auto out = line();
-      if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone,
-                           ast::Access::kReadWrite, name)) {
-        return false;
-      }
+
+      std::string pre, post;
 
       for (auto* deco : mem->Declaration()->decorations()) {
         if (auto* location = deco->As<ast::LocationDecoration>()) {
@@ -2752,16 +2779,16 @@
 
           if (pipeline_stage_uses.count(
                   sem::PipelineStageUsage::kVertexInput)) {
-            out << " : TEXCOORD" + std::to_string(location->value());
+            post += " : TEXCOORD" + std::to_string(location->value());
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kVertexOutput)) {
-            out << " : TEXCOORD" + std::to_string(location->value());
+            post += " : TEXCOORD" + std::to_string(location->value());
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kFragmentInput)) {
-            out << " : TEXCOORD" + std::to_string(location->value());
+            post += " : TEXCOORD" + std::to_string(location->value());
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kFragmentOutput)) {
-            out << " : SV_Target" + std::to_string(location->value());
+            post += " : SV_Target" + std::to_string(location->value());
           } else {
             TINT_ICE(Writer, diagnostics_)
                 << "invalid use of location decoration";
@@ -2772,13 +2799,25 @@
             diagnostics_.add_error(diag::System::Writer, "unsupported builtin");
             return false;
           }
-          out << " : " << attr;
-        } else if (deco->Is<ast::InterpolateDecoration>()) {
-          TINT_UNIMPLEMENTED(Writer, diagnostics_) << "interpolate decoration";
+          post += " : " + attr;
+        } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
+          auto mod = interpolation_to_modifiers(interpolate->type(),
+                                                interpolate->sampling());
+          if (mod.empty()) {
+            diagnostics_.add_error(diag::System::Writer,
+                                   "unsupported interpolation");
+            return false;
+          }
+          pre += mod;
         }
       }
 
-      out << ";";
+      out << pre;
+      if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone,
+                           ast::Access::kReadWrite, name)) {
+        return false;
+      }
+      out << post << ";";
     }
   }
 
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index fd3c6bd..77f2bcf 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -353,6 +353,14 @@
   /// @returns the string name of the builtin or blank on error
   std::string builtin_to_attribute(ast::Builtin builtin) const;
 
+  /// Converts interpolation attributes to a HLSL modifiers
+  /// @param type the interpolation type
+  /// @param sampling the interpolation sampling
+  /// @returns the string name of the attribute or blank on error
+  std::string interpolation_to_modifiers(
+      ast::InterpolationType type,
+      ast::InterpolationSampling sampling) const;
+
   /// Generate a unique name
   /// @param prefix the name prefix
   /// @returns a unique name
diff --git a/test/shader_io/interpolate_input_parameters.wgsl.expected.hlsl b/test/shader_io/interpolate_input_parameters.wgsl.expected.hlsl
index 3cd1e7f..e653990 100644
--- a/test/shader_io/interpolate_input_parameters.wgsl.expected.hlsl
+++ b/test/shader_io/interpolate_input_parameters.wgsl.expected.hlsl
@@ -1,10 +1,22 @@
-SKIP: FAILED
+struct tint_symbol_1 {
+  float none : TEXCOORD0;
+  nointerpolation float flat : TEXCOORD1;
+  linear float perspective_center : TEXCOORD2;
+  linear centroid float perspective_centroid : TEXCOORD3;
+  linear sample float perspective_sample : TEXCOORD4;
+  noperspective float linear_center : TEXCOORD5;
+  noperspective centroid float linear_centroid : TEXCOORD6;
+  noperspective sample float linear_sample : TEXCOORD7;
+};
 
-../../src/writer/hlsl/generator_impl.cc:2862 internal compiler error: TINT_UNIMPLEMENTED interpolate decoration
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
+void main(tint_symbol_1 tint_symbol) {
+  const float none = tint_symbol.none;
+  const float flat = tint_symbol.flat;
+  const float perspective_center = tint_symbol.perspective_center;
+  const float perspective_centroid = tint_symbol.perspective_centroid;
+  const float perspective_sample = tint_symbol.perspective_sample;
+  const float linear_center = tint_symbol.linear_center;
+  const float linear_centroid = tint_symbol.linear_centroid;
+  const float linear_sample = tint_symbol.linear_sample;
+  return;
+}
diff --git a/test/shader_io/interpolate_input_struct.wgsl.expected.hlsl b/test/shader_io/interpolate_input_struct.wgsl.expected.hlsl
index 3cd1e7f..694807b 100644
--- a/test/shader_io/interpolate_input_struct.wgsl.expected.hlsl
+++ b/test/shader_io/interpolate_input_struct.wgsl.expected.hlsl
@@ -1,10 +1,25 @@
-SKIP: FAILED
+struct In {
+  float none;
+  float flat;
+  float perspective_center;
+  float perspective_centroid;
+  float perspective_sample;
+  float linear_center;
+  float linear_centroid;
+  float linear_sample;
+};
+struct tint_symbol_2 {
+  float none : TEXCOORD0;
+  nointerpolation float flat : TEXCOORD1;
+  linear float perspective_center : TEXCOORD2;
+  linear centroid float perspective_centroid : TEXCOORD3;
+  linear sample float perspective_sample : TEXCOORD4;
+  noperspective float linear_center : TEXCOORD5;
+  noperspective centroid float linear_centroid : TEXCOORD6;
+  noperspective sample float linear_sample : TEXCOORD7;
+};
 
-../../src/writer/hlsl/generator_impl.cc:2862 internal compiler error: TINT_UNIMPLEMENTED interpolate decoration
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
+void main(tint_symbol_2 tint_symbol_1) {
+  const In tint_symbol = {tint_symbol_1.none, tint_symbol_1.flat, tint_symbol_1.perspective_center, tint_symbol_1.perspective_centroid, tint_symbol_1.perspective_sample, tint_symbol_1.linear_center, tint_symbol_1.linear_centroid, tint_symbol_1.linear_sample};
+  return;
+}
diff --git a/test/shader_io/interpolate_return_struct.wgsl.expected.hlsl b/test/shader_io/interpolate_return_struct.wgsl.expected.hlsl
index 3cd1e7f..e7d0604 100644
--- a/test/shader_io/interpolate_return_struct.wgsl.expected.hlsl
+++ b/test/shader_io/interpolate_return_struct.wgsl.expected.hlsl
@@ -1,10 +1,28 @@
-SKIP: FAILED
+struct Out {
+  float4 pos;
+  float none;
+  float flat;
+  float perspective_center;
+  float perspective_centroid;
+  float perspective_sample;
+  float linear_center;
+  float linear_centroid;
+  float linear_sample;
+};
+struct tint_symbol {
+  float none : TEXCOORD0;
+  nointerpolation float flat : TEXCOORD1;
+  linear float perspective_center : TEXCOORD2;
+  linear centroid float perspective_centroid : TEXCOORD3;
+  linear sample float perspective_sample : TEXCOORD4;
+  noperspective float linear_center : TEXCOORD5;
+  noperspective centroid float linear_centroid : TEXCOORD6;
+  noperspective sample float linear_sample : TEXCOORD7;
+  float4 pos : SV_Position;
+};
 
-../../src/writer/hlsl/generator_impl.cc:2862 internal compiler error: TINT_UNIMPLEMENTED interpolate decoration
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
+tint_symbol main() {
+  const Out tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+  const tint_symbol tint_symbol_2 = {tint_symbol_1.none, tint_symbol_1.flat, tint_symbol_1.perspective_center, tint_symbol_1.perspective_centroid, tint_symbol_1.perspective_sample, tint_symbol_1.linear_center, tint_symbol_1.linear_centroid, tint_symbol_1.linear_sample, tint_symbol_1.pos};
+  return tint_symbol_2;
+}