spirv-reader: support GLSL.std.450 instruction FindILsb

Fixed: tint:1057
Change-Id: Iacaefb9d634b60745f163061424090b041fccc68
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/104901
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: David Neto <dneto@google.com>
Commit-Queue: David Neto <dneto@google.com>
This commit is contained in:
David Neto 2022-10-11 21:47:41 +00:00 committed by Dawn LUCI CQ
parent 2ad747dedd
commit 542d27d874
3 changed files with 74 additions and 2 deletions

View File

@ -327,6 +327,8 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
return "exp2";
case GLSLstd450FaceForward:
return "faceForward";
case GLSLstd450FindILsb:
return "firstTrailingBit";
case GLSLstd450Floor:
return "floor";
case GLSLstd450Fma:
@ -427,7 +429,6 @@ std::string GetGlslStd450FuncName(uint32_t ext_opcode) {
case GLSLstd450PackDouble2x32:
case GLSLstd450UnpackDouble2x32:
case GLSLstd450FindILsb:
case GLSLstd450FindSMsb:
case GLSLstd450FindUMsb:

View File

@ -179,6 +179,8 @@ using SpvParserTest_GlslStd450_Inting_IntingInting =
SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
using SpvParserTest_GlslStd450_Inting_IntingIntingInting =
SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
using SpvParserTest_GlslStd450_Uinting_Uinting =
SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
using SpvParserTest_GlslStd450_Uinting_UintingUinting =
SpvParserTestBase<::testing::TestWithParam<GlslStd450Case>>;
using SpvParserTest_GlslStd450_Uinting_UintingUintingUinting =
@ -580,7 +582,8 @@ TEST_P(SpvParserTest_GlslStd450_Inting_IntingIntingInting, Vector) {
INSTANTIATE_TEST_SUITE_P(Samples,
SpvParserTest_GlslStd450_Inting_Inting,
::testing::Values(GlslStd450Case{"SAbs", "abs"}));
::testing::Values(GlslStd450Case{"SAbs", "abs"},
GlslStd450Case{"FindILsb", "firstTrailingBit"}));
INSTANTIATE_TEST_SUITE_P(Samples,
SpvParserTest_GlslStd450_Inting_IntingInting,
@ -591,6 +594,41 @@ INSTANTIATE_TEST_SUITE_P(Samples,
SpvParserTest_GlslStd450_Inting_IntingIntingInting,
::testing::Values(GlslStd450Case{"SClamp", "clamp"}));
TEST_P(SpvParserTest_GlslStd450_Uinting_Uinting, Scalar) {
const auto assembly = Preamble() + R"(
%1 = OpExtInst %uint %glsl )" +
GetParam().opcode +
R"( %u1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
const auto body = test::ToString(p->program(), ast_body);
EXPECT_THAT(body, HasSubstr("let x_1 : u32 = " + GetParam().wgsl_func + "(u1);")) << body;
}
TEST_P(SpvParserTest_GlslStd450_Uinting_Uinting, Vector) {
const auto assembly = Preamble() + R"(
%1 = OpExtInst %v2uint %glsl )" +
GetParam().opcode +
R"( %v2u1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
const auto body = test::ToString(p->program(), ast_body);
EXPECT_THAT(body, HasSubstr("let x_1 : vec2<u32> = " + GetParam().wgsl_func + "(v2u1);"))
<< body;
}
TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUinting, Scalar) {
const auto assembly = Preamble() + R"(
%1 = OpExtInst %uint %glsl )" +
@ -661,6 +699,10 @@ TEST_P(SpvParserTest_GlslStd450_Uinting_UintingUintingUinting, Vector) {
<< body;
}
INSTANTIATE_TEST_SUITE_P(Samples,
SpvParserTest_GlslStd450_Uinting_Uinting,
::testing::Values(GlslStd450Case{"FindILsb", "firstTrailingBit"}));
INSTANTIATE_TEST_SUITE_P(Samples,
SpvParserTest_GlslStd450_Uinting_UintingUinting,
::testing::Values(GlslStd450Case{"UMax", "max"},
@ -907,6 +949,34 @@ TEST_F(SpvParserTest, RectifyOperandsAndResult_UClamp) {
<< body;
}
TEST_F(SpvParserTest, RectifyOperandsAndResult_FindILsb) {
// Check conversion of:
// signed results to unsigned result to match first arg.
// unsigned results to signed result to match first arg.
// This is the first extended instruction we've supported which goes both
// ways.
const auto assembly = Preamble() + R"(
%1 = OpExtInst %uint %glsl FindILsb %i1
%2 = OpExtInst %v2uint %glsl FindILsb %v2i1
%3 = OpExtInst %int %glsl FindILsb %u1
%4 = OpExtInst %v2int %glsl FindILsb %v2u1
OpReturn
OpFunctionEnd
)";
auto p = parser(test::Assemble(assembly));
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
auto fe = p->function_emitter(100);
EXPECT_TRUE(fe.EmitBody()) << p->error();
auto ast_body = fe.ast_body();
const auto body = test::ToString(p->program(), ast_body);
EXPECT_THAT(body, HasSubstr(R"(
let x_1 : u32 = bitcast<u32>(firstTrailingBit(i1));
let x_2 : vec2<u32> = bitcast<vec2<u32>>(firstTrailingBit(v2i1));
let x_3 : i32 = bitcast<i32>(firstTrailingBit(u1));
let x_4 : vec2<i32> = bitcast<vec2<i32>>(firstTrailingBit(v2u1));)"))
<< body;
}
struct DataPackingCase {
std::string opcode;
std::string wgsl_func;

View File

@ -221,6 +221,7 @@ bool AssumesResultSignednessMatchesFirstOperand(GLSLstd450 extended_opcode) {
case GLSLstd450UMin:
case GLSLstd450UMax:
case GLSLstd450UClamp:
case GLSLstd450FindILsb:
// TODO(dneto): FindSMsb?
// TODO(dneto): FindUMsb?
return true;