[spirv-reader] Support OpAny, OpAll, OpIsInf, OpIsNan
Bug: tint:3, tint:121 Change-Id: I1a6a2d45684c28a0e03ad4b208dc6b2f737da694 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/25422 Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
e3de74fd2b
commit
b6f0299964
|
@ -191,6 +191,25 @@ bool GetUnaryOp(SpvOp opcode, ast::UnaryOp* ast_unary_op) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Converts a SPIR-V opcode for a WGSL builtin function, if there is a
|
||||
/// direct translation. Returns nullptr otherwise.
|
||||
/// @returns the WGSL builtin function name for the given opcode, or nullptr.
|
||||
const char* GetUnaryBuiltInFunctionName(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpAny:
|
||||
return "any";
|
||||
case SpvOpAll:
|
||||
return "all";
|
||||
case SpvOpIsNan:
|
||||
return "is_nan";
|
||||
case SpvOpIsInf:
|
||||
return "is_inf";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Converts a SPIR-V opcode to its corresponding AST binary opcode, if any
|
||||
// @param opcode SPIR-V opcode
|
||||
// @returns the AST binary op for the given opcode, or kNone
|
||||
|
@ -2649,6 +2668,16 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
|||
arg0.type);
|
||||
}
|
||||
|
||||
const char* unary_builtin_name = GetUnaryBuiltInFunctionName(opcode);
|
||||
if (unary_builtin_name != nullptr) {
|
||||
ast::ExpressionList params;
|
||||
params.emplace_back(MakeOperand(inst, 0).expr);
|
||||
return {ast_type,
|
||||
std::make_unique<ast::CallExpression>(
|
||||
std::make_unique<ast::IdentifierExpression>(unary_builtin_name),
|
||||
std::move(params))};
|
||||
}
|
||||
|
||||
if (opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) {
|
||||
return MakeAccessChain(inst);
|
||||
}
|
||||
|
|
|
@ -1279,10 +1279,198 @@ TEST_F(SpvFUnordTest, Select_VecBoolCond_VectorParams) {
|
|||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
// TODO(dneto): OpAny - likely builtin function TBD
|
||||
// TODO(dneto): OpAll - likely builtin function TBD
|
||||
// TODO(dneto): OpIsNan - likely builtin function TBD
|
||||
// TODO(dneto): OpIsInf - likely builtin function TBD
|
||||
using SpvLogicalTest = SpvParserTestBase<::testing::Test>;
|
||||
|
||||
TEST_F(SpvLogicalTest, Any) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpAny %bool %v2bool_t_f
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{any}
|
||||
(
|
||||
TypeConstructor{
|
||||
__vec_2__bool
|
||||
ScalarConstructor{true}
|
||||
ScalarConstructor{false}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
TEST_F(SpvLogicalTest, All) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpAll %bool %v2bool_t_f
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{all}
|
||||
(
|
||||
TypeConstructor{
|
||||
__vec_2__bool
|
||||
ScalarConstructor{true}
|
||||
ScalarConstructor{false}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
TEST_F(SpvLogicalTest, IsNan_Scalar) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpIsNan %bool %float_50
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{is_nan}
|
||||
(
|
||||
ScalarConstructor{50.000000}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
TEST_F(SpvLogicalTest, IsNan_Vector) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpIsNan %v2bool %v2float_50_60
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__vec_2__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{is_nan}
|
||||
(
|
||||
TypeConstructor{
|
||||
__vec_2__f32
|
||||
ScalarConstructor{50.000000}
|
||||
ScalarConstructor{60.000000}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
TEST_F(SpvLogicalTest, IsInf_Scalar) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpIsInf %bool %float_50
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{is_inf}
|
||||
(
|
||||
ScalarConstructor{50.000000}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
TEST_F(SpvLogicalTest, IsInf_Vector) {
|
||||
const auto assembly = CommonTypes() + R"(
|
||||
%100 = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
%1 = OpIsInf %v2bool %v2float_50_60
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
auto* p = parser(test::Assemble(assembly));
|
||||
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
|
||||
FunctionEmitter fe(p, *spirv_function(100));
|
||||
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(VariableDeclStatement{
|
||||
Variable{
|
||||
x_1
|
||||
none
|
||||
__vec_2__bool
|
||||
{
|
||||
Call{
|
||||
Identifier{is_inf}
|
||||
(
|
||||
TypeConstructor{
|
||||
__vec_2__f32
|
||||
ScalarConstructor{50.000000}
|
||||
ScalarConstructor{60.000000}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})")) << ToString(fe.ast_body());
|
||||
}
|
||||
|
||||
// TODO(dneto): Kernel-guarded instructions.
|
||||
// TODO(dneto): OpSelect over more general types, as in SPIR-V 1.4
|
||||
|
||||
|
|
Loading…
Reference in New Issue