dawn-cmake/src/transform/vertex_pulling_transform_test.cc
dan sinclair 7156d3e314 [wgsl-reader] Add parsing of named structs.
This CL adds the parsing of structs with names. The parsing of type
aliased structs remains to allow for migration to the new system. The
named struct format is always emitted.

Bug: tint:175
Change-Id: Ic0579dedbd2dd0edc7dfd30bc2ec02972091e718
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/30341
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: David Neto <dneto@google.com>
2020-10-19 15:31:47 +00:00

1032 lines
24 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 "src/transform/vertex_pulling_transform.h"
#include "gtest/gtest.h"
#include "src/ast/decorated_variable.h"
#include "src/ast/function.h"
#include "src/ast/pipeline_stage.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/type/array_type.h"
#include "src/ast/type/f32_type.h"
#include "src/ast/type/i32_type.h"
#include "src/ast/type/void_type.h"
#include "src/type_determiner.h"
#include "src/validator.h"
namespace tint {
namespace transform {
namespace {
class VertexPullingTransformHelper {
public:
VertexPullingTransformHelper() {
mod_ = std::make_unique<ast::Module>();
transform_ = std::make_unique<VertexPullingTransform>(&ctx_, mod_.get());
}
// Create basic module with an entry point and vertex function
void InitBasicModule() {
auto func = std::make_unique<ast::Function>(
"main", ast::VariableList{},
ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>()));
func->add_decoration(
std::make_unique<ast::StageDecoration>(ast::PipelineStage ::kVertex));
mod()->AddFunction(std::move(func));
}
// Set up the transformation, after building the module
void InitTransform(VertexStateDescriptor vertex_state) {
EXPECT_TRUE(mod_->IsValid());
TypeDeterminer td(&ctx_, mod_.get());
EXPECT_TRUE(td.Determine());
transform_->SetVertexState(
std::make_unique<VertexStateDescriptor>(std::move(vertex_state)));
transform_->SetEntryPoint("main");
}
// Inserts a variable which will be converted to vertex pulling
void AddVertexInputVariable(uint32_t location,
std::string name,
ast::type::Type* type) {
auto var = std::make_unique<ast::DecoratedVariable>(
std::make_unique<ast::Variable>(name, ast::StorageClass::kInput, type));
ast::VariableDecorationList decorations;
decorations.push_back(std::make_unique<ast::LocationDecoration>(location));
var->set_decorations(std::move(decorations));
mod_->AddGlobalVariable(std::move(var));
}
Context* ctx() { return &ctx_; }
ast::Module* mod() { return mod_.get(); }
VertexPullingTransform* transform() { return transform_.get(); }
private:
Context ctx_;
std::unique_ptr<ast::Module> mod_;
std::unique_ptr<VertexPullingTransform> transform_;
};
class VertexPullingTransformTest : public VertexPullingTransformHelper,
public testing::Test {};
TEST_F(VertexPullingTransformTest, Error_NoVertexState) {
EXPECT_FALSE(transform()->Run());
EXPECT_EQ(transform()->error(), "SetVertexState not called");
}
TEST_F(VertexPullingTransformTest, Error_NoEntryPoint) {
transform()->SetVertexState(std::make_unique<VertexStateDescriptor>());
EXPECT_FALSE(transform()->Run());
EXPECT_EQ(transform()->error(), "Vertex stage entry point not found");
}
TEST_F(VertexPullingTransformTest, Error_InvalidEntryPoint) {
InitBasicModule();
InitTransform({});
transform()->SetEntryPoint("_");
EXPECT_FALSE(transform()->Run());
EXPECT_EQ(transform()->error(), "Vertex stage entry point not found");
}
TEST_F(VertexPullingTransformTest, Error_EntryPointWrongStage) {
auto func = std::make_unique<ast::Function>(
"main", ast::VariableList{},
ctx()->type_mgr().Get(std::make_unique<ast::type::VoidType>()));
func->add_decoration(
std::make_unique<ast::StageDecoration>(ast::PipelineStage::kFragment));
mod()->AddFunction(std::move(func));
InitTransform({});
EXPECT_FALSE(transform()->Run());
EXPECT_EQ(transform()->error(), "Vertex stage entry point not found");
}
TEST_F(VertexPullingTransformTest, BasicModule) {
InitBasicModule();
InitTransform({});
EXPECT_TRUE(transform()->Run());
}
TEST_F(VertexPullingTransformTest, OneAttribute) {
InitBasicModule();
ast::type::F32Type f32;
AddVertexInputVariable(0, "var_a", &f32);
InitTransform({{{4, InputStepMode::kVertex, {{VertexFormat::kF32, 0, 0}}}}});
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__f32
}
DecoratedVariable{
Decorations{
BuiltinDecoration{vertex_idx}
}
_tint_pulling_vertex_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{4}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
TEST_F(VertexPullingTransformTest, OneInstancedAttribute) {
InitBasicModule();
ast::type::F32Type f32;
AddVertexInputVariable(0, "var_a", &f32);
InitTransform(
{{{4, InputStepMode::kInstance, {{VertexFormat::kF32, 0, 0}}}}});
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__f32
}
DecoratedVariable{
Decorations{
BuiltinDecoration{instance_idx}
}
_tint_pulling_instance_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_instance_index}
multiply
ScalarConstructor{4}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
TEST_F(VertexPullingTransformTest, OneAttributeDifferentOutputSet) {
InitBasicModule();
ast::type::F32Type f32;
AddVertexInputVariable(0, "var_a", &f32);
InitTransform({{{4, InputStepMode::kVertex, {{VertexFormat::kF32, 0, 0}}}}});
transform()->SetPullingBufferBindingSet(5);
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__f32
}
DecoratedVariable{
Decorations{
BuiltinDecoration{vertex_idx}
}
_tint_pulling_vertex_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{5}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{4}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
// We expect the transform to use an existing builtin variables if it finds them
TEST_F(VertexPullingTransformTest, ExistingVertexIndexAndInstanceIndex) {
InitBasicModule();
ast::type::F32Type f32;
AddVertexInputVariable(0, "var_a", &f32);
AddVertexInputVariable(1, "var_b", &f32);
ast::type::I32Type i32;
{
auto vertex_index_var = std::make_unique<ast::DecoratedVariable>(
std::make_unique<ast::Variable>("custom_vertex_index",
ast::StorageClass::kInput, &i32));
ast::VariableDecorationList decorations;
decorations.push_back(
std::make_unique<ast::BuiltinDecoration>(ast::Builtin::kVertexIdx));
vertex_index_var->set_decorations(std::move(decorations));
mod()->AddGlobalVariable(std::move(vertex_index_var));
}
{
auto instance_index_var = std::make_unique<ast::DecoratedVariable>(
std::make_unique<ast::Variable>("custom_instance_index",
ast::StorageClass::kInput, &i32));
ast::VariableDecorationList decorations;
decorations.push_back(
std::make_unique<ast::BuiltinDecoration>(ast::Builtin::kInstanceIdx));
instance_index_var->set_decorations(std::move(decorations));
mod()->AddGlobalVariable(std::move(instance_index_var));
}
InitTransform(
{{{4, InputStepMode::kVertex, {{VertexFormat::kF32, 0, 0}}},
{4, InputStepMode::kInstance, {{VertexFormat::kF32, 0, 1}}}}});
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__f32
}
Variable{
var_b
private
__f32
}
DecoratedVariable{
Decorations{
BuiltinDecoration{vertex_idx}
}
custom_vertex_index
in
__i32
}
DecoratedVariable{
Decorations{
BuiltinDecoration{instance_idx}
}
custom_instance_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
DecoratedVariable{
Decorations{
BindingDecoration{1}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_1
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{custom_vertex_index}
multiply
ScalarConstructor{4}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{custom_instance_index}
multiply
ScalarConstructor{4}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_b}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_1}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
TEST_F(VertexPullingTransformTest, TwoAttributesSameBuffer) {
InitBasicModule();
ast::type::F32Type f32;
AddVertexInputVariable(0, "var_a", &f32);
ast::type::ArrayType vec4_f32{&f32, 4u};
AddVertexInputVariable(1, "var_b", &vec4_f32);
InitTransform(
{{{16,
InputStepMode::kVertex,
{{VertexFormat::kF32, 0, 0}, {VertexFormat::kVec4F32, 0, 1}}}}});
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__f32
}
Variable{
var_b
private
__array__f32_4
}
DecoratedVariable{
Decorations{
BuiltinDecoration{vertex_idx}
}
_tint_pulling_vertex_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{16}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Identifier{_tint_pulling_pos}
divide
ScalarConstructor{4}
}
}
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{16}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_b}
TypeConstructor{
__vec_4__f32
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{0}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{4}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{8}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{12}
}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
TEST_F(VertexPullingTransformTest, FloatVectorAttributes) {
InitBasicModule();
ast::type::F32Type f32;
ast::type::ArrayType vec2_f32{&f32, 2u};
AddVertexInputVariable(0, "var_a", &vec2_f32);
ast::type::ArrayType vec3_f32{&f32, 3u};
AddVertexInputVariable(1, "var_b", &vec3_f32);
ast::type::ArrayType vec4_f32{&f32, 4u};
AddVertexInputVariable(2, "var_c", &vec4_f32);
InitTransform(
{{{8, InputStepMode::kVertex, {{VertexFormat::kVec2F32, 0, 0}}},
{12, InputStepMode::kVertex, {{VertexFormat::kVec3F32, 0, 1}}},
{16, InputStepMode::kVertex, {{VertexFormat::kVec4F32, 0, 2}}}}});
EXPECT_TRUE(transform()->Run());
EXPECT_EQ(R"(Module{
TintVertexData Struct{
[[block]]
StructMember{[[ offset 0 ]] _tint_vertex_data: __array__u32_stride_4}
}
Variable{
var_a
private
__array__f32_2
}
Variable{
var_b
private
__array__f32_3
}
Variable{
var_c
private
__array__f32_4
}
DecoratedVariable{
Decorations{
BuiltinDecoration{vertex_idx}
}
_tint_pulling_vertex_index
in
__i32
}
DecoratedVariable{
Decorations{
BindingDecoration{0}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_0
storage_buffer
__struct_TintVertexData
}
DecoratedVariable{
Decorations{
BindingDecoration{1}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_1
storage_buffer
__struct_TintVertexData
}
DecoratedVariable{
Decorations{
BindingDecoration{2}
SetDecoration{4}
}
_tint_pulling_vertex_buffer_2
storage_buffer
__struct_TintVertexData
}
Function main -> __void
StageDecoration{vertex}
()
{
Block{
VariableDeclStatement{
Variable{
_tint_pulling_pos
function
__i32
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{8}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_a}
TypeConstructor{
__vec_2__f32
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{0}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_0}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{4}
}
divide
ScalarConstructor{4}
}
}
}
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{12}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_b}
TypeConstructor{
__vec_3__f32
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_1}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{0}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_1}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{4}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_1}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{8}
}
divide
ScalarConstructor{4}
}
}
}
}
}
Assignment{
Identifier{_tint_pulling_pos}
Binary{
Binary{
Identifier{_tint_pulling_vertex_index}
multiply
ScalarConstructor{16}
}
add
ScalarConstructor{0}
}
}
Assignment{
Identifier{var_c}
TypeConstructor{
__vec_4__f32
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_2}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{0}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_2}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{4}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_2}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{8}
}
divide
ScalarConstructor{4}
}
}
}
Bitcast<__f32>{
ArrayAccessor{
MemberAccessor{
Identifier{_tint_pulling_vertex_buffer_2}
Identifier{_tint_vertex_data}
}
Binary{
Binary{
Identifier{_tint_pulling_pos}
add
ScalarConstructor{12}
}
divide
ScalarConstructor{4}
}
}
}
}
}
}
}
}
)",
mod()->to_str());
}
} // namespace
} // namespace transform
} // namespace tint