Compat: Make sample, linear usage info createShaderModule errors

There errors were pipeline creation errors but the spec changed
to make them shader module creation errors.

Bug: 340322894
Change-Id: I537aa5e0e10ec85a838040fba36546af57b10db6
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/193700
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Gregg Tavares <gman@chromium.org>
diff --git a/src/dawn/native/RenderPipeline.cpp b/src/dawn/native/RenderPipeline.cpp
index c94db8b..cd1441b 100644
--- a/src/dawn/native/RenderPipeline.cpp
+++ b/src/dawn/native/RenderPipeline.cpp
@@ -797,18 +797,6 @@
             "different from the interpolation sampling (%s) of the fragment input at "
             "location %u.",
             vertexOutputInfo.interpolationSampling, i, fragmentInputInfo.interpolationSampling, i);
-
-        DAWN_INVALID_IF(device->IsCompatibilityMode() &&
-                            vertexOutputInfo.interpolationType == InterpolationType::Linear,
-                        "The interpolation type (%s) of the vertex output at location %u is not "
-                        "supported in compatibility mode",
-                        vertexOutputInfo.interpolationType, i);
-
-        DAWN_INVALID_IF(device->IsCompatibilityMode() &&
-                            vertexOutputInfo.interpolationSampling == InterpolationSampling::Sample,
-                        "The interpolation sampling (%s) of the vertex output at location %u is "
-                        "not supported in compatibility mode",
-                        vertexOutputInfo.interpolationSampling, i);
     }
 
     return {};
diff --git a/src/dawn/tests/unittests/validation/CompatValidationTests.cpp b/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
index 3313b26..fec272f 100644
--- a/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
@@ -235,6 +235,7 @@
 
 TEST_F(CompatValidationTest, CanNotUseShaderWithUnsupportedInterpolateTypeOrSampling) {
     static const char* interpolateParams[] = {
+        "perspective",  // should pass
         "linear",
         "perspective, sample",
     };
@@ -250,43 +251,15 @@
                 v.color = vec4f(1);
                 return v;
             }
-            @fragment fn fsWithoutBadInterpolationUsage() -> @location(0) vec4f {
-                return vec4f(1);
-            }
-            @fragment fn fsWithBadInterpolationUsage1(v: Vertex) -> @location(0) vec4f {
-                return vec4f(1);
-            }
-            @fragment fn fsWithBadInterpolationUsage2(v: Vertex) -> @location(0) vec4f {
-                return v.pos;
-            }
-            @fragment fn fsWithBadInterpolationUsage3(v: Vertex) -> @location(0) vec4f {
-                return v.color;
-            }
         )",
                                     interpolateParam);
-        wgpu::ShaderModule moduleInterpolationLinear =
-            utils::CreateShaderModule(device, wgsl.c_str());
-
-        static const char* entryPoints[] = {
-            "fsWithoutBadInterpolationUsage",
-            "fsWithBadInterpolationUsage1",
-            "fsWithBadInterpolationUsage2",
-            "fsWithBadInterpolationUsage3",
-        };
-        for (auto entryPoint : entryPoints) {
-            utils::ComboRenderPipelineDescriptor descriptor;
-            descriptor.vertex.module = moduleInterpolationLinear;
-            descriptor.cFragment.module = moduleInterpolationLinear;
-            descriptor.cFragment.entryPoint = entryPoint;
-
-            bool shouldSucceed = entryPoint == entryPoints[0];
-
-            if (shouldSucceed) {
-                device.CreateRenderPipeline(&descriptor);
-            } else {
-                ASSERT_DEVICE_ERROR(device.CreateRenderPipeline(&descriptor),
-                                    testing::HasSubstr("in compatibility mode"));
-            }
+        if (strcmp(interpolateParam, "perspective") == 0) {
+            wgpu::ShaderModule moduleInterpolationLinear =
+                utils::CreateShaderModule(device, wgsl.c_str());
+        } else {
+            ASSERT_DEVICE_ERROR(wgpu::ShaderModule moduleInterpolationLinear =
+                                    utils::CreateShaderModule(device, wgsl.c_str()),
+                                testing::HasSubstr("in compatibility mode"));
         }
     }
 }
diff --git a/src/tint/lang/wgsl/resolver/compatibility_mode_test.cc b/src/tint/lang/wgsl/resolver/compatibility_mode_test.cc
index 49b96a6..758fa8d 100644
--- a/src/tint/lang/wgsl/resolver/compatibility_mode_test.cc
+++ b/src/tint/lang/wgsl/resolver/compatibility_mode_test.cc
@@ -179,5 +179,96 @@
         R"(12:34 error: use of '@builtin(sample_index)' is not allowed in compatibility mode)");
 }
 
+TEST_F(ResolverCompatibilityModeTest, LinearInterpolation_Parameter) {
+    // @fragment
+    // fn main(@location(1) @interpolate(linear) value : f32) {
+    // }
+
+    Func("main",
+         Vector{Param("value", ty.f32(),
+                      Vector{
+                          Location(1_i),
+                          Interpolate(Source{{12, 34}}, core::InterpolationType::kLinear,
+                                      core::InterpolationSampling::kCenter),
+                      })},
+         ty.void_(), Empty,
+         Vector{
+             Stage(ast::PipelineStage::kFragment),
+         },
+         Vector{
+             Builtin(core::BuiltinValue::kPosition),
+         });
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(),
+              R"(12:34 error: use of '@interpolate(linear)' is not allowed in compatibility mode)");
+}
+
+TEST_F(ResolverCompatibilityModeTest, LinearInterpolation_StructMember) {
+    // struct S {
+    //   @location(1) @interpolate(linear) value : f32,
+    // }
+
+    Structure("S", Vector{
+                       Member("value", ty.f32(),
+                              Vector{
+                                  Location(1_i),
+                                  Interpolate(Source{{12, 34}}, core::InterpolationType::kLinear,
+                                              core::InterpolationSampling::kCenter),
+                              }),
+                   });
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(r()->error(),
+              R"(12:34 error: use of '@interpolate(linear)' is not allowed in compatibility mode)");
+}
+
+TEST_F(ResolverCompatibilityModeTest, SampleInterpolation_Parameter) {
+    // @fragment
+    // fn main(@location(1) @interpolate(perspective, sample) value : f32) {
+    // }
+
+    Func("main",
+         Vector{Param("value", ty.f32(),
+                      Vector{
+                          Location(1_i),
+                          Interpolate(Source{{12, 34}}, core::InterpolationType::kPerspective,
+                                      core::InterpolationSampling::kSample),
+                      })},
+         ty.void_(), Empty,
+         Vector{
+             Stage(ast::PipelineStage::kFragment),
+         },
+         Vector{
+             Builtin(core::BuiltinValue::kPosition),
+         });
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(
+        r()->error(),
+        R"(12:34 error: use of '@interpolate(..., sample)' is not allowed in compatibility mode)");
+}
+
+TEST_F(ResolverCompatibilityModeTest, SampleInterpolation_StructMember) {
+    // struct S {
+    //   @location(1) @interpolate(perspective, sample) value : f32,
+    // }
+
+    Structure("S",
+              Vector{
+                  Member("value", ty.f32(),
+                         Vector{
+                             Location(1_i),
+                             Interpolate(Source{{12, 34}}, core::InterpolationType::kPerspective,
+                                         core::InterpolationSampling::kSample),
+                         }),
+              });
+
+    EXPECT_FALSE(r()->Resolve());
+    EXPECT_EQ(
+        r()->error(),
+        R"(12:34 error: use of '@interpolate(..., sample)' is not allowed in compatibility mode)");
+}
+
 }  // namespace
 }  // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 2f9951d..a19c181 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -1120,6 +1120,22 @@
         return false;
     }
 
+    if (mode_ == wgsl::ValidationMode::kCompat) {
+        if (i_type->Value() == core::InterpolationType::kLinear) {
+            AddError(attr->source)
+                << "use of '@interpolate(linear)' is not allowed in compatibility mode";
+            return false;
+        }
+
+        if (attr->sampling) {
+            auto s_type = sem_.AsInterpolationSampling(sem_.Get(attr->sampling));
+            if (s_type->Value() == core::InterpolationSampling::kSample) {
+                AddError(attr->source)
+                    << "use of '@interpolate(..., sample)' is not allowed in compatibility mode";
+                return false;
+            }
+        }
+    }
     return true;
 }