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:
parent
443c41de33
commit
90503dec9c
|
@ -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")
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
@ -996,17 +996,17 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingStorageClass) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarPtrMissingStorageClass) {
|
||||||
|
@ -1017,10 +1017,10 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingLessThan) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarAtomicMissingLessThan) {
|
||||||
|
@ -1045,10 +1045,10 @@ 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");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingLessThan) {
|
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingLessThan) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue