mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-19 13:03:43 +00:00
When a type alias is created, map the SPIR-V type ID to the type alias, not the underlying type. Only unpack the alias as needed when inspecting the content structure to make values. Bug: tint:3 Change-Id: I11011ddd190d89c81d3323f684a5e13f17dde09d Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23582 Reviewed-by: dan sinclair <dsinclair@google.com>
749 lines
20 KiB
C++
749 lines
20 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 <string>
|
|
#include <vector>
|
|
|
|
#include "gmock/gmock.h"
|
|
#include "src/reader/spirv/fail_stream.h"
|
|
#include "src/reader/spirv/function.h"
|
|
#include "src/reader/spirv/parser_impl.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 Preamble() {
|
|
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_3 = OpConstant %uint 3
|
|
%uint_4 = OpConstant %uint 4
|
|
%uint_5 = OpConstant %uint 5
|
|
%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
|
|
)";
|
|
}
|
|
|
|
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;
|
|
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__u32
|
|
{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{10}
|
|
ScalarConstructor{20}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
Variable{
|
|
x_2
|
|
none
|
|
__vec_2__i32
|
|
{
|
|
TypeConstructor{
|
|
__vec_2__i32
|
|
ScalarConstructor{30}
|
|
ScalarConstructor{40}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
Variable{
|
|
x_3
|
|
none
|
|
__vec_2__f32
|
|
{
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{50.000000}
|
|
ScalarConstructor{60.000000}
|
|
}
|
|
}
|
|
}
|
|
})")) << ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_1
|
|
none
|
|
__mat_2_3__f32
|
|
{
|
|
TypeConstructor{
|
|
__mat_2_3__f32
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{50.000000}
|
|
ScalarConstructor{60.000000}
|
|
}
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{60.000000}
|
|
ScalarConstructor{50.000000}
|
|
}
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{70.000000}
|
|
ScalarConstructor{70.000000}
|
|
}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_1
|
|
none
|
|
__array__u32_5
|
|
{
|
|
TypeConstructor{
|
|
__array__u32_5
|
|
ScalarConstructor{10}
|
|
ScalarConstructor{20}
|
|
ScalarConstructor{3}
|
|
ScalarConstructor{4}
|
|
ScalarConstructor{5}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_1
|
|
none
|
|
__alias_S__struct_S
|
|
{
|
|
TypeConstructor{
|
|
__alias_S__struct_S
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{50.000000}
|
|
ScalarConstructor{60.000000}
|
|
}
|
|
ScalarConstructor{5}
|
|
ScalarConstructor{30}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_1
|
|
none
|
|
__f32
|
|
{
|
|
MemberAccessor{
|
|
TypeConstructor{
|
|
__vec_2__f32
|
|
ScalarConstructor{50.000000}
|
|
ScalarConstructor{60.000000}
|
|
}
|
|
Identifier{y}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_THAT(p->error(), Eq("CompositeExtract %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
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %v2float %1 2
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_2
|
|
none
|
|
__vec_2__f32
|
|
{
|
|
ArrayAccessor{
|
|
Identifier{x_1}
|
|
ScalarConstructor{2}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Matrix_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %m3v2float
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %v2float %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(), Eq("CompositeExtract %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
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpLoad %m3v2float %var
|
|
%2 = OpCompositeExtract %float %1 2 1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_2
|
|
none
|
|
__f32
|
|
{
|
|
MemberAccessor{
|
|
ArrayAccessor{
|
|
Identifier{x_1}
|
|
ScalarConstructor{2}
|
|
}
|
|
Identifier{y}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Array) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %a_u_5
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpLoad %a_u_5 %var
|
|
%2 = OpCompositeExtract %uint %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_2
|
|
none
|
|
__u32
|
|
{
|
|
ArrayAccessor{
|
|
Identifier{x_1}
|
|
ScalarConstructor{3}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, RuntimeArray_IsError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%rtarr = OpTypeRuntimeArray %uint
|
|
%ptr = OpTypePointer Function %rtarr
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpLoad %rtarr %var
|
|
%2 = OpCompositeExtract %uint %1 3
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(), Eq("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
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_2
|
|
none
|
|
__i32
|
|
{
|
|
MemberAccessor{
|
|
Identifier{x_1}
|
|
Identifier{field2}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CompositeExtract, Struct_IndexTooBigError) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %s_v2f_u_i
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_FALSE(fe.EmitBody());
|
|
EXPECT_THAT(p->error(), Eq("CompositeExtract %2 index value 40 is out of "
|
|
"bounds for structure %25 having 3 elements"));
|
|
}
|
|
|
|
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
|
|
%var = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(
|
|
Variable{
|
|
x_2
|
|
none
|
|
__f32
|
|
{
|
|
MemberAccessor{
|
|
ArrayAccessor{
|
|
ArrayAccessor{
|
|
MemberAccessor{
|
|
Identifier{x_1}
|
|
Identifier{field1}
|
|
}
|
|
ScalarConstructor{2}
|
|
}
|
|
ScalarConstructor{0}
|
|
}
|
|
Identifier{y}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
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
|
|
__u32
|
|
{
|
|
ScalarConstructor{3}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
Variable{
|
|
x_2
|
|
none
|
|
__u32
|
|
{
|
|
Identifier{x_1}
|
|
}
|
|
}
|
|
})")) << ToString(fe.ast_body());
|
|
}
|
|
|
|
TEST_F(SpvParserTest_CopyObject, Pointer) {
|
|
const auto assembly = Preamble() + R"(
|
|
%ptr = OpTypePointer Function %uint
|
|
%10 = OpVariable %ptr Function
|
|
|
|
%100 = OpFunction %void None %voidfn
|
|
%entry = OpLabel
|
|
%1 = OpCopyObject %ptr %10
|
|
%2 = OpCopyObject %ptr %1
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
auto* p = parser(test::Assemble(assembly));
|
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
|
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
|
|
__ptr_function__u32
|
|
{
|
|
Identifier{x_10}
|
|
}
|
|
}
|
|
}
|
|
VariableDeclStatement{
|
|
Variable{
|
|
x_2
|
|
none
|
|
__ptr_function__u32
|
|
{
|
|
Identifier{x_1}
|
|
}
|
|
}
|
|
})")) << ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
|
|
x_10
|
|
none
|
|
__vec_4__u32
|
|
{
|
|
TypeConstructor{
|
|
__vec_4__u32
|
|
MemberAccessor{
|
|
Identifier{x_2}
|
|
Identifier{y}
|
|
}
|
|
MemberAccessor{
|
|
Identifier{x_2}
|
|
Identifier{x}
|
|
}
|
|
MemberAccessor{
|
|
Identifier{x_1}
|
|
Identifier{y}
|
|
}
|
|
MemberAccessor{
|
|
Identifier{x_1}
|
|
Identifier{x}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})")) << ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
|
|
x_10
|
|
none
|
|
__vec_4__u32
|
|
{
|
|
TypeConstructor{
|
|
__vec_4__u32
|
|
MemberAccessor{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{4}
|
|
ScalarConstructor{3}
|
|
}
|
|
Identifier{y}
|
|
}
|
|
MemberAccessor{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{4}
|
|
ScalarConstructor{3}
|
|
}
|
|
Identifier{x}
|
|
}
|
|
MemberAccessor{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{3}
|
|
ScalarConstructor{4}
|
|
}
|
|
Identifier{y}
|
|
}
|
|
MemberAccessor{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{3}
|
|
ScalarConstructor{4}
|
|
}
|
|
Identifier{x}
|
|
}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(ToString(fe.ast_body()), HasSubstr(R"(Variable{
|
|
x_10
|
|
none
|
|
__vec_2__u32
|
|
{
|
|
TypeConstructor{
|
|
__vec_2__u32
|
|
ScalarConstructor{0}
|
|
MemberAccessor{
|
|
Identifier{x_1}
|
|
Identifier{y}
|
|
}
|
|
}
|
|
}
|
|
})"))
|
|
<< ToString(fe.ast_body());
|
|
}
|
|
|
|
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;
|
|
FunctionEmitter fe(p, *spirv_function(100));
|
|
EXPECT_FALSE(fe.EmitBody()) << p->error();
|
|
EXPECT_THAT(p->error(),
|
|
Eq("invalid vectorshuffle ID %10: index too large: 9"));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace spirv
|
|
} // namespace reader
|
|
} // namespace tint
|