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>
This commit is contained in:
Ben Clayton 2021-04-16 10:43:34 +00:00 committed by Commit Bot service account
parent 434cd396fe
commit 98b084e4a4
2 changed files with 91 additions and 0 deletions

View File

@ -442,6 +442,24 @@ semantic::IntrinsicType GetIntrinsic(SpvOp opcode) {
return semantic::IntrinsicType::kReverseBits; return semantic::IntrinsicType::kReverseBits;
case SpvOpDot: case SpvOpDot:
return semantic::IntrinsicType::kDot; 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: default:
break; break;
} }

View File

@ -1478,6 +1478,79 @@ TEST_F(SpvBinaryArithTestBasic, OuterProduct) {
<< got; << 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 // TODO(dneto): OpSRem. Missing from WGSL
// https://github.com/gpuweb/gpuweb/issues/702 // https://github.com/gpuweb/gpuweb/issues/702