reader/wgsl: Remove old shader IO syntax

Removing parsing support for the 'in' and 'out' storage classes is
enough to prevent anyone from using the old syntax. The Input and
Output storage classes will remain in the AST for now, as the SPIR-V
reader still has codepaths that use them, and the SPIR-V writer
currently still relies on them.

Bug: tint:697
Change-Id: Ifef9eda8bcbf2f243b1e1d8d4fab25784cd3f80e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54841
Auto-Submit: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
James Price 2021-06-18 20:14:07 +00:00 committed by Tint LUCI CQ
parent 443c41de33
commit 90503dec9c
15 changed files with 67 additions and 555 deletions

View File

@ -586,8 +586,6 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
return {Token::Type::kImage, source, "image"}; return {Token::Type::kImage, source, "image"};
if (str == "import") if (str == "import")
return {Token::Type::kImport, source, "import"}; return {Token::Type::kImport, source, "import"};
if (str == "in")
return {Token::Type::kIn, source, "in"};
if (str == "let") if (str == "let")
return {Token::Type::kLet, source, "let"}; return {Token::Type::kLet, source, "let"};
if (str == "loop") if (str == "loop")
@ -610,8 +608,6 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
return {Token::Type::kMat4x3, source, "mat4x3"}; return {Token::Type::kMat4x3, source, "mat4x3"};
if (str == "mat4x4") if (str == "mat4x4")
return {Token::Type::kMat4x4, source, "mat4x4"}; return {Token::Type::kMat4x4, source, "mat4x4"};
if (str == "out")
return {Token::Type::kOut, source, "out"};
if (str == "private") if (str == "private")
return {Token::Type::kPrivate, source, "private"}; return {Token::Type::kPrivate, source, "private"};
if (str == "ptr") if (str == "ptr")

View File

@ -475,7 +475,6 @@ INSTANTIATE_TEST_SUITE_P(
TokenData{"if", Token::Type::kIf}, TokenData{"if", Token::Type::kIf},
TokenData{"image", Token::Type::kImage}, TokenData{"image", Token::Type::kImage},
TokenData{"import", Token::Type::kImport}, TokenData{"import", Token::Type::kImport},
TokenData{"in", Token::Type::kIn},
TokenData{"let", Token::Type::kLet}, TokenData{"let", Token::Type::kLet},
TokenData{"loop", Token::Type::kLoop}, TokenData{"loop", Token::Type::kLoop},
TokenData{"mat2x2", Token::Type::kMat2x2}, TokenData{"mat2x2", Token::Type::kMat2x2},
@ -487,7 +486,6 @@ INSTANTIATE_TEST_SUITE_P(
TokenData{"mat4x2", Token::Type::kMat4x2}, TokenData{"mat4x2", Token::Type::kMat4x2},
TokenData{"mat4x3", Token::Type::kMat4x3}, TokenData{"mat4x3", Token::Type::kMat4x3},
TokenData{"mat4x4", Token::Type::kMat4x4}, TokenData{"mat4x4", Token::Type::kMat4x4},
TokenData{"out", Token::Type::kOut},
TokenData{"private", Token::Type::kPrivate}, TokenData{"private", Token::Type::kPrivate},
TokenData{"ptr", Token::Type::kPtr}, TokenData{"ptr", Token::Type::kPtr},
TokenData{"return", Token::Type::kReturn}, TokenData{"return", Token::Type::kReturn},

View File

@ -530,18 +530,6 @@ Maybe<ParserImpl::VarDeclInfo> ParserImpl::variable_decl(bool allow_inferred) {
return Failure::kErrored; return Failure::kErrored;
if (explicit_vq.matched) { if (explicit_vq.matched) {
vq = explicit_vq.value; vq = explicit_vq.value;
// TODO(crbug.com/tint/697): Remove this.
if (vq.storage_class == ast::StorageClass::kInput) {
deprecated(explicit_vq.source,
"use an entry point parameter instead of a variable in the "
"`in` storage class");
}
if (vq.storage_class == ast::StorageClass::kOutput) {
deprecated(explicit_vq.source,
"use an entry point return value instead of a variable in the "
"`out` storage class");
}
} }
auto decl = auto decl =
@ -1236,12 +1224,6 @@ Expect<ast::StorageClass> ParserImpl::expect_storage_class(
const std::string& use) { const std::string& use) {
auto source = peek().source(); auto source = peek().source();
if (match(Token::Type::kIn))
return {ast::StorageClass::kInput, source};
if (match(Token::Type::kOut))
return {ast::StorageClass::kOutput, source};
if (match(Token::Type::kUniform)) if (match(Token::Type::kUniform))
return {ast::StorageClass::kUniform, source}; return {ast::StorageClass::kUniform, source};

View File

@ -996,16 +996,16 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingLessThan) {
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingGreaterThan) { TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingGreaterThan) {
EXPECT("var i : ptr<in, u32;", EXPECT("var i : ptr<private, u32;",
"test.wgsl:1:20 error: expected '>' for ptr declaration\n" "test.wgsl:1:25 error: expected '>' for ptr declaration\n"
"var i : ptr<in, u32;\n" "var i : ptr<private, u32;\n"
" ^\n"); " ^\n");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingComma) { TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingComma) {
EXPECT("var i : ptr<in u32>;", EXPECT("var i : ptr<private u32>;",
"test.wgsl:1:16 error: expected ',' for ptr declaration\n" "test.wgsl:1:21 error: expected ',' for ptr declaration\n"
"var i : ptr<in u32>;\n" "var i : ptr<private u32>;\n"
" ^^^\n"); " ^^^\n");
} }
@ -1017,9 +1017,9 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingStorageClass) {
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingType) { TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingType) {
EXPECT("var i : ptr<in, 1>;", EXPECT("var i : ptr<private, 1>;",
"test.wgsl:1:17 error: invalid type for ptr declaration\n" "test.wgsl:1:22 error: invalid type for ptr declaration\n"
"var i : ptr<in, 1>;\n" "var i : ptr<private, 1>;\n"
" ^\n"); " ^\n");
} }
@ -1045,9 +1045,9 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclInvalidClass) {
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclMissingGThan) { TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclMissingGThan) {
EXPECT("var<in i : i32", EXPECT("var<private i : i32",
"test.wgsl:1:8 error: expected '>' for variable declaration\n" "test.wgsl:1:13 error: expected '>' for variable declaration\n"
"var<in i : i32\n" "var<private i : i32\n"
" ^\n"); " ^\n");
} }

View File

@ -168,48 +168,6 @@ TEST_F(ParserImplTest, GlobalVariableDecl_InvalidVariableDecl) {
EXPECT_EQ(p->error(), "1:5: invalid storage class for variable declaration"); EXPECT_EQ(p->error(), "1:5: invalid storage class for variable declaration");
} }
TEST_F(ParserImplTest, GlobalVariableDecl_StorageClassIn_Deprecated) {
auto p = parser("[[location(0)]] var<in> a : f32");
auto f = p->function_header();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_TRUE(decos.matched);
auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kInput);
EXPECT_EQ(
p->builder().Diagnostics().str(),
R"(test.wgsl:1:21 warning: use of deprecated language feature: use an entry point parameter instead of a variable in the `in` storage class
[[location(0)]] var<in> a : f32
^^
)");
}
TEST_F(ParserImplTest, GlobalVariableDecl_StorageClassOut_Deprecated) {
auto p = parser("[[location(0)]] var<out> a : f32");
auto f = p->function_header();
auto decos = p->decoration_list();
EXPECT_FALSE(decos.errored);
EXPECT_TRUE(decos.matched);
auto e = p->global_variable_decl(decos.value);
ASSERT_FALSE(p->has_error()) << p->error();
EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
EXPECT_TRUE(e->type()->Is<ast::F32>());
EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kOutput);
EXPECT_EQ(
p->builder().Diagnostics().str(),
R"(test.wgsl:1:21 warning: use of deprecated language feature: use an entry point return value instead of a variable in the `out` storage class
[[location(0)]] var<out> a : f32
^^^
)");
}
} // namespace } // namespace
} // namespace wgsl } // namespace wgsl
} // namespace reader } // namespace reader

View File

@ -46,8 +46,6 @@ INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
StorageClassTest, StorageClassTest,
testing::Values( testing::Values(
StorageClassData{"in", ast::StorageClass::kInput},
StorageClassData{"out", ast::StorageClass::kOutput},
StorageClassData{"uniform", ast::StorageClass::kUniform}, StorageClassData{"uniform", ast::StorageClass::kUniform},
StorageClassData{"workgroup", ast::StorageClass::kWorkgroup}, StorageClassData{"workgroup", ast::StorageClass::kWorkgroup},
StorageClassData{"storage", ast::StorageClass::kStorage}, StorageClassData{"storage", ast::StorageClass::kStorage},

View File

@ -26,18 +26,15 @@ TEST_F(ParserImplTest, Empty) {
TEST_F(ParserImplTest, Parses) { TEST_F(ParserImplTest, Parses) {
auto p = parser(R"( auto p = parser(R"(
[[location(0)]] var<out> gl_FragColor : vec4<f32>; [[stage(fragment)]]
fn main() -> [[location(0)]] vec4<f32> {
[[stage(vertex)]] return vec4<f32>(.4, .2, .3, 1);
fn main() {
gl_FragColor = vec4<f32>(.4, .2, .3, 1);
} }
)"); )");
ASSERT_TRUE(p->Parse()) << p->error(); ASSERT_TRUE(p->Parse()) << p->error();
Program program = p->program(); Program program = p->program();
ASSERT_EQ(1u, program.AST().Functions().size()); ASSERT_EQ(1u, program.AST().Functions().size());
ASSERT_EQ(1u, program.AST().GlobalVariables().size());
} }
TEST_F(ParserImplTest, HandlesError) { TEST_F(ParserImplTest, HandlesError) {

View File

@ -50,10 +50,6 @@ INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
VariableQualifierTest, VariableQualifierTest,
testing::Values( testing::Values(
VariableStorageData{"in", ast::StorageClass::kInput,
ast::Access::kUndefined},
VariableStorageData{"out", ast::StorageClass::kOutput,
ast::Access::kUndefined},
VariableStorageData{"uniform", ast::StorageClass::kUniform, VariableStorageData{"uniform", ast::StorageClass::kUniform,
ast::Access::kUndefined}, ast::Access::kUndefined},
VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup, VariableStorageData{"workgroup", ast::StorageClass::kWorkgroup,
@ -94,34 +90,34 @@ TEST_F(ParserImplTest, VariableQualifier_Empty) {
} }
TEST_F(ParserImplTest, VariableQualifier_MissingLessThan) { TEST_F(ParserImplTest, VariableQualifier_MissingLessThan) {
auto p = parser("in>"); auto p = parser("private>");
auto sc = p->variable_qualifier(); auto sc = p->variable_qualifier();
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_FALSE(sc.errored); EXPECT_FALSE(sc.errored);
EXPECT_FALSE(sc.matched); EXPECT_FALSE(sc.matched);
auto t = p->next(); auto t = p->next();
ASSERT_TRUE(t.IsIn()); ASSERT_TRUE(t.IsPrivate());
} }
TEST_F(ParserImplTest, VariableQualifier_MissingLessThan_AfterSC) { TEST_F(ParserImplTest, VariableQualifier_MissingLessThan_AfterSC) {
auto p = parser("in, >"); auto p = parser("private, >");
auto sc = p->variable_qualifier(); auto sc = p->variable_qualifier();
EXPECT_FALSE(p->has_error()); EXPECT_FALSE(p->has_error());
EXPECT_FALSE(sc.errored); EXPECT_FALSE(sc.errored);
EXPECT_FALSE(sc.matched); EXPECT_FALSE(sc.matched);
auto t = p->next(); auto t = p->next();
ASSERT_TRUE(t.IsIn()); ASSERT_TRUE(t.IsPrivate());
} }
TEST_F(ParserImplTest, VariableQualifier_MissingGreaterThan) { TEST_F(ParserImplTest, VariableQualifier_MissingGreaterThan) {
auto p = parser("<in"); auto p = parser("<private");
auto sc = p->variable_qualifier(); auto sc = p->variable_qualifier();
EXPECT_TRUE(p->has_error()); EXPECT_TRUE(p->has_error());
EXPECT_TRUE(sc.errored); EXPECT_TRUE(sc.errored);
EXPECT_FALSE(sc.matched); EXPECT_FALSE(sc.matched);
EXPECT_EQ(p->error(), "1:4: expected '>' for variable declaration"); EXPECT_EQ(p->error(), "1:9: expected '>' for variable declaration");
} }
} // namespace } // namespace

View File

@ -34,11 +34,9 @@ TEST_F(ParserTest, Empty) {
TEST_F(ParserTest, Parses) { TEST_F(ParserTest, Parses) {
Source::File file("test.wgsl", R"( Source::File file("test.wgsl", R"(
[[location(0)]] var<out> gl_FragColor : vec4<f32>;
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main() -> [[location(0)]] vec4<f32> {
gl_FragColor = vec4<f32>(.4, .2, .3, 1.); return vec4<f32>(.4, .2, .3, 1.);
} }
)"); )");
auto program = Parse(&file); auto program = Parse(&file);
@ -46,7 +44,6 @@ fn main() {
ASSERT_TRUE(program.IsValid()) << errs; ASSERT_TRUE(program.IsValid()) << errs;
ASSERT_EQ(1u, program.AST().Functions().size()); ASSERT_EQ(1u, program.AST().Functions().size());
ASSERT_EQ(1u, program.AST().GlobalVariables().size());
} }
TEST_F(ParserTest, HandlesError) { TEST_F(ParserTest, HandlesError) {

View File

@ -221,8 +221,6 @@ std::string Token::TypeToName(Type type) {
return "image"; return "image";
case Token::Type::kImport: case Token::Type::kImport:
return "import"; return "import";
case Token::Type::kIn:
return "in";
case Token::Type::kLet: case Token::Type::kLet:
return "let"; return "let";
case Token::Type::kLoop: case Token::Type::kLoop:
@ -245,8 +243,6 @@ std::string Token::TypeToName(Type type) {
return "mat4x3"; return "mat4x3";
case Token::Type::kMat4x4: case Token::Type::kMat4x4:
return "mat4x4"; return "mat4x4";
case Token::Type::kOut:
return "out";
case Token::Type::kPrivate: case Token::Type::kPrivate:
return "private"; return "private";
case Token::Type::kPtr: case Token::Type::kPtr:

View File

@ -229,8 +229,6 @@ class Token {
kImage, kImage,
/// A 'import' /// A 'import'
kImport, kImport,
/// A 'in'
kIn,
/// A 'let' /// A 'let'
kLet, kLet,
/// A 'loop' /// A 'loop'
@ -253,8 +251,6 @@ class Token {
kMat4x3, kMat4x3,
/// A 'mat4x4' /// A 'mat4x4'
kMat4x4, kMat4x4,
/// A 'out'
kOut,
/// A 'private' /// A 'private'
kPrivate, kPrivate,
/// A 'ptr' /// A 'ptr'
@ -576,8 +572,6 @@ class Token {
bool IsImage() const { return type_ == Type::kImage; } bool IsImage() const { return type_ == Type::kImage; }
/// @returns true if token is a 'import' /// @returns true if token is a 'import'
bool IsImport() const { return type_ == Type::kImport; } bool IsImport() const { return type_ == Type::kImport; }
/// @returns true if token is a 'in'
bool IsIn() const { return type_ == Type::kIn; }
/// @returns true if token is a 'let' /// @returns true if token is a 'let'
bool IsLet() const { return type_ == Type::kLet; } bool IsLet() const { return type_ == Type::kLet; }
/// @returns true if token is a 'loop' /// @returns true if token is a 'loop'
@ -600,8 +594,6 @@ class Token {
bool IsMat4x3() const { return type_ == Type::kMat4x3; } bool IsMat4x3() const { return type_ == Type::kMat4x3; }
/// @returns true if token is a 'mat4x4' /// @returns true if token is a 'mat4x4'
bool IsMat4x4() const { return type_ == Type::kMat4x4; } bool IsMat4x4() const { return type_ == Type::kMat4x4; }
/// @returns true if token is a 'out'
bool IsOut() const { return type_ == Type::kOut; }
/// @returns true if token is a 'private' /// @returns true if token is a 'private'
bool IsPrivate() const { return type_ == Type::kPrivate; } bool IsPrivate() const { return type_ == Type::kPrivate; }
/// @returns true if token is a 'ptr' /// @returns true if token is a 'ptr'

View File

@ -326,236 +326,6 @@ fn entry_c([[builtin(instance_index)]] inst_idx : u32) -> [[builtin(position)]]
EXPECT_EQ(data->first_instance_offset, 4u); EXPECT_EQ(data->first_instance_offset, 4u);
} }
TEST_F(FirstIndexOffsetTest, OLD_BasicModuleVertexIndex) {
auto* src = R"(
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return vert_idx;
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
auto* expect = R"(
[[block]]
struct tint_symbol {
first_vertex_index : u32;
};
[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return (vert_idx + tint_symbol_1.first_vertex_index);
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
EXPECT_EQ(expect, str(got));
auto* data = got.data.Get<FirstIndexOffset::Data>();
ASSERT_NE(data, nullptr);
EXPECT_EQ(data->has_vertex_index, true);
EXPECT_EQ(data->has_instance_index, false);
EXPECT_EQ(data->first_vertex_offset, 0u);
EXPECT_EQ(data->first_instance_offset, 0u);
}
TEST_F(FirstIndexOffsetTest, OLD_BasicModuleInstanceIndex) {
auto* src = R"(
[[builtin(instance_index)]] var<in> inst_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return inst_idx;
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
auto* expect = R"(
[[block]]
struct tint_symbol {
first_instance_index : u32;
};
[[binding(1), group(7)]] var<uniform> tint_symbol_1 : tint_symbol;
[[builtin(instance_index)]] var<in> inst_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return (inst_idx + tint_symbol_1.first_instance_index);
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 7);
auto got = Run<FirstIndexOffset>(src, std::move(config));
EXPECT_EQ(expect, str(got));
auto* data = got.data.Get<FirstIndexOffset::Data>();
ASSERT_NE(data, nullptr);
EXPECT_EQ(data->has_vertex_index, false);
EXPECT_EQ(data->has_instance_index, true);
EXPECT_EQ(data->first_vertex_offset, 0u);
EXPECT_EQ(data->first_instance_offset, 0u);
}
TEST_F(FirstIndexOffsetTest, OLD_BasicModuleBothIndex) {
auto* src = R"(
[[builtin(instance_index)]] var<in> instance_idx : u32;
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return instance_idx + vert_idx;
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
auto* expect = R"(
[[block]]
struct tint_symbol {
first_vertex_index : u32;
first_instance_index : u32;
};
[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
[[builtin(instance_index)]] var<in> instance_idx : u32;
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn test() -> u32 {
return ((instance_idx + tint_symbol_1.first_instance_index) + (vert_idx + tint_symbol_1.first_vertex_index));
}
[[stage(vertex)]]
fn entry() {
ignore(test());
pos = vec4<f32>();
}
)";
DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
EXPECT_EQ(expect, str(got));
auto* data = got.data.Get<FirstIndexOffset::Data>();
ASSERT_NE(data, nullptr);
EXPECT_EQ(data->has_vertex_index, true);
EXPECT_EQ(data->has_instance_index, true);
EXPECT_EQ(data->first_vertex_offset, 0u);
EXPECT_EQ(data->first_instance_offset, 4u);
}
TEST_F(FirstIndexOffsetTest, OLD_NestedCalls) {
auto* src = R"(
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn func1() -> u32 {
return vert_idx;
}
fn func2() -> u32 {
return func1();
}
[[stage(vertex)]]
fn entry() {
ignore(func2());
pos = vec4<f32>();
}
)";
auto* expect = R"(
[[block]]
struct tint_symbol {
first_vertex_index : u32;
};
[[binding(1), group(2)]] var<uniform> tint_symbol_1 : tint_symbol;
[[builtin(vertex_index)]] var<in> vert_idx : u32;
[[builtin(position)]] var<out> pos : vec4<f32>;
fn func1() -> u32 {
return (vert_idx + tint_symbol_1.first_vertex_index);
}
fn func2() -> u32 {
return func1();
}
[[stage(vertex)]]
fn entry() {
ignore(func2());
pos = vec4<f32>();
}
)";
DataMap config;
config.Add<FirstIndexOffset::BindingPoint>(1, 2);
auto got = Run<FirstIndexOffset>(src, std::move(config));
EXPECT_EQ(expect, str(got));
auto* data = got.data.Get<FirstIndexOffset::Data>();
ASSERT_NE(data, nullptr);
EXPECT_EQ(data->has_vertex_index, true);
EXPECT_EQ(data->has_instance_index, false);
EXPECT_EQ(data->first_vertex_offset, 0u);
EXPECT_EQ(data->first_instance_offset, 0u);
}
} // namespace } // namespace
} // namespace transform } // namespace transform
} // namespace tint } // namespace tint

View File

@ -42,29 +42,26 @@ TEST_F(RenamerTest, EmptyModule) {
TEST_F(RenamerTest, BasicModuleVertexIndex) { TEST_F(RenamerTest, BasicModuleVertexIndex) {
auto* src = R"( auto* src = R"(
[[builtin(vertex_index)]] var<in> vert_idx : u32; fn test(vert_idx : u32) -> u32 {
fn test() -> u32 {
return vert_idx; return vert_idx;
} }
[[stage(vertex)]] [[stage(vertex)]]
fn entry() -> [[builtin(position)]] vec4<f32> { fn entry([[builtin(vertex_index)]] vert_idx : u32
ignore(test()); ) -> [[builtin(position)]] vec4<f32> {
ignore(test(vert_idx));
return vec4<f32>(); return vec4<f32>();
} }
)"; )";
auto* expect = R"( auto* expect = R"(
[[builtin(vertex_index)]] var<in> tint_symbol : u32; fn tint_symbol(tint_symbol_1 : u32) -> u32 {
return tint_symbol_1;
fn tint_symbol_1() -> u32 {
return tint_symbol;
} }
[[stage(vertex)]] [[stage(vertex)]]
fn tint_symbol_2() -> [[builtin(position)]] vec4<f32> { fn tint_symbol_2([[builtin(vertex_index)]] tint_symbol_1 : u32) -> [[builtin(position)]] vec4<f32> {
ignore(tint_symbol_1()); ignore(tint_symbol(tint_symbol_1));
return vec4<f32>(); return vec4<f32>();
} }
)"; )";
@ -77,8 +74,8 @@ fn tint_symbol_2() -> [[builtin(position)]] vec4<f32> {
ASSERT_NE(data, nullptr); ASSERT_NE(data, nullptr);
Renamer::Data::Remappings expected_remappings = { Renamer::Data::Remappings expected_remappings = {
{"vert_idx", "tint_symbol"}, {"vert_idx", "tint_symbol_1"},
{"test", "tint_symbol_1"}, {"test", "tint_symbol"},
{"entry", "tint_symbol_2"}, {"entry", "tint_symbol_2"},
}; };
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings)); EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));

View File

@ -492,28 +492,29 @@ fn main() {
TEST_F(SpirvTest, HandleSampleMaskBuiltins_Basic) { TEST_F(SpirvTest, HandleSampleMaskBuiltins_Basic) {
auto* src = R"( auto* src = R"(
[[builtin(sample_index)]] var<in> sample_index : u32;
[[builtin(sample_mask)]] var<in> mask_in : u32;
[[builtin(sample_mask)]] var<out> mask_out : u32;
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main([[builtin(sample_index)]] sample_index : u32,
mask_out = mask_in; [[builtin(sample_mask)]] mask_in : u32
) -> [[builtin(sample_mask)]] u32 {
return mask_in;
} }
)"; )";
auto* expect = R"( auto* expect = R"(
[[builtin(sample_index)]] var<in> sample_index : u32; [[builtin(sample_index)]] var<in> tint_symbol : u32;
[[builtin(sample_mask)]] var<in> mask_in : array<u32, 1>; [[builtin(sample_mask)]] var<in> tint_symbol_1 : array<u32, 1>;
[[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>; [[builtin(sample_mask)]] var<out> tint_symbol_3 : array<u32, 1>;
fn tint_symbol_4(tint_symbol_2 : u32) {
tint_symbol_3[0] = tint_symbol_2;
}
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main() {
mask_out[0] = mask_in[0]; tint_symbol_4(tint_symbol_1[0]);
return;
} }
)"; )";
@ -524,40 +525,42 @@ fn main() {
TEST_F(SpirvTest, HandleSampleMaskBuiltins_FunctionArg) { TEST_F(SpirvTest, HandleSampleMaskBuiltins_FunctionArg) {
auto* src = R"( auto* src = R"(
[[builtin(sample_mask)]] var<in> mask_in : u32;
[[builtin(sample_mask)]] var<out> mask_out : u32;
fn filter(mask: u32) -> u32 { fn filter(mask: u32) -> u32 {
return (mask & 3u); return (mask & 3u);
} }
fn set_mask(input : u32) { fn set_mask(input : u32) -> u32 {
mask_out = input; return input;
} }
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main([[builtin(sample_mask)]] mask_in : u32
set_mask(filter(mask_in)); ) -> [[builtin(sample_mask)]] u32 {
return set_mask(filter(mask_in));
} }
)"; )";
auto* expect = R"( auto* expect = R"(
[[builtin(sample_mask)]] var<in> mask_in : array<u32, 1>;
[[builtin(sample_mask)]] var<out> mask_out : array<u32, 1>;
fn filter(mask : u32) -> u32 { fn filter(mask : u32) -> u32 {
return (mask & 3u); return (mask & 3u);
} }
fn set_mask(input : u32) { fn set_mask(input : u32) -> u32 {
mask_out[0] = input; return input;
}
[[builtin(sample_mask)]] var<in> tint_symbol : array<u32, 1>;
[[builtin(sample_mask)]] var<out> tint_symbol_2 : array<u32, 1>;
fn tint_symbol_3(tint_symbol_1 : u32) {
tint_symbol_2[0] = tint_symbol_1;
} }
[[stage(fragment)]] [[stage(fragment)]]
fn main() { fn main() {
set_mask(filter(mask_in[0])); tint_symbol_3(set_mask(filter(tint_symbol[0])));
return;
} }
)"; )";

View File

@ -652,174 +652,6 @@ fn main([[builtin(vertex_index)]] tint_pulling_vertex_index_1 : u32) -> [[builti
EXPECT_EQ(expect, str(got)); EXPECT_EQ(expect, str(got));
} }
// TODO(crbug.com/tint/697): Remove this.
TEST_F(VertexPullingTest, OneAttributeDifferentOutputSet_Legacy) {
auto* src = R"(
[[location(0)]] var<in> var_a : f32;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)";
auto* expect = R"(
[[builtin(vertex_index)]] var<in> tint_pulling_vertex_index : u32;
[[block]]
struct TintVertexData {
tint_vertex_data : [[stride(4)]] array<u32>;
};
[[binding(0), group(5)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
var<private> var_a : f32;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
{
var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 4u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
}
return vec4<f32>();
}
)";
VertexPulling::Config cfg;
cfg.vertex_state = {
{{4, InputStepMode::kVertex, {{VertexFormat::kF32, 0, 0}}}}};
cfg.pulling_group = 5;
cfg.entry_point_name = "main";
DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
EXPECT_EQ(expect, str(got));
}
// TODO(crbug.com/tint/697): Remove this.
// We expect the transform to use an existing builtin variables if it finds them
TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex_Legacy) {
auto* src = R"(
[[location(0)]] var<in> var_a : f32;
[[location(1)]] var<in> var_b : f32;
[[builtin(vertex_index)]] var<in> custom_vertex_index : u32;
[[builtin(instance_index)]] var<in> custom_instance_index : u32;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)";
auto* expect = R"(
[[block]]
struct TintVertexData {
tint_vertex_data : [[stride(4)]] array<u32>;
};
[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
[[binding(1), group(4)]] var<storage, read> tint_pulling_vertex_buffer_1 : TintVertexData;
var<private> var_a : f32;
var<private> var_b : f32;
[[builtin(vertex_index)]] var<in> custom_vertex_index : u32;
[[builtin(instance_index)]] var<in> custom_instance_index : u32;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
{
var tint_pulling_pos : u32;
tint_pulling_pos = ((custom_vertex_index * 4u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
tint_pulling_pos = ((custom_instance_index * 4u) + 0u);
var_b = bitcast<f32>(tint_pulling_vertex_buffer_1.tint_vertex_data[(tint_pulling_pos / 4u)]);
}
return vec4<f32>();
}
)";
VertexPulling::Config cfg;
cfg.vertex_state = {{
{
4,
InputStepMode::kVertex,
{{VertexFormat::kF32, 0, 0}},
},
{
4,
InputStepMode::kInstance,
{{VertexFormat::kF32, 0, 1}},
},
}};
cfg.entry_point_name = "main";
DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
EXPECT_EQ(expect, str(got));
}
// TODO(crbug.com/tint/697): Remove this.
TEST_F(VertexPullingTest, TwoAttributesSameBuffer_Legacy) {
auto* src = R"(
[[location(0)]] var<in> var_a : f32;
[[location(1)]] var<in> var_b : vec4<f32>;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
return vec4<f32>();
}
)";
auto* expect = R"(
[[builtin(vertex_index)]] var<in> tint_pulling_vertex_index : u32;
[[block]]
struct TintVertexData {
tint_vertex_data : [[stride(4)]] array<u32>;
};
[[binding(0), group(4)]] var<storage, read> tint_pulling_vertex_buffer_0 : TintVertexData;
var<private> var_a : f32;
var<private> var_b : vec4<f32>;
[[stage(vertex)]]
fn main() -> [[builtin(position)]] vec4<f32> {
{
var tint_pulling_pos : u32;
tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u);
var_a = bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[(tint_pulling_pos / 4u)]);
tint_pulling_pos = ((tint_pulling_vertex_index * 16u) + 0u);
var_b = vec4<f32>(bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 0u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 4u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 8u) / 4u)]), bitcast<f32>(tint_pulling_vertex_buffer_0.tint_vertex_data[((tint_pulling_pos + 12u) / 4u)]));
}
return vec4<f32>();
}
)";
VertexPulling::Config cfg;
cfg.vertex_state = {
{{16,
InputStepMode::kVertex,
{{VertexFormat::kF32, 0, 0}, {VertexFormat::kVec4F32, 0, 1}}}}};
cfg.entry_point_name = "main";
DataMap data;
data.Add<VertexPulling::Config>(cfg);
auto got = Run<VertexPulling>(src, data);
EXPECT_EQ(expect, str(got));
}
} // namespace } // namespace
} // namespace transform } // namespace transform
} // namespace tint } // namespace tint