[spirv-reader] Test loop block order
Change-Id: If33d37d2813b1b1e584972d4da7aadbcb345d12f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20066 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
b5d518b68b
commit
8e8c291db1
|
@ -35,6 +35,7 @@ std::string CommonTypes() {
|
||||||
|
|
||||||
%bool = OpTypeBool
|
%bool = OpTypeBool
|
||||||
%cond = OpUndef %bool
|
%cond = OpUndef %bool
|
||||||
|
%cond2 = OpUndef %bool
|
||||||
|
|
||||||
%uint = OpTypeInt 32 0
|
%uint = OpTypeInt 32 0
|
||||||
%selector = OpUndef %uint
|
%selector = OpUndef %uint
|
||||||
|
@ -502,7 +503,7 @@ TEST_F(SpvParserTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SpvParserTest,
|
TEST_F(SpvParserTest,
|
||||||
ComputeBlockOrder_Nest_If_In_If) {
|
ComputeBlockOrder_Nest_If_Contains_If) {
|
||||||
auto assembly = CommonTypes() + R"(
|
auto assembly = CommonTypes() + R"(
|
||||||
%100 = OpFunction %void None %voidfn
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
@ -691,8 +692,466 @@ TEST_F(SpvParserTest,
|
||||||
<< assembly;
|
<< assembly;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(dneto): test nesting
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_Simple) {
|
||||||
// TODO(dneto): test loops
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
; The entry block can't be the target of a branch
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %20 None
|
||||||
|
OpBranchConditional %cond %20 %99
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_Infinite) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
; The entry block can't be the target of a branch
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %20 None
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_SingleBlock_DupInfinite) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
; The entry block can't be the target of a branch
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %20 None
|
||||||
|
OpBranchConditional %cond %20 %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_HeaderHasBreakIf) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99 ; like While
|
||||||
|
|
||||||
|
%30 = OpLabel ; trivial body
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_HeaderHasBreakUnless) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %99 %30 ; has break-unless
|
||||||
|
|
||||||
|
%30 = OpLabel ; trivial body
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreak) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %99 ; break
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreakIf) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %99 %40 ; break-if
|
||||||
|
|
||||||
|
%40 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasBreakUnless) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %40 %99 ; break-unless
|
||||||
|
|
||||||
|
%40 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasContinueIf) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %50 %40 ; continue-if
|
||||||
|
|
||||||
|
%40 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasContinueUnless) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %40 %50 ; continue-unless
|
||||||
|
|
||||||
|
%40 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 40, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_BodyHasSwitchContinueBreak) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpSwitch %selector %99 50 %50 ; default is break, 50 is continue
|
||||||
|
|
||||||
|
%40 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_Sequence) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranch %60
|
||||||
|
|
||||||
|
%60 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 60, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_ContainsIf) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpSelectionMerge %89 None
|
||||||
|
OpBranchConditional %cond2 %60 %70
|
||||||
|
|
||||||
|
%89 = OpLabel
|
||||||
|
OpBranch %20 ; backedge
|
||||||
|
|
||||||
|
%60 = OpLabel
|
||||||
|
OpBranch %89
|
||||||
|
|
||||||
|
%70 = OpLabel
|
||||||
|
OpBranch %89
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 60, 70, 89, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_HasBreakIf) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %99 %20
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_HasBreakUnless) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpBranchConditional %cond2 %20 %99
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ComputeBlockOrder_Loop_Continue_SwitchBreak) {
|
||||||
|
auto assembly = CommonTypes() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%10 = OpLabel
|
||||||
|
OpBranch %20
|
||||||
|
|
||||||
|
%20 = OpLabel
|
||||||
|
OpLoopMerge %99 %50 None
|
||||||
|
OpBranchConditional %cond %30 %99
|
||||||
|
|
||||||
|
%30 = OpLabel
|
||||||
|
OpBranch %50
|
||||||
|
|
||||||
|
%50 = OpLabel
|
||||||
|
OpSwitch %selector %20 99 %99 ; yes, this is obtuse but valid
|
||||||
|
|
||||||
|
%99 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
)";
|
||||||
|
auto* p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << p->error();
|
||||||
|
FunctionEmitter fe(p, *spirv_function(100));
|
||||||
|
fe.ComputeBlockOrderAndPositions();
|
||||||
|
|
||||||
|
EXPECT_THAT(fe.rspo(), ElementsAre(10, 20, 30, 50, 99)) << assembly;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
|
|
Loading…
Reference in New Issue