spirv-reader: ignore RelaxedPrecision on struct members

Bug: tint:737
Change-Id: Ic9a37e70ad1e6c1aa49aa49fe37a842361e306e1
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53440
Auto-Submit: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/reader/spirv/function_var_test.cc b/src/reader/spirv/function_var_test.cc
index c2ba7ec..114dfd9 100644
--- a/src/reader/spirv/function_var_test.cc
+++ b/src/reader/spirv/function_var_test.cc
@@ -72,15 +72,21 @@
   )";
 }
 
-// Returns the SPIR-V assembly for a vertex shader, optionally
-// with OpName decorations for certain SPIR-V IDs
-std::string PreambleNames(std::vector<std::string> ids) {
+// Returns the SPIR-V assembly for capabilities, the memory model,
+// a vertex shader entry point declaration, and name declarations
+// for specified IDs.
+std::string Caps(std::vector<std::string> ids = {}) {
   return R"(
     OpCapability Shader
     OpMemoryModel Logical Simple
     OpEntryPoint Vertex %100 "main"
-)" + Names(ids) +
-         CommonTypes();
+)" + Names(ids);
+}
+
+// Returns the SPIR-V assembly for a vertex shader, optionally
+// with OpName decorations for certain SPIR-V IDs
+std::string PreambleNames(std::vector<std::string> ids) {
+  return Caps(ids) + CommonTypes();
 }
 
 std::string Preamble() {
@@ -681,6 +687,77 @@
 }
 
 TEST_F(SpvParserFunctionVarTest,
+       EmitFunctionVariables_Decorate_RelaxedPrecision) {
+  // RelaxedPrecisionis dropped
+  auto p = parser(test::Assemble(Caps({"myvar"}) + R"(
+     OpDecorate %myvar RelaxedPrecision
+
+     %float = OpTypeFloat 32
+     %ptr = OpTypePointer Function %float
+
+     %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+     %100 = OpFunction %void None %voidfn
+     %entry = OpLabel
+     %myvar = OpVariable %ptr Function
+     OpReturn
+     OpFunctionEnd
+  )"));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
+  auto fe = p->function_emitter(100);
+  EXPECT_TRUE(fe.EmitFunctionVariables());
+
+  const auto got = ToString(p->builder(), fe.ast_body());
+  EXPECT_EQ(got, R"(VariableDeclStatement{
+  Variable{
+    myvar
+    none
+    undefined
+    __f32
+  }
+}
+)") << got;
+}
+
+TEST_F(SpvParserFunctionVarTest,
+       EmitFunctionVariables_MemberDecorate_RelaxedPrecision) {
+  // RelaxedPrecisionis dropped
+  const auto assembly = Caps({"myvar", "strct"}) + R"(
+     OpMemberDecorate %strct 0 RelaxedPrecision
+
+     %float = OpTypeFloat 32
+     %strct = OpTypeStruct %float
+     %ptr = OpTypePointer Function %strct
+
+     %void = OpTypeVoid
+     %voidfn = OpTypeFunction %void
+
+     %100 = OpFunction %void None %voidfn
+     %entry = OpLabel
+     %myvar = OpVariable %ptr Function
+     OpReturn
+     OpFunctionEnd
+  )";
+  auto p = parser(test::Assemble(assembly));
+  ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions())
+      << assembly << p->error() << std::endl;
+  auto fe = p->function_emitter(100);
+  EXPECT_TRUE(fe.EmitFunctionVariables());
+
+  const auto got = ToString(p->builder(), fe.ast_body());
+  EXPECT_EQ(got, R"(VariableDeclStatement{
+  Variable{
+    myvar
+    none
+    undefined
+    __type_name_strct
+  }
+}
+)") << got;
+}
+
+TEST_F(SpvParserFunctionVarTest,
        EmitStatement_CombinatorialValue_Defer_UsedOnceSameConstruct) {
   auto assembly = Preamble() + R"(
      %100 = OpFunction %void None %voidfn
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 9f6a865..70dd7eb 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -445,6 +445,9 @@
     case SpvDecorationColMajor:
       // WGSL only supports column major matrices.
       return nullptr;
+    case SpvDecorationRelaxedPrecision:
+      // WGSL doesn't support relaxed precision.
+      return nullptr;
     case SpvDecorationRowMajor:
       Fail() << "WGSL does not support row-major matrices: can't "
                 "translate member "
diff --git a/src/reader/spirv/parser_impl_convert_member_decoration_test.cc b/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
index bd77db4..01f29d4 100644
--- a/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
+++ b/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
@@ -61,6 +61,18 @@
   EXPECT_TRUE(p->error().empty());
 }
 
+TEST_F(SpvParserTest, ConvertMemberDecoration_RelaxedPrecision) {
+  // WGSL does not support relaxed precision. Drop it.
+  // It's functionally correct to use full precision f32 instead of
+  // relaxed precision f32.
+  auto p = parser(std::vector<uint32_t>{});
+
+  auto* result =
+      p->ConvertMemberDecoration(1, 1, {SpvDecorationRelaxedPrecision});
+  EXPECT_EQ(result, nullptr);
+  EXPECT_TRUE(p->error().empty());
+}
+
 TEST_F(SpvParserTest, ConvertMemberDecoration_UnhandledDecoration) {
   auto p = parser(std::vector<uint32_t>{});
 
diff --git a/src/reader/spirv/parser_impl_get_decorations_test.cc b/src/reader/spirv/parser_impl_get_decorations_test.cc
index bc0a88d..f70af99 100644
--- a/src/reader/spirv/parser_impl_get_decorations_test.cc
+++ b/src/reader/spirv/parser_impl_get_decorations_test.cc
@@ -98,6 +98,19 @@
   EXPECT_TRUE(p->error().empty());
 }
 
+TEST_F(SpvParserGetDecorationsTest, GetDecorationsForMember_RelaxedPrecision) {
+  auto p = parser(test::Assemble(R"(
+    OpMemberDecorate %10 0 RelaxedPrecision
+    %float = OpTypeFloat 32
+    %10 = OpTypeStruct %float
+  )"));
+  EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
+  auto decorations = p->GetDecorationsForMember(10, 0);
+  EXPECT_THAT(decorations,
+              UnorderedElementsAre(Decoration{SpvDecorationRelaxedPrecision}));
+  EXPECT_TRUE(p->error().empty());
+}
+
 // TODO(dneto): Enable when ArrayStride is handled
 TEST_F(SpvParserGetDecorationsTest,
        DISABLED_GetDecorationsForMember_OneDecoration) {