spirv/reader: Implement derivative intrinsics
Fixed: tint:719
Change-Id: Iaa5e44a574b2843f4f6f9264b8baa8d199acd70f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/47770
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Alan Baker <alanbaker@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index d31e56d..6e73457 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -442,6 +442,24 @@
return semantic::IntrinsicType::kReverseBits;
case SpvOpDot:
return semantic::IntrinsicType::kDot;
+ case SpvOpDPdx:
+ return semantic::IntrinsicType::kDpdx;
+ case SpvOpDPdy:
+ return semantic::IntrinsicType::kDpdy;
+ case SpvOpFwidth:
+ return semantic::IntrinsicType::kFwidth;
+ case SpvOpDPdxFine:
+ return semantic::IntrinsicType::kDpdxFine;
+ case SpvOpDPdyFine:
+ return semantic::IntrinsicType::kDpdyFine;
+ case SpvOpFwidthFine:
+ return semantic::IntrinsicType::kFwidthFine;
+ case SpvOpDPdxCoarse:
+ return semantic::IntrinsicType::kDpdxCoarse;
+ case SpvOpDPdyCoarse:
+ return semantic::IntrinsicType::kDpdyCoarse;
+ case SpvOpFwidthCoarse:
+ return semantic::IntrinsicType::kFwidthCoarse;
default:
break;
}
diff --git a/src/reader/spirv/function_arithmetic_test.cc b/src/reader/spirv/function_arithmetic_test.cc
index 5d0fdfc..9ff8fba 100644
--- a/src/reader/spirv/function_arithmetic_test.cc
+++ b/src/reader/spirv/function_arithmetic_test.cc
@@ -1478,6 +1478,79 @@
<< got;
}
+struct IntrinsicData {
+ const std::string spirv;
+ const std::string wgsl;
+};
+inline std::ostream& operator<<(std::ostream& out, IntrinsicData data) {
+ out << "OpData{" << data.spirv << "," << data.wgsl << "}";
+ return out;
+}
+struct ArgAndTypeData {
+ const std::string spirv_type;
+ const std::string spirv_arg;
+ const std::string ast_type;
+};
+inline std::ostream& operator<<(std::ostream& out, ArgAndTypeData data) {
+ out << "ArgAndTypeData{" << data.spirv_type << "," << data.spirv_arg << ","
+ << data.ast_type << "}";
+ return out;
+}
+
+using SpvBinaryDerivativeTest = SpvParserTestBase<
+ ::testing::TestWithParam<std::tuple<IntrinsicData, ArgAndTypeData>>>;
+
+TEST_P(SpvBinaryDerivativeTest, Derivatives) {
+ auto& intrinsic = std::get<0>(GetParam());
+ auto& arg = std::get<1>(GetParam());
+
+ const auto assembly = CommonTypes() + R"(
+ %100 = OpFunction %void None %voidfn
+ %entry = OpLabel
+ %1 = OpCopyObject %)" +
+ arg.spirv_type + " %" + arg.spirv_arg + R"(
+ %2 = )" + intrinsic.spirv +
+ " %" + arg.spirv_type + R"( %1
+ OpReturn
+ OpFunctionEnd
+)";
+ auto p = parser(test::Assemble(assembly));
+ ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
+ FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
+ EXPECT_TRUE(fe.EmitBody()) << p->error();
+ EXPECT_THAT(ToString(p->builder(), fe.ast_body()), HasSubstr(R"(VariableConst{
+ x_2
+ none
+ )" + arg.ast_type + R"(
+ {
+ Call[not set]{
+ Identifier[not set]{)" + intrinsic.wgsl + R"(}
+ (
+ Identifier[not set]{x_1}
+ )
+ }
+ }
+ })"));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SpvBinaryDerivativeTest,
+ SpvBinaryDerivativeTest,
+ testing::Combine(
+ ::testing::Values(IntrinsicData{"OpDPdx", "dpdx"},
+ IntrinsicData{"OpDPdy", "dpdy"},
+ IntrinsicData{"OpFwidth", "fwidth"},
+ IntrinsicData{"OpDPdxFine", "dpdxFine"},
+ IntrinsicData{"OpDPdyFine", "dpdyFine"},
+ IntrinsicData{"OpFwidthFine", "fwidthFine"},
+ IntrinsicData{"OpDPdxCoarse", "dpdxCoarse"},
+ IntrinsicData{"OpDPdyCoarse", "dpdyCoarse"},
+ IntrinsicData{"OpFwidthCoarse", "fwidthCoarse"}),
+ ::testing::Values(
+ ArgAndTypeData{"float", "float_50", "__f32"},
+ ArgAndTypeData{"v2float", "v2float_50_60", "__vec_2__f32"},
+ ArgAndTypeData{"v3float", "v3float_50_60_70", "__vec_3__f32"})));
+
// TODO(dneto): OpSRem. Missing from WGSL
// https://github.com/gpuweb/gpuweb/issues/702