mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-13 00:26:00 +00:00
Spec change: https://github.com/gpuweb/gpuweb/pull/2427 Reverses: tint:867 This reverts and fixes commits: b6fdcc54df6e012578e69550788e2b4b2b611c32 10442eff7db4271d53eed553795e655068488276 Added a bunch of end-to-end tests. Fixed: tint:1352 Change-Id: I34968243bbec1cab838c8ba50a6f027146bbfd06 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/75401 Reviewed-by: David Neto <dneto@google.com> Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
1076 lines
33 KiB
C++
1076 lines
33 KiB
C++
// Copyright 2020 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "src/reader/spirv/function.h"
|
|
#include "src/reader/spirv/parser_impl_test_helper.h"
|
|
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
|
|
|
namespace tint {
|
|
namespace reader {
|
|
namespace spirv {
|
|
namespace {
|
|
|
|
using ::testing::Eq;
|
|
using ::testing::HasSubstr;
|
|
|
|
std::string Caps() {
|
|
return R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical Simple
|
|
OpEntryPoint GLCompute %100 "main"
|
|
OpExecutionMode %100 LocalSize 1 1 1
|
|
)";
|
|
}
|
|
|
|
std::string CommonTypes() {
|
|
return R"(
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
|
|
%uint = OpTypeInt 32 0
|
|
%int = OpTypeInt 32 1
|
|
%float = OpTypeFloat 32
|
|
|
|
%uint_10 = OpConstant %uint 10
|
|
%uint_20 = OpConstant %uint 20
|
|
%uint_1 = OpConstant %uint 1
|
|
%uint_3 = OpConstant %uint 3
|
|
%uint_4 = OpConstant %uint 4
|
|
%uint_5 = OpConstant %uint 5
|
|
%int_1 = OpConstant %int 1
|
|
%int_30 = OpConstant %int 30
|
|
%int_40 = OpConstant %int 40
|
|
%float_50 = OpConstant %float 50
|
|
%float_60 = OpConstant %float 60
|
|
%float_70 = OpConstant %float 70
|
|
|
|
%v2uint = OpTypeVector %uint 2
|
|
%v3uint = OpTypeVector %uint 3
|
|
%v4uint = OpTypeVector %uint 4
|
|
%v2int = OpTypeVector %int 2
|
|
%v2float = OpTypeVector %float 2
|
|
|
|
%m3v2float = OpTypeMatrix %v2float 3
|
|
%m3v2float_0 = OpConstantNull %m3v2float
|
|
|
|
%s_v2f_u_i = OpTypeStruct %v2float %uint %int
|
|
%a_u_5 = OpTypeArray %uint %uint_5
|
|
|
|
%v2uint_3_4 = OpConstantComposite %v2uint %uint_3 %uint_4
|
|
%v2uint_4_3 = OpConstantComposite %v2uint %uint_4 %uint_3
|
|
%v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60
|
|
%v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50
|
|
%v2float_70_70 = OpConstantComposite %v2float %float_70 %float_70
|
|
)";
|
|
}
|
|
|
|
std::string Preamble() {
|
|
return Caps() + CommonTypes();
|
|
}
|
|
|
|
using SpvParserTest_Composite_Construct = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_Composite_Construct, Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeConstruct %v2uint %uint_10 %uint_20
|
|
%2 = OpCompositeConstruct %v2int %int_30 %int_40
|
|
%3 = OpCompositeConstruct %v2float %float_50 %float_60
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr(R"(let x_1 : vec2<u32> = vec2<u32>(10u, 20u);
|
|
let x_2 : vec2<i32> = vec2<i32>(30, 40);
|
|
let x_3 : vec2<f32> = vec2<f32>(50.0, 60.0);
|
|
)"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_Composite_Construct, Matrix) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeConstruct %m3v2float %v2float_50_60 %v2float_60_50 %v2float_70_70
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_1 : mat3x2<f32> = mat3x2<f32>("
|
|
"vec2<f32>(50.0, 60.0), "
|
|
"vec2<f32>(60.0, 50.0), "
|
|
"vec2<f32>(70.0, 70.0));"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_Composite_Construct, Array) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeConstruct %a_u_5 %uint_10 %uint_20 %uint_3 %uint_4 %uint_5
|
|
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();
|
|
EXPECT_THAT(
|
|
test::ToString(p->program(), ast_body),
|
|
HasSubstr(
|
|
"let x_1 : array<u32, 5u> = array<u32, 5u>(10u, 20u, 3u, 4u, 5u);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_Composite_Construct, Struct) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeConstruct %s_v2f_u_i %v2float_50_60 %uint_5 %int_30
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_1 : S = S(vec2<f32>(50.0, 60.0), 5u, 30);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_Composite_Construct,
|
|
ConstantComposite_Struct_NoDeduplication) {
|
|
const auto assembly = Preamble() + R"(
|
|
%200 = OpTypeStruct %uint
|
|
%300 = OpTypeStruct %uint ; isomorphic structures
|
|
|
|
%201 = OpConstantComposite %200 %uint_10
|
|
%301 = OpConstantComposite %300 %uint_10 ; isomorphic constants
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%2 = OpCopyObject %200 %201
|
|
%3 = OpCopyObject %300 %301
|
|
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 got = test::ToString(p->program(), ast_body);
|
|
const auto expected = std::string(
|
|
R"(let x_2 : S_1 = S_1(10u);
|
|
let x_3 : S_2 = S_2(10u);
|
|
return;
|
|
)");
|
|
EXPECT_EQ(got, expected) << got;
|
|
}
|
|
|
|
using SpvParserTest_CompositeExtract = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeExtract %float %v2float_50_60 1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_1 : f32 = vec2<f32>(50.0, 60.0).y;"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Vector_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeExtract %float %v2float_50_60 900
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeExtract %1 index value 900 is out of bounds for vector "
|
|
"of 2 elements");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Matrix) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %v2float %1 2
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_2 : vec2<f32> = x_1[2u];"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Matrix_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %v2float %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeExtract %2 index value 3 is out of bounds for matrix "
|
|
"of 3 elements");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Matrix_Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %float %1 2 1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_2 : f32 = x_1[2u].y;"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Array) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %a_u_5
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %a_u_5 %var
|
|
%2 = OpCompositeExtract %uint %1 3
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_2 : u32 = x_1[3u];"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, RuntimeArray_IsError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%rtarr = OpTypeRuntimeArray %uint
|
|
%ptr = OpTypePointer Function %rtarr
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %rtarr %var
|
|
%2 = OpCompositeExtract %uint %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(),
|
|
HasSubstr("can't do OpCompositeExtract on a runtime array: "));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Struct) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %s_v2f_u_i
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s_v2f_u_i %var
|
|
%2 = OpCompositeExtract %int %1 2
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_2 : i32 = x_1.field2;"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Struct_DifferOnlyInMemberName) {
|
|
const std::string assembly = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical Simple
|
|
OpEntryPoint Fragment %100 "main"
|
|
OpExecutionMode %100 OriginUpperLeft
|
|
|
|
OpMemberName %s0 0 "algo"
|
|
OpMemberName %s1 0 "rithm"
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
|
|
%uint = OpTypeInt 32 0
|
|
|
|
%s0 = OpTypeStruct %uint
|
|
%s1 = OpTypeStruct %uint
|
|
%ptr0 = OpTypePointer Function %s0
|
|
%ptr1 = OpTypePointer Function %s1
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var0 = OpVariable %ptr0 Function
|
|
%var1 = OpVariable %ptr1 Function
|
|
%1 = OpLoad %s0 %var0
|
|
%2 = OpCompositeExtract %uint %1 0
|
|
%3 = OpLoad %s1 %var1
|
|
%4 = OpCompositeExtract %uint %3 0
|
|
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 got = fe.ast_body();
|
|
auto program = p->program();
|
|
EXPECT_THAT(test::ToString(program, got),
|
|
HasSubstr("let x_2 : u32 = x_1.algo;"))
|
|
<< test::ToString(program, got);
|
|
EXPECT_THAT(test::ToString(program, got),
|
|
HasSubstr("let x_4 : u32 = x_3.rithm;"))
|
|
<< test::ToString(program, got);
|
|
p->SkipDumpingPending("crbug.com/tint/863");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Struct_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %s_v2f_u_i
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s_v2f_u_i %var
|
|
%2 = OpCompositeExtract %int %1 40
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeExtract %2 index value 40 is out of bounds for "
|
|
"structure %27 having 3 members");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Struct_Array_Matrix_Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%a_mat = OpTypeArray %m3v2float %uint_3
|
|
%s = OpTypeStruct %uint %a_mat
|
|
%ptr = OpTypePointer Function %s
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s %var
|
|
%2 = OpCompositeExtract %float %1 1 2 0 1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_2 : f32 = x_1.field1[2u][0u].y;"));
|
|
}
|
|
|
|
using SpvParserTest_CompositeInsert = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeInsert %v2float %float_70 %v2float_50_60 1
|
|
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();
|
|
auto got = test::ToString(p->program(), ast_body);
|
|
const auto* expected =
|
|
R"(var x_1_1 : vec2<f32> = vec2<f32>(50.0, 60.0);
|
|
x_1_1.y = 70.0;
|
|
let x_1 : vec2<f32> = x_1_1;
|
|
return;
|
|
)";
|
|
EXPECT_EQ(got, expected);
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Vector_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCompositeInsert %v2float %float_70 %v2float_50_60 900
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeInsert %1 index value 900 is out of bounds for vector "
|
|
"of 2 elements");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Matrix) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeInsert %m3v2float %v2float_50_60 %1 2
|
|
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();
|
|
auto body_str = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(body_str, HasSubstr(R"(var x_2_1 : mat3x2<f32> = x_1;
|
|
x_2_1[2u] = vec2<f32>(50.0, 60.0);
|
|
let x_2 : mat3x2<f32> = x_2_1;
|
|
)")) << body_str;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Matrix_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeInsert %m3v2float %v2float_50_60 %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeInsert %2 index value 3 is out of bounds for matrix of "
|
|
"3 elements");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Matrix_Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeInsert %m3v2float %v2float_50_60 %1 2
|
|
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();
|
|
auto body_str = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(body_str, HasSubstr(R"(var x_2_1 : mat3x2<f32> = x_1;
|
|
x_2_1[2u] = vec2<f32>(50.0, 60.0);
|
|
let x_2 : mat3x2<f32> = x_2_1;
|
|
return;
|
|
)")) << body_str;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Array) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %a_u_5
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %a_u_5 %var
|
|
%2 = OpCompositeInsert %a_u_5 %uint_20 %1 3
|
|
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();
|
|
auto body_str = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(body_str, HasSubstr(R"(var x_2_1 : array<u32, 5u> = x_1;
|
|
x_2_1[3u] = 20u;
|
|
let x_2 : array<u32, 5u> = x_2_1;
|
|
)")) << body_str;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, RuntimeArray_IsError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%rtarr = OpTypeRuntimeArray %uint
|
|
%ptr = OpTypePointer Function %rtarr
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %rtarr %var
|
|
%2 = OpCompositeInsert %rtarr %uint_20 %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(),
|
|
HasSubstr("can't do OpCompositeInsert on a runtime array: "));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Struct) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %s_v2f_u_i
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s_v2f_u_i %var
|
|
%2 = OpCompositeInsert %s_v2f_u_i %int_30 %1 2
|
|
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();
|
|
auto body_str = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(body_str, HasSubstr(R"(var x_36 : S;
|
|
let x_1 : S = x_36;
|
|
var x_2_1 : S = x_1;
|
|
x_2_1.field2 = 30;
|
|
let x_2 : S = x_2_1;
|
|
)")) << body_str;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Struct_DifferOnlyInMemberName) {
|
|
const std::string assembly = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical Simple
|
|
OpEntryPoint Fragment %100 "main"
|
|
OpExecutionMode %100 OriginUpperLeft
|
|
|
|
OpName %var0 "var0"
|
|
OpName %var1 "var1"
|
|
OpMemberName %s0 0 "algo"
|
|
OpMemberName %s1 0 "rithm"
|
|
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
|
|
%uint = OpTypeInt 32 0
|
|
%uint_10 = OpConstant %uint 10
|
|
%uint_11 = OpConstant %uint 11
|
|
|
|
%s0 = OpTypeStruct %uint
|
|
%s1 = OpTypeStruct %uint
|
|
%ptr0 = OpTypePointer Function %s0
|
|
%ptr1 = OpTypePointer Function %s1
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var0 = OpVariable %ptr0 Function
|
|
%var1 = OpVariable %ptr1 Function
|
|
%1 = OpLoad %s0 %var0
|
|
%2 = OpCompositeInsert %s0 %uint_10 %1 0
|
|
%3 = OpLoad %s1 %var1
|
|
%4 = OpCompositeInsert %s1 %uint_11 %3 0
|
|
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 got = test::ToString(p->program(), ast_body);
|
|
const std::string expected = R"(var var0 : S;
|
|
var var1 : S_1;
|
|
let x_1 : S = var0;
|
|
var x_2_1 : S = x_1;
|
|
x_2_1.algo = 10u;
|
|
let x_2 : S = x_2_1;
|
|
let x_3 : S_1 = var1;
|
|
var x_4_1 : S_1 = x_3;
|
|
x_4_1.rithm = 11u;
|
|
let x_4 : S_1 = x_4_1;
|
|
return;
|
|
)";
|
|
EXPECT_EQ(got, expected) << got;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Struct_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %s_v2f_u_i
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s_v2f_u_i %var
|
|
%2 = OpCompositeInsert %s_v2f_u_i %uint_10 %1 40
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_EQ(p->error(),
|
|
"OpCompositeInsert %2 index value 40 is out of bounds for "
|
|
"structure %27 having 3 members");
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeInsert, Struct_Array_Matrix_Vector) {
|
|
const auto assembly = Preamble() + R"(
|
|
%a_mat = OpTypeArray %m3v2float %uint_3
|
|
%s = OpTypeStruct %uint %a_mat
|
|
%ptr = OpTypePointer Function %s
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%var = OpVariable %ptr Function
|
|
%1 = OpLoad %s %var
|
|
%2 = OpCompositeInsert %s %float_70 %1 1 2 0 1
|
|
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();
|
|
auto body_str = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(body_str, HasSubstr(R"(var x_38 : S_1;
|
|
let x_1 : S_1 = x_38;
|
|
var x_2_1 : S_1 = x_1;
|
|
x_2_1.field1[2u][0u].y = 70.0;
|
|
let x_2 : S_1 = x_2_1;
|
|
)")) << body_str;
|
|
}
|
|
|
|
using SpvParserTest_CopyObject = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_CopyObject, Scalar) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %uint %uint_3
|
|
%2 = OpCopyObject %uint %1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr(R"(let x_1 : u32 = 3u;
|
|
let x_2 : u32 = x_1;
|
|
)"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CopyObject, Pointer) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %uint
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%10 = OpVariable %ptr Function
|
|
%1 = OpCopyObject %ptr %10
|
|
%2 = OpCopyObject %ptr %1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr(R"(let x_1 : ptr<function, u32> = &(x_10);
|
|
let x_2 : ptr<function, u32> = x_1;
|
|
)"));
|
|
}
|
|
|
|
using SpvParserTest_VectorShuffle = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_VectorShuffle, FunctionScopeOperands_UseBoth) {
|
|
// Note that variables are generated for the vector operands.
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
|
%2 = OpIAdd %v2uint %v2uint_4_3 %v2uint_3_4
|
|
%10 = OpVectorShuffle %v4uint %1 %2 3 2 1 0
|
|
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();
|
|
EXPECT_THAT(
|
|
test::ToString(p->program(), ast_body),
|
|
HasSubstr(
|
|
"let x_10 : vec4<u32> = vec4<u32>(x_2.y, x_2.x, x_1.y, x_1.x);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_UseBoth) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%10 = OpVectorShuffle %v4uint %v2uint_3_4 %v2uint_4_3 3 2 1 0
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_10 : vec4<u32> = vec4<u32>("
|
|
"vec2<u32>(4u, 3u).y, "
|
|
"vec2<u32>(4u, 3u).x, "
|
|
"vec2<u32>(3u, 4u).y, "
|
|
"vec2<u32>(3u, 4u).x);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_VectorShuffle, ConstantOperands_AllOnesMapToNull) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_4_3
|
|
%10 = OpVectorShuffle %v2uint %1 %1 0xFFFFFFFF 1
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_10 : vec2<u32> = vec2<u32>(0u, x_1.y);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_VectorShuffle,
|
|
FunctionScopeOperands_MixedInputOperandSizes) {
|
|
// Note that variables are generated for the vector operands.
|
|
const auto assembly = Preamble() + R"(
|
|
%v3uint_3_4_5 = OpConstantComposite %v3uint %uint_3 %uint_4 %uint_5
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
|
%3 = OpCopyObject %v3uint %v3uint_3_4_5
|
|
%10 = OpVectorShuffle %v2uint %1 %3 1 4
|
|
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();
|
|
EXPECT_THAT(test::ToString(p->program(), ast_body),
|
|
HasSubstr("let x_10 : vec2<u32> = vec2<u32>(x_1.y, x_3.z);"));
|
|
}
|
|
|
|
TEST_F(SpvParserTest_VectorShuffle, IndexTooBig_IsError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%10 = OpVectorShuffle %v4uint %v2uint_3_4 %v2uint_4_3 9 2 1 0
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(),
|
|
Eq("invalid vectorshuffle ID %10: index too large: 9"));
|
|
}
|
|
|
|
using SpvParserTest_VectorExtractDynamic = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_VectorExtractDynamic, SignedIndex) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
|
%2 = OpCopyObject %int %int_1
|
|
%10 = OpVectorExtractDynamic %uint %1 %2
|
|
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 got = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(got, HasSubstr("let x_10 : u32 = x_1[x_2];")) << got;
|
|
}
|
|
|
|
TEST_F(SpvParserTest_VectorExtractDynamic, UnsignedIndex) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
|
%2 = OpCopyObject %uint %uint_1
|
|
%10 = OpVectorExtractDynamic %uint %1 %2
|
|
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 got = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(got, HasSubstr("let x_10 : u32 = x_1[x_2];")) << got;
|
|
}
|
|
|
|
using SpvParserTest_VectorInsertDynamic = SpvParserTest;
|
|
|
|
TEST_F(SpvParserTest_VectorInsertDynamic, Sample) {
|
|
const auto assembly = Preamble() + R"(
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
|
%2 = OpCopyObject %uint %uint_3
|
|
%3 = OpCopyObject %int %int_1
|
|
%10 = OpVectorInsertDynamic %v2uint %1 %2 %3
|
|
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 got = test::ToString(p->program(), ast_body);
|
|
EXPECT_THAT(got, HasSubstr(R"(var x_10_1 : vec2<u32> = x_1;
|
|
x_10_1[x_3] = x_2;
|
|
let x_10 : vec2<u32> = x_10_1;
|
|
)")) << got
|
|
<< assembly;
|
|
}
|
|
|
|
TEST_F(SpvParserTest, DISABLED_WorkgroupSize_Overridable) {
|
|
// TODO(dneto): Support specializable workgroup size. crbug.com/tint/504
|
|
const auto* assembly = R"(
|
|
OpCapability Shader
|
|
OpMemoryModel Logical Simple
|
|
OpEntryPoint GLCompute %100 "main"
|
|
OpDecorate %1 BuiltIn WorkgroupSize
|
|
OpDecorate %uint_2 SpecId 0
|
|
OpDecorate %uint_4 SpecId 1
|
|
OpDecorate %uint_8 SpecId 2
|
|
|
|
%uint = OpTypeInt 32 0
|
|
%uint_2 = OpSpecConstant %uint 2
|
|
%uint_4 = OpSpecConstant %uint 4
|
|
%uint_8 = OpSpecConstant %uint 8
|
|
%v3uint = OpTypeVector %uint 3
|
|
%1 = OpSpecConstantComposite %v3uint %uint_2 %uint_4 %uint_8
|
|
%void = OpTypeVoid
|
|
%voidfn = OpTypeFunction %void
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%10 = OpCopyObject %v3uint %1
|
|
%11 = OpCopyObject %uint %uint_2
|
|
%12 = OpCopyObject %uint %uint_4
|
|
%13 = OpCopyObject %uint %uint_8
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
auto p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
auto fe = p->function_emitter(100);
|
|
EXPECT_TRUE(fe.Emit()) << p->error();
|
|
const auto got = test::ToString(p->program());
|
|
EXPECT_THAT(got, HasSubstr(R"(
|
|
VariableConst{
|
|
Decorations{
|
|
OverrideDecoration{0}
|
|
}
|
|
x_2
|
|
none
|
|
__u32
|
|
{
|
|
ScalarConstructor[not set]{2}
|
|
}
|
|
}
|
|
VariableConst{
|
|
Decorations{
|
|
OverrideDecoration{1}
|
|
}
|
|
x_3
|
|
none
|
|
__u32
|
|
{
|
|
ScalarConstructor[not set]{4}
|
|
}
|
|
}
|
|
VariableConst{
|
|
Decorations{
|
|
OverrideDecoration{2}
|
|
}
|
|
x_4
|
|
none
|
|
__u32
|
|
{
|
|
ScalarConstructor[not set]{8}
|
|
}
|
|
}
|
|
)")) << got;
|
|
EXPECT_THAT(got, HasSubstr(R"(
|
|
VariableDeclStatement{
|
|
VariableConst{
|
|
x_10
|
|
none
|
|
__vec_3__u32
|
|
{
|
|
TypeConstructor[not set]{
|
|
__vec_3__u32
|
|
ScalarConstructor[not set]{2}
|
|
ScalarConstructor[not set]{4}
|
|
ScalarConstructor[not set]{8}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
VariableConst{
|
|
x_11
|
|
none
|
|
__u32
|
|
{
|
|
Identifier[not set]{x_2}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
VariableConst{
|
|
x_12
|
|
none
|
|
__u32
|
|
{
|
|
Identifier[not set]{x_3}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
VariableConst{
|
|
x_13
|
|
none
|
|
__u32
|
|
{
|
|
Identifier[not set]{x_4}
|
|
}
|
|
}
|
|
})"))
|
|
<< got << assembly;
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace spirv
|
|
} // namespace reader
|
|
} // namespace tint
|