[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;
|
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
|
// Converts a SPIR-V opcode to its corresponding AST binary opcode, if any
|
||||||
// @param opcode SPIR-V opcode
|
// @param opcode SPIR-V opcode
|
||||||
// @returns the AST binary op for the given opcode, or kNone
|
// @returns the AST binary op for the given opcode, or kNone
|
||||||
|
@ -2649,6 +2668,16 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
||||||
arg0.type);
|
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) {
|
if (opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) {
|
||||||
return MakeAccessChain(inst);
|
return MakeAccessChain(inst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1279,10 +1279,198 @@ TEST_F(SpvFUnordTest, Select_VecBoolCond_VectorParams) {
|
||||||
})")) << ToString(fe.ast_body());
|
})")) << ToString(fe.ast_body());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dneto): OpAny - likely builtin function TBD
|
using SpvLogicalTest = SpvParserTestBase<::testing::Test>;
|
||||||
// TODO(dneto): OpAll - likely builtin function TBD
|
|
||||||
// TODO(dneto): OpIsNan - likely builtin function TBD
|
TEST_F(SpvLogicalTest, Any) {
|
||||||
// TODO(dneto): OpIsInf - likely builtin function TBD
|
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): Kernel-guarded instructions.
|
||||||
// TODO(dneto): OpSelect over more general types, as in SPIR-V 1.4
|
// TODO(dneto): OpSelect over more general types, as in SPIR-V 1.4
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue