GLSL: special-case BinaryOp::kModulo for floating point.

The '%' operator in GLSL is integer-only. Use the full OpFRem
expression: (a - b * trunc(a / b)).

Bug: tint:1270
Change-Id: I0a969983bef132e004ce456d4a738488e400a61b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68760
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 6d6eda3..29d172c 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -372,6 +372,66 @@
   return true;
 }
 
+bool GeneratorImpl::EmitFloatModulo(std::ostream& out,
+                                    const ast::BinaryExpression* expr) {
+  std::string fn;
+  auto* ret_ty = TypeOf(expr)->UnwrapRef();
+  fn = utils::GetOrCreate(float_modulo_funcs_, ret_ty, [&]() -> std::string {
+    TextBuffer b;
+    TINT_DEFER(helpers_.Append(b));
+
+    auto fn_name = UniqueIdentifier("tint_float_modulo");
+    std::vector<std::string> parameter_names;
+    {
+      auto decl = line(&b);
+      if (!EmitTypeAndName(decl, ret_ty, ast::StorageClass::kNone,
+                           ast::Access::kUndefined, fn_name)) {
+        return "";
+      }
+      {
+        ScopedParen sp(decl);
+        const auto* ty = TypeOf(expr->lhs)->UnwrapRef();
+        if (!EmitTypeAndName(decl, ty, ast::StorageClass::kNone,
+                             ast::Access::kUndefined, "lhs")) {
+          return "";
+        }
+        decl << ", ";
+        ty = TypeOf(expr->rhs)->UnwrapRef();
+        if (!EmitTypeAndName(decl, ty, ast::StorageClass::kNone,
+                             ast::Access::kUndefined, "rhs")) {
+          return "";
+        }
+      }
+      decl << " {";
+    }
+    {
+      ScopedIndent si(&b);
+      line(&b) << "return (lhs - rhs * trunc(lhs / rhs));";
+    }
+    line(&b) << "}";
+    line(&b);
+    return fn_name;
+  });
+
+  if (fn.empty()) {
+    return false;
+  }
+
+  // Call the helper
+  out << fn;
+  {
+    ScopedParen sp(out);
+    if (!EmitExpression(out, expr->lhs)) {
+      return false;
+    }
+    out << ", ";
+    if (!EmitExpression(out, expr->rhs)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 bool GeneratorImpl::EmitBinary(std::ostream& out,
                                const ast::BinaryExpression* expr) {
   if (IsRelational(expr->op) && !TypeOf(expr->lhs)->UnwrapRef()->is_scalar()) {
@@ -416,6 +476,12 @@
     return EmitBitwiseBoolOp(out, expr);
   }
 
+  if (expr->op == ast::BinaryOp::kModulo &&
+      (TypeOf(expr->lhs)->UnwrapRef()->is_float_scalar_or_vector() ||
+       TypeOf(expr->rhs)->UnwrapRef()->is_float_scalar_or_vector())) {
+    return EmitFloatModulo(out, expr);
+  }
+
   out << "(";
   if (!EmitExpression(out, expr->lhs)) {
     return false;
diff --git a/src/tint/writer/glsl/generator_impl.h b/src/tint/writer/glsl/generator_impl.h
index a01352f..61db755 100644
--- a/src/tint/writer/glsl/generator_impl.h
+++ b/src/tint/writer/glsl/generator_impl.h
@@ -82,6 +82,11 @@
   /// @param out the output of the expression stream
   /// @param expr the binary expression
   /// @returns true if the expression was emitted, false otherwise
+  bool EmitFloatModulo(std::ostream& out, const ast::BinaryExpression* expr);
+  /// Handles generating the modulo operator on float vector operands
+  /// @param out the output of the expression stream
+  /// @param expr the binary expression
+  /// @returns true if the expression was emitted, false otherwise
   bool EmitBinary(std::ostream& out, const ast::BinaryExpression* expr);
   /// Handles generating a bitcast expression
   /// @param out the output of the expression stream
@@ -503,6 +508,7 @@
   std::unordered_map<const sem::Struct*, std::string> structure_builders_;
   std::unordered_map<const sem::Vector*, std::string> dynamic_vector_write_;
   std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_;
+  std::unordered_map<const sem::Type*, std::string> float_modulo_funcs_;
   bool requires_oes_sample_variables_ = false;
   bool requires_default_precision_qualifier_ = false;
   Version version_;
diff --git a/src/tint/writer/glsl/generator_impl_binary_test.cc b/src/tint/writer/glsl/generator_impl_binary_test.cc
index 8420ade..ad11beb 100644
--- a/src/tint/writer/glsl/generator_impl_binary_test.cc
+++ b/src/tint/writer/glsl/generator_impl_binary_test.cc
@@ -40,7 +40,8 @@
   if (params.op == ast::BinaryOp::kAnd || params.op == ast::BinaryOp::kOr ||
       params.op == ast::BinaryOp::kXor ||
       params.op == ast::BinaryOp::kShiftLeft ||
-      params.op == ast::BinaryOp::kShiftRight) {
+      params.op == ast::BinaryOp::kShiftRight ||
+      params.op == ast::BinaryOp::kModulo) {
     return;
   }
 
@@ -260,6 +261,36 @@
 )");
 }
 
+TEST_F(GlslGeneratorImplTest_Binary, ModF32) {
+  Global("a", ty.f32(), ast::StorageClass::kPrivate);
+  Global("b", ty.f32(), ast::StorageClass::kPrivate);
+
+  auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr("a"),
+                                             Expr("b"));
+  WrapInFunction(expr);
+
+  GeneratorImpl& gen = Build();
+
+  std::stringstream out;
+  ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
+  EXPECT_EQ(out.str(), "tint_float_modulo(a, b)");
+}
+
+TEST_F(GlslGeneratorImplTest_Binary, ModVec3F32) {
+  Global("a", ty.vec3<f32>(), ast::StorageClass::kPrivate);
+  Global("b", ty.vec3<f32>(), ast::StorageClass::kPrivate);
+
+  auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr("a"),
+                                             Expr("b"));
+  WrapInFunction(expr);
+
+  GeneratorImpl& gen = Build();
+
+  std::stringstream out;
+  ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
+  EXPECT_EQ(out.str(), "tint_float_modulo(a, b)");
+}
+
 TEST_F(GlslGeneratorImplTest_Binary, Logical_Multi) {
   // (a && b) || (c || d)
   Global("a", ty.bool_(), ast::StorageClass::kPrivate);
diff --git a/test/tint/benchmark/animometer.wgsl.expected.glsl b/test/tint/benchmark/animometer.wgsl.expected.glsl
index e0d2486..2a44a68 100644
--- a/test/tint/benchmark/animometer.wgsl.expected.glsl
+++ b/test/tint/benchmark/animometer.wgsl.expected.glsl
@@ -1,7 +1,10 @@
-SKIP: FAILED
-
 #version 310 es
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) in vec4 position_1;
 layout(location = 1) in vec4 color_1;
 layout(location = 0) out vec4 v_color_1;
@@ -35,7 +38,7 @@
 };
 
 VertexOutput vert_main(vec4 position, vec4 color) {
-  float fade = ((uniforms.scalarOffset + ((time.value * uniforms.scalar) / 10.0f)) % 1.0f);
+  float fade = tint_float_modulo((uniforms.scalarOffset + ((time.value * uniforms.scalar) / 10.0f)), 1.0f);
   if ((fade < 0.5f)) {
     fade = (fade * 2.0f);
   } else {
@@ -62,13 +65,6 @@
   gl_Position.z = ((2.0f * gl_Position.z) - gl_Position.w);
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:36: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:36: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
 #version 310 es
 precision mediump float;
 
diff --git a/test/tint/bug/tint/948.wgsl.expected.glsl b/test/tint/bug/tint/948.wgsl.expected.glsl
index f62e60c..e5cd11e 100644
--- a/test/tint/bug/tint/948.wgsl.expected.glsl
+++ b/test/tint/bug/tint/948.wgsl.expected.glsl
@@ -1,8 +1,11 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 2) in vec2 tUV_param_1;
 layout(location = 5) in vec2 tileID_1_param_1;
 layout(location = 4) in vec2 levelUnits_param_1;
@@ -119,7 +122,7 @@
       if ((x_174 > 0.0f)) {
         float x_181 = x_20.time;
         float x_184 = animationData.z;
-        mt = ((x_181 * x_184) % 1.0f);
+        mt = tint_float_modulo((x_181 * x_184), 1.0f);
         f = 0.0f;
         {
           for(; (f < 8.0f); f = (f + 1.0f)) {
@@ -199,10 +202,3 @@
   glFragColor_1_1 = inner_result.glFragColor_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:120: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp mediump float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:120: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/builtins/gen/textureDimensions/ba1481.wgsl.expected.glsl b/test/tint/builtins/gen/textureDimensions/ba1481.wgsl.expected.glsl
index 8e05f60..da9e40c 100644
--- a/test/tint/builtins/gen/textureDimensions/ba1481.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/textureDimensions/ba1481.wgsl.expected.glsl
@@ -1,6 +1,6 @@
 SKIP: FAILED
 
-../../src/tint/writer/glsl/generator_impl.cc:2589 internal compiler error: Multiplanar external texture transform was not run.
+../../src/tint/writer/glsl/generator_impl.cc:2656 internal compiler error: Multiplanar external texture transform was not run.
 
 
 ********************************************************************
diff --git a/test/tint/builtins/gen/textureLoad/8acf41.wgsl.expected.glsl b/test/tint/builtins/gen/textureLoad/8acf41.wgsl.expected.glsl
index 8e05f60..da9e40c 100644
--- a/test/tint/builtins/gen/textureLoad/8acf41.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/textureLoad/8acf41.wgsl.expected.glsl
@@ -1,6 +1,6 @@
 SKIP: FAILED
 
-../../src/tint/writer/glsl/generator_impl.cc:2589 internal compiler error: Multiplanar external texture transform was not run.
+../../src/tint/writer/glsl/generator_impl.cc:2656 internal compiler error: Multiplanar external texture transform was not run.
 
 
 ********************************************************************
diff --git a/test/tint/builtins/gen/textureSampleLevel/979816.wgsl.expected.glsl b/test/tint/builtins/gen/textureSampleLevel/979816.wgsl.expected.glsl
index 8e05f60..da9e40c 100644
--- a/test/tint/builtins/gen/textureSampleLevel/979816.wgsl.expected.glsl
+++ b/test/tint/builtins/gen/textureSampleLevel/979816.wgsl.expected.glsl
@@ -1,6 +1,6 @@
 SKIP: FAILED
 
-../../src/tint/writer/glsl/generator_impl.cc:2589 internal compiler error: Multiplanar external texture transform was not run.
+../../src/tint/writer/glsl/generator_impl.cc:2656 internal compiler error: Multiplanar external texture transform was not run.
 
 
 ********************************************************************
diff --git a/test/tint/expressions/binary/mod/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod/scalar-scalar/f32.wgsl.expected.glsl
index 58ac79d..bf3ed5b 100644
--- a/test/tint/expressions/binary/mod/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,9 +1,12 @@
-SKIP: FAILED
-
 #version 310 es
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
-  float r = (1.0f % 2.0f);
+  float r = tint_float_modulo(1.0f, 2.0f);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -11,10 +14,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:4: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:4: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod/vec3-vec3/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod/vec3-vec3/f32.wgsl.expected.glsl
index 541db7f..99b1ce5 100644
--- a/test/tint/expressions/binary/mod/vec3-vec3/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod/vec3-vec3/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+vec3 tint_float_modulo(vec3 lhs, vec3 rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   vec3 a = vec3(1.0f, 2.0f, 3.0f);
   vec3 b = vec3(4.0f, 5.0f, 6.0f);
-  vec3 r = (a % b);
+  vec3 r = tint_float_modulo(a, b);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp 3-component vector of float' and a right operand of type ' temp highp 3-component vector of float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
index 7e7046a..fa3aedc 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,9 +1,12 @@
-SKIP: FAILED
-
 #version 310 es
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
-  float r = (1.0f % 0.0f);
+  float r = tint_float_modulo(1.0f, 0.0f);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -11,10 +14,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:4: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:4: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/f32.wgsl.expected.glsl
index 2152369..3b69dee 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_constant/vec3-vec3/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+vec3 tint_float_modulo(vec3 lhs, vec3 rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   vec3 a = vec3(1.0f, 2.0f, 3.0f);
   vec3 b = vec3(0.0f, 5.0f, 0.0f);
-  vec3 r = (a % b);
+  vec3 r = tint_float_modulo(a, b);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp 3-component vector of float' and a right operand of type ' temp highp 3-component vector of float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/f32.wgsl.expected.glsl
index 20e3ea5..d04fe1a 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   float a = 1.0f;
   float b = 0.0f;
-  float r = (a % (b + b));
+  float r = tint_float_modulo(a, (b + b));
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp float' and a right operand of type ' temp highp float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/f32.wgsl.expected.glsl
index 034903a..cf21005 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_expression/vec3-vec3/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+vec3 tint_float_modulo(vec3 lhs, vec3 rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   vec3 a = vec3(1.0f, 2.0f, 3.0f);
   vec3 b = vec3(0.0f, 5.0f, 0.0f);
-  vec3 r = (a % (b + b));
+  vec3 r = tint_float_modulo(a, (b + b));
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp 3-component vector of float' and a right operand of type ' temp highp 3-component vector of float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/f32.wgsl.expected.glsl
index 39c64fe..e768a19 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/scalar-scalar/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   float a = 1.0f;
   float b = 0.0f;
-  float r = (a % b);
+  float r = tint_float_modulo(a, b);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp float' and a right operand of type ' temp highp float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/f32.wgsl.expected.glsl b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/f32.wgsl.expected.glsl
index 2152369..3b69dee 100644
--- a/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/f32.wgsl.expected.glsl
+++ b/test/tint/expressions/binary/mod_by_zero/by_identifier/vec3-vec3/f32.wgsl.expected.glsl
@@ -1,11 +1,14 @@
-SKIP: FAILED
-
 #version 310 es
 
+vec3 tint_float_modulo(vec3 lhs, vec3 rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void f() {
   vec3 a = vec3(1.0f, 2.0f, 3.0f);
   vec3 b = vec3(0.0f, 5.0f, 0.0f);
-  vec3 r = (a % b);
+  vec3 r = tint_float_modulo(a, b);
 }
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
@@ -13,10 +16,3 @@
   f();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:6: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp highp 3-component vector of float' and a right operand of type ' temp highp 3-component vector of float' (or there is no acceptable conversion)
-ERROR: 0:6: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_0.spvasm.expected.glsl b/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_0.spvasm.expected.glsl
index 7b1c356..544c44d 100644
--- a/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_0.spvasm.expected.glsl
+++ b/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_0.spvasm.expected.glsl
@@ -1,10 +1,13 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void main_1() {
-  float x_1 = (50.0f % 60.0f);
+  float x_1 = tint_float_modulo(50.0f, 60.0f);
   return;
 }
 
@@ -16,10 +19,3 @@
   tint_symbol();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:5: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:5: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_1.spvasm.expected.glsl b/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_1.spvasm.expected.glsl
index 40f51bd..9154a88 100644
--- a/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_1.spvasm.expected.glsl
+++ b/test/tint/unittest/reader/spirv/SpvParserTest_FRem_SpvBinaryArithTest_EmitExpression_1.spvasm.expected.glsl
@@ -1,10 +1,13 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+vec2 tint_float_modulo(vec2 lhs, vec2 rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 void main_1() {
-  vec2 x_1 = (vec2(50.0f, 60.0f) % vec2(60.0f, 50.0f));
+  vec2 x_1 = tint_float_modulo(vec2(50.0f, 60.0f), vec2(60.0f, 50.0f));
   return;
 }
 
@@ -16,10 +19,3 @@
   tint_symbol();
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:5: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const 2-component vector of float' and a right operand of type ' const 2-component vector of float' (or there is no acceptable conversion)
-ERROR: 0:5: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl.expected.glsl
index abb8a2d..3d8eb49 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-apfloat-mod-zero/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<i32, 3>;
             ^^^^^^
@@ -11,6 +9,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   int el;
@@ -41,7 +44,7 @@
   float undefined = 0.0f;
   bool x_51 = false;
   bool x_52_phi = false;
-  undefined = (5.0f % 0.0f);
+  undefined = tint_float_modulo(5.0f, 0.0f);
   int x_10 = x_6.x_GLF_uniform_int_values[0].el;
   int x_11 = x_6.x_GLF_uniform_int_values[0].el;
   int x_12 = x_6.x_GLF_uniform_int_values[1].el;
@@ -82,10 +85,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:34: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:34: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-module-small-number/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-module-small-number/0-opt.wgsl.expected.glsl
index 4d69683..41ecdd6 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-module-small-number/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-apfloat-module-small-number/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-apfloat-module-small-number/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<i32, 2>;
             ^^^^^^
@@ -15,6 +13,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   int el;
@@ -43,7 +46,7 @@
   float f1 = 0.0f;
   bool x_72 = false;
   bool x_73_phi = false;
-  f0 = (10.0f % 0.000001f);
+  f0 = tint_float_modulo(10.0f, 0.000001f);
   s1 = 9.99999935e-39f;
   if ((s1 == 0.0f)) {
     s1 = 1.0f;
@@ -52,7 +55,7 @@
   bool x_71 = false;
   bool x_63_phi = false;
   bool x_72_phi = false;
-  f1 = (10.0f % s1);
+  f1 = tint_float_modulo(10.0f, s1);
   bool tint_tmp = isinf(f1);
   if (!tint_tmp) {
     tint_tmp = (s1 == 1.0f);
@@ -116,10 +119,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:32: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:32: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-const-folding-mod-one-one-lte/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-const-folding-mod-one-one-lte/0-opt.wgsl.expected.glsl
index 9835939..5a25470 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-const-folding-mod-one-one-lte/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-const-folding-mod-one-one-lte/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-const-folding-mod-one-one-lte/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<i32, 2>;
             ^^^^^^
@@ -7,6 +5,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   int el;
@@ -22,7 +25,7 @@
 } x_5;
 
 void main_1() {
-  if (((1.0f % 1.0f) <= 0.01f)) {
+  if ((tint_float_modulo(1.0f, 1.0f) <= 0.01f)) {
     int x_29 = x_5.x_GLF_uniform_int_values[0].el;
     int x_32 = x_5.x_GLF_uniform_int_values[0].el;
     int x_35 = x_5.x_GLF_uniform_int_values[1].el;
@@ -50,10 +53,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:19: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' const float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:19: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-acos-undefined/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-acos-undefined/0-opt.wgsl.expected.glsl
index d67ac88..ab6472c 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-acos-undefined/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-acos-undefined/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-acos-undefined/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<i32, 2>;
             ^^^^^^
@@ -11,6 +9,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   int el;
@@ -45,7 +48,7 @@
   int x_13 = x_5.x_GLF_uniform_int_values[0].el;
   x_GLF_color = vec4(float(x_10), float(x_11), float(x_12), float(x_13));
   float x_45 = x_8.x_GLF_uniform_float_values[1].el;
-  a = (x_45 % uintBitsToFloat(0x7f800000u));
+  a = tint_float_modulo(x_45, uintBitsToFloat(0x7f800000u));
   float x_47 = a;
   float x_49 = x_8.x_GLF_uniform_float_values[0].el;
   if ((x_47 != x_49)) {
@@ -70,10 +73,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:38: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp mediump float' and a right operand of type ' global highp float' (or there is no acceptable conversion)
-ERROR: 0:38: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-sqrt-undefined/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-sqrt-undefined/0-opt.wgsl.expected.glsl
index 35c15b0..0223216 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-sqrt-undefined/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-sqrt-undefined/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-instruction-simplify-mod-sqrt-undefined/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<i32, 2>;
             ^^^^^^
@@ -11,6 +9,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   int el;
@@ -45,7 +48,7 @@
   int x_13 = x_5.x_GLF_uniform_int_values[0].el;
   x_GLF_color = vec4(float(x_10), float(x_11), float(x_12), float(x_13));
   float x_45 = x_8.x_GLF_uniform_float_values[1].el;
-  a = (uintBitsToFloat(0xff800000u) % x_45);
+  a = tint_float_modulo(uintBitsToFloat(0xff800000u), x_45);
   float x_47 = a;
   float x_49 = x_8.x_GLF_uniform_float_values[0].el;
   if ((x_47 != x_49)) {
@@ -70,10 +73,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:38: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' global highp float' and a right operand of type ' temp mediump float' (or there is no acceptable conversion)
-ERROR: 0:38: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-mod-uint-bits-float/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-mod-uint-bits-float/0-opt.wgsl.expected.glsl
index e5bc8a0..ba0e9ee 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-mod-uint-bits-float/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-mod-uint-bits-float/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-mod-uint-bits-float/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<f32, 3>;
             ^^^^^^
@@ -7,6 +5,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   float el;
@@ -23,7 +26,7 @@
 
 void main_1() {
   float a = 0.0f;
-  a = (uintBitsToFloat(1u) % 1.0f);
+  a = tint_float_modulo(uintBitsToFloat(1u), 1.0f);
   float x_29 = x_6.x_GLF_uniform_float_values[1].el;
   x_GLF_color = vec4(x_29, x_29, x_29, x_29);
   float x_31 = a;
@@ -53,10 +56,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:20: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' global highp float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:20: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/cov-simplify-modulo-1/0-opt.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/cov-simplify-modulo-1/0-opt.wgsl.expected.glsl
index 97fce96..8a54fbb 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/cov-simplify-modulo-1/0-opt.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/cov-simplify-modulo-1/0-opt.wgsl.expected.glsl
@@ -1,5 +1,3 @@
-SKIP: FAILED
-
 vk-gl-cts/graphicsfuzz/cov-simplify-modulo-1/0-opt.wgsl:1:13 warning: use of deprecated language feature: the @stride attribute is deprecated; use a larger type if necessary
 type Arr = @stride(16) array<f32, 2>;
             ^^^^^^
@@ -11,6 +9,11 @@
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct tint_padded_array_element {
   float el;
@@ -40,7 +43,7 @@
 void main_1() {
   float a = 0.0f;
   float x_30 = x_6.x_GLF_uniform_float_values[0].el;
-  a = (x_30 % 1.0f);
+  a = tint_float_modulo(x_30, 1.0f);
   float x_32 = a;
   float x_34 = x_6.x_GLF_uniform_float_values[0].el;
   if ((x_32 == x_34)) {
@@ -71,10 +74,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:33: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp mediump float' and a right operand of type ' const float' (or there is no acceptable conversion)
-ERROR: 0:33: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-float-mat-determinant-clamp/0.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-float-mat-determinant-clamp/0.wgsl.expected.glsl
index 1a4f5d2..6f9d51c 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-float-mat-determinant-clamp/0.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-float-mat-determinant-clamp/0.wgsl.expected.glsl
@@ -1,8 +1,11 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct buf0 {
   vec2 resolution;
@@ -26,7 +29,7 @@
       } else {
         int x_122 = i;
         float x_124 = thirty_two;
-        if (((float(x_122) % round(x_124)) <= 0.01f)) {
+        if ((tint_float_modulo(float(x_122), round(x_124)) <= 0.01f)) {
           result = (result + 100.0f);
         }
       }
@@ -97,10 +100,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:27: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp float' and a right operand of type ' global mediump float' (or there is no acceptable conversion)
-ERROR: 0:27: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-injected-conditional-true/1.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-injected-conditional-true/1.wgsl.expected.glsl
index 9d3977b..33401ed 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-injected-conditional-true/1.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-injected-conditional-true/1.wgsl.expected.glsl
@@ -1,8 +1,11 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct buf0 {
   vec2 resolution;
@@ -34,7 +37,7 @@
       } else {
         int x_136 = i;
         float x_138 = thirty_two;
-        if (((float(x_136) % round(x_138)) <= 0.01f)) {
+        if ((tint_float_modulo(float(x_136), round(x_138)) <= 0.01f)) {
           result = (result + 100.0f);
         }
       }
@@ -113,10 +116,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:35: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp float' and a right operand of type ' global mediump float' (or there is no acceptable conversion)
-ERROR: 0:35: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-true-conditional-simple-loop/1.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-true-conditional-simple-loop/1.wgsl.expected.glsl
index 257f592..c21996e 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-true-conditional-simple-loop/1.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-true-conditional-simple-loop/1.wgsl.expected.glsl
@@ -1,8 +1,11 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct buf0 {
   vec2 resolution;
@@ -34,7 +37,7 @@
       } else {
         int x_155 = i;
         float x_157 = thirty_two;
-        if (((float(x_155) % round(x_157)) <= 0.01f)) {
+        if ((tint_float_modulo(float(x_155), round(x_157)) <= 0.01f)) {
           result = (result + 100.0f);
         }
       }
@@ -129,10 +132,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:35: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp float' and a right operand of type ' global mediump float' (or there is no acceptable conversion)
-ERROR: 0:35: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-
diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-vec3-values-from-matrix/1.wgsl.expected.glsl b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-vec3-values-from-matrix/1.wgsl.expected.glsl
index c04d2ac..c07062a 100644
--- a/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-vec3-values-from-matrix/1.wgsl.expected.glsl
+++ b/test/tint/vk-gl-cts/graphicsfuzz/stable-colorgrid-modulo-vec3-values-from-matrix/1.wgsl.expected.glsl
@@ -1,8 +1,11 @@
-SKIP: FAILED
-
 #version 310 es
 precision mediump float;
 
+float tint_float_modulo(float lhs, float rhs) {
+  return (lhs - rhs * trunc(lhs / rhs));
+}
+
+
 layout(location = 0) out vec4 x_GLF_color_1_1;
 struct buf0 {
   vec2 resolution;
@@ -26,7 +29,7 @@
       } else {
         int x_147 = i;
         float x_149 = thirty_two;
-        if (((float(x_147) % round(x_149)) <= 0.01f)) {
+        if ((tint_float_modulo(float(x_147), round(x_149)) <= 0.01f)) {
           result = (result + 100.0f);
         }
       }
@@ -102,10 +105,3 @@
   x_GLF_color_1_1 = inner_result.x_GLF_color_1;
   return;
 }
-Error parsing GLSL shader:
-ERROR: 0:27: '%' :  wrong operand types: no operation '%' exists that takes a left-hand operand of type ' temp float' and a right operand of type ' global mediump float' (or there is no acceptable conversion)
-ERROR: 0:27: '' : compilation terminated 
-ERROR: 2 compilation errors.  No code generated.
-
-
-