GLSL: implement desktop GLSL support.

Introduce a glsl::Version, to allow the client to specify ES or
Desktop, as well as the desired GLSL major and minor version.

Bug: tint:1422

Change-Id: I4116bc2da40ae6a553dc2522d042dda1464a0c05
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79700
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2022-02-09 17:44:17 +00:00 committed by Tint LUCI CQ
parent d21ebe74bd
commit 35cc663130
11 changed files with 343 additions and 23 deletions

View File

@ -525,6 +525,7 @@ if(${TINT_BUILD_GLSL_WRITER})
writer/glsl/generator.h writer/glsl/generator.h
writer/glsl/generator_impl.cc writer/glsl/generator_impl.cc
writer/glsl/generator_impl.h writer/glsl/generator_impl.h
writer/glsl/version.h
) )
endif() endif()
@ -1082,10 +1083,12 @@ if(TINT_BUILD_TESTS)
writer/glsl/generator_impl_module_constant_test.cc writer/glsl/generator_impl_module_constant_test.cc
writer/glsl/generator_impl_return_test.cc writer/glsl/generator_impl_return_test.cc
writer/glsl/generator_impl_sanitizer_test.cc writer/glsl/generator_impl_sanitizer_test.cc
writer/glsl/generator_impl_storage_buffer_test.cc
writer/glsl/generator_impl_switch_test.cc writer/glsl/generator_impl_switch_test.cc
writer/glsl/generator_impl_test.cc writer/glsl/generator_impl_test.cc
writer/glsl/generator_impl_type_test.cc writer/glsl/generator_impl_type_test.cc
writer/glsl/generator_impl_unary_op_test.cc writer/glsl/generator_impl_unary_op_test.cc
writer/glsl/generator_impl_uniform_buffer_test.cc
writer/glsl/generator_impl_variable_decl_statement_test.cc writer/glsl/generator_impl_variable_decl_statement_test.cc
writer/glsl/generator_impl_workgroup_var_test.cc writer/glsl/generator_impl_workgroup_var_test.cc
writer/glsl/test_helper.h writer/glsl/test_helper.h

View File

@ -53,7 +53,7 @@ Result Generate(const Program* program,
} }
// Generate the GLSL code. // Generate the GLSL code.
auto impl = std::make_unique<GeneratorImpl>(&output.program); auto impl = std::make_unique<GeneratorImpl>(&output.program, options.version);
result.success = impl->Generate(); result.success = impl->Generate();
result.error = impl->error(); result.error = impl->error();
result.glsl = impl->result(); result.glsl = impl->result();

View File

@ -25,6 +25,7 @@
#include "src/ast/pipeline_stage.h" #include "src/ast/pipeline_stage.h"
#include "src/sem/binding_point.h" #include "src/sem/binding_point.h"
#include "src/sem/sampler_texture_pair.h" #include "src/sem/sampler_texture_pair.h"
#include "src/writer/glsl/version.h"
#include "src/writer/text.h" #include "src/writer/text.h"
namespace tint { namespace tint {
@ -69,6 +70,9 @@ struct Options {
/// If true, then validation will be disabled for binding point collisions /// If true, then validation will be disabled for binding point collisions
/// generated by the BindingRemapper transform /// generated by the BindingRemapper transform
bool allow_collisions = false; bool allow_collisions = false;
/// The GLSL version to emit
Version version;
}; };
/// The result produced when generating GLSL. /// The result produced when generating GLSL.

View File

@ -128,12 +128,20 @@ const char* convert_texel_format_to_glsl(const ast::TexelFormat format) {
} // namespace } // namespace
GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {} GeneratorImpl::GeneratorImpl(const Program* program, const Version& version)
: TextGenerator(program), version_(version) {}
GeneratorImpl::~GeneratorImpl() = default; GeneratorImpl::~GeneratorImpl() = default;
bool GeneratorImpl::Generate() { bool GeneratorImpl::Generate() {
line() << "#version 310 es"; {
auto out = line();
out << "#version " << version_.major_version << version_.minor_version
<< "0";
if (version_.IsES()) {
out << " es";
}
}
auto helpers_insertion_point = current_buffer_->lines.size(); auto helpers_insertion_point = current_buffer_->lines.size();
@ -181,7 +189,7 @@ bool GeneratorImpl::Generate() {
TextBuffer extensions; TextBuffer extensions;
if (requires_oes_sample_variables_) { if (version_.IsES() && requires_oes_sample_variables_) {
extensions.Append("#extension GL_OES_sample_variables : require"); extensions.Append("#extension GL_OES_sample_variables : require");
} }
@ -192,7 +200,7 @@ bool GeneratorImpl::Generate() {
helpers_insertion_point += extensions.lines.size(); helpers_insertion_point += extensions.lines.size();
} }
if (requires_default_precision_qualifier_) { if (version_.IsES() && requires_default_precision_qualifier_) {
current_buffer_->Insert("precision mediump float;", current_buffer_->Insert("precision mediump float;",
helpers_insertion_point++, indent); helpers_insertion_point++, indent);
} }
@ -1729,9 +1737,15 @@ bool GeneratorImpl::EmitUniformVariable(const sem::Variable* var) {
return false; return false;
} }
ast::VariableBindingPoint bp = decl->BindingPoint(); ast::VariableBindingPoint bp = decl->BindingPoint();
line() << "layout(binding = " << bp.binding->value << ") uniform " {
<< UniqueIdentifier(StructName(str)) << " {"; auto out = line();
EmitStructMembers(current_buffer_, str); out << "layout(binding = " << bp.binding->value;
if (version_.IsDesktop()) {
out << ", std140";
}
out << ") uniform " << UniqueIdentifier(StructName(str)) << " {";
}
EmitStructMembers(current_buffer_, str, /* emit_offsets */ true);
auto name = builder_.Symbols().NameFor(decl->symbol); auto name = builder_.Symbols().NameFor(decl->symbol);
line() << "} " << name << ";"; line() << "} " << name << ";";
line(); line();
@ -1751,7 +1765,7 @@ bool GeneratorImpl::EmitStorageVariable(const sem::Variable* var) {
ast::VariableBindingPoint bp = decl->BindingPoint(); ast::VariableBindingPoint bp = decl->BindingPoint();
line() << "layout(binding = " << bp.binding->value << ", std430) buffer " line() << "layout(binding = " << bp.binding->value << ", std430) buffer "
<< UniqueIdentifier(StructName(str)) << " {"; << UniqueIdentifier(StructName(str)) << " {";
EmitStructMembers(current_buffer_, str); EmitStructMembers(current_buffer_, str, /* emit_offsets */ true);
auto name = builder_.Symbols().NameFor(decl->symbol); auto name = builder_.Symbols().NameFor(decl->symbol);
line() << "} " << name << ";"; line() << "} " << name << ";";
return true; return true;
@ -2509,14 +2523,16 @@ bool GeneratorImpl::EmitTypeAndName(std::ostream& out,
bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) { bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
auto storage_class_uses = str->StorageClassUsage(); auto storage_class_uses = str->StorageClassUsage();
line(b) << "struct " << StructName(str) << " {"; line(b) << "struct " << StructName(str) << " {";
EmitStructMembers(b, str); EmitStructMembers(b, str, false);
line(b) << "};"; line(b) << "};";
line(b); line(b);
return true; return true;
} }
bool GeneratorImpl::EmitStructMembers(TextBuffer* b, const sem::Struct* str) { bool GeneratorImpl::EmitStructMembers(TextBuffer* b,
const sem::Struct* str,
bool emit_offsets) {
ScopedIndent si(b); ScopedIndent si(b);
for (auto* mem : str->Members()) { for (auto* mem : str->Members()) {
auto name = builder_.Symbols().NameFor(mem->Name()); auto name = builder_.Symbols().NameFor(mem->Name());
@ -2525,6 +2541,10 @@ bool GeneratorImpl::EmitStructMembers(TextBuffer* b, const sem::Struct* str) {
auto out = line(b); auto out = line(b);
// Note: offsets are unsupported on GLSL ES.
if (emit_offsets && version_.IsDesktop() && mem->Offset() != 0) {
out << "layout(offset=" << mem->Offset() << ") ";
}
if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone, if (!EmitTypeAndName(out, ty, ast::StorageClass::kNone,
ast::Access::kReadWrite, name)) { ast::Access::kReadWrite, name)) {
return false; return false;

View File

@ -35,6 +35,7 @@
#include "src/scope_stack.h" #include "src/scope_stack.h"
#include "src/transform/decompose_memory_access.h" #include "src/transform/decompose_memory_access.h"
#include "src/utils/hash.h" #include "src/utils/hash.h"
#include "src/writer/glsl/version.h"
#include "src/writer/text_generator.h" #include "src/writer/text_generator.h"
namespace tint { namespace tint {
@ -55,7 +56,8 @@ class GeneratorImpl : public TextGenerator {
public: public:
/// Constructor /// Constructor
/// @param program the program to generate /// @param program the program to generate
explicit GeneratorImpl(const Program* program); /// @param version the GLSL version to use
GeneratorImpl(const Program* program, const Version& version);
~GeneratorImpl(); ~GeneratorImpl();
/// @returns true on successful generation; false otherwise /// @returns true on successful generation; false otherwise
@ -388,8 +390,11 @@ class GeneratorImpl : public TextGenerator {
/// Handles generating the members of a structure /// Handles generating the members of a structure
/// @param buffer the text buffer that the struct members will be written to /// @param buffer the text buffer that the struct members will be written to
/// @param ty the struct to generate /// @param ty the struct to generate
/// @param emit_offsets whether offsets should be emitted as offset=
/// @returns true if the struct members are emitted /// @returns true if the struct members are emitted
bool EmitStructMembers(TextBuffer* buffer, const sem::Struct* ty); bool EmitStructMembers(TextBuffer* buffer,
const sem::Struct* ty,
bool emit_offsets);
/// Handles a unary op expression /// Handles a unary op expression
/// @param out the output of the expression stream /// @param out the output of the expression stream
/// @param expr the expression to emit /// @param expr the expression to emit
@ -475,6 +480,7 @@ class GeneratorImpl : public TextGenerator {
std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_; std::unordered_map<const sem::Vector*, std::string> int_dot_funcs_;
bool requires_oes_sample_variables_ = false; bool requires_oes_sample_variables_ = false;
bool requires_default_precision_qualifier_ = false; bool requires_default_precision_qualifier_ = false;
Version version_;
}; };
} // namespace glsl } // namespace glsl

View File

@ -0,0 +1,97 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gmock/gmock.h"
#include "src/writer/glsl/test_helper.h"
using ::testing::HasSubstr;
namespace tint {
namespace writer {
namespace glsl {
namespace {
using GlslGeneratorImplTest_StorageBuffer = TestHelper;
void TestAlign(ProgramBuilder* ctx) {
// struct Nephews {
// @align(256) huey : f32;
// @align(256) dewey : f32;
// @align(256) louie : f32;
// };
// @group(0) @binding(0) var<storage, read_write> nephews : Nephews;
auto* nephews = ctx->Structure(
"Nephews",
{
ctx->Member("huey", ctx->ty.f32(), {ctx->MemberAlign(256)}),
ctx->Member("dewey", ctx->ty.f32(), {ctx->MemberAlign(256)}),
ctx->Member("louie", ctx->ty.f32(), {ctx->MemberAlign(256)}),
});
ctx->Global("nephews", ctx->ty.Of(nephews), ast::StorageClass::kStorage,
ast::AttributeList{
ctx->create<ast::BindingAttribute>(0),
ctx->create<ast::GroupAttribute>(0),
});
}
TEST_F(GlslGeneratorImplTest_StorageBuffer, Align) {
TestAlign(this);
GeneratorImpl& gen = Build();
// TODO(crbug.com/tint/1421) offsets do not currently work on GLSL ES.
// They will likely require manual padding.
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
struct Nephews {
float huey;
float dewey;
float louie;
};
layout(binding = 0, std430) buffer Nephews_1 {
float huey;
float dewey;
float louie;
} nephews;
)");
}
TEST_F(GlslGeneratorImplTest_StorageBuffer, Align_Desktop) {
TestAlign(this);
GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 440
struct Nephews {
float huey;
float dewey;
float louie;
};
layout(binding = 0, std430) buffer Nephews_1 {
float huey;
layout(offset=256) float dewey;
layout(offset=512) float louie;
} nephews;
)");
}
} // namespace
} // namespace glsl
} // namespace writer
} // namespace tint

View File

@ -36,6 +36,64 @@ void my_func() {
)"); )");
} }
TEST_F(GlslGeneratorImplTest, GenerateDesktop) {
Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::AttributeList{});
GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 440
void my_func() {
}
)");
}
TEST_F(GlslGeneratorImplTest, GenerateSampleIndexES) {
Global(
"gl_SampleID", ty.i32(),
ast::AttributeList{Builtin(ast::Builtin::kSampleIndex),
Disable(ast::DisabledValidation::kIgnoreStorageClass)},
ast::StorageClass::kInput);
Func("my_func", {}, ty.i32(),
ast::StatementList{Return(Expr("gl_SampleID"))});
GeneratorImpl& gen = Build(Version(Version::Standard::kES, 3, 1));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
#extension GL_OES_sample_variables : require
int my_func() {
return gl_SampleID;
}
)");
}
TEST_F(GlslGeneratorImplTest, GenerateSampleIndexDesktop) {
Global(
"gl_SampleID", ty.i32(),
ast::AttributeList{Builtin(ast::Builtin::kSampleIndex),
Disable(ast::DisabledValidation::kIgnoreStorageClass)},
ast::StorageClass::kInput);
Func("my_func", {}, ty.i32(),
ast::StatementList{Return(Expr("gl_SampleID"))});
GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 440
int my_func() {
return gl_SampleID;
}
)");
}
} // namespace } // namespace
} // namespace glsl } // namespace glsl
} // namespace writer } // namespace writer

View File

@ -0,0 +1,72 @@
// Copyright 2022 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gmock/gmock.h"
#include "src/writer/glsl/test_helper.h"
using ::testing::HasSubstr;
namespace tint {
namespace writer {
namespace glsl {
namespace {
using GlslGeneratorImplTest_UniformBuffer = TestHelper;
TEST_F(GlslGeneratorImplTest_UniformBuffer, Simple) {
auto* simple = Structure("Simple", {Member("member", ty.f32())});
Global("simple", ty.Of(simple), ast::StorageClass::kUniform,
GroupAndBinding(0, 0));
GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 310 es
struct Simple {
float member;
};
layout(binding = 0) uniform Simple_1 {
float member;
} simple;
)");
}
TEST_F(GlslGeneratorImplTest_UniformBuffer, Simple_Desktop) {
auto* simple = Structure("Simple", {Member("member", ty.f32())});
Global("simple", ty.Of(simple), ast::StorageClass::kUniform,
GroupAndBinding(0, 0));
GeneratorImpl& gen = Build(Version(Version::Standard::kDesktop, 4, 4));
ASSERT_TRUE(gen.Generate()) << gen.error();
EXPECT_EQ(gen.result(), R"(#version 440
struct Simple {
float member;
};
layout(binding = 0, std140) uniform Simple_1 {
float member;
} simple;
)");
}
} // namespace
} // namespace glsl
} // namespace writer
} // namespace tint

View File

@ -39,8 +39,9 @@ class TestHelperBase : public BODY, public ProgramBuilder {
/// Builds the program and returns a GeneratorImpl from the program. /// Builds the program and returns a GeneratorImpl from the program.
/// @note The generator is only built once. Multiple calls to Build() will /// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding. /// return the same GeneratorImpl without rebuilding.
/// @param version the GLSL version
/// @return the built generator /// @return the built generator
GeneratorImpl& Build() { GeneratorImpl& Build(Version version = Version()) {
if (gen_) { if (gen_) {
return *gen_; return *gen_;
} }
@ -53,7 +54,7 @@ class TestHelperBase : public BODY, public ProgramBuilder {
ASSERT_TRUE(program->IsValid()) ASSERT_TRUE(program->IsValid())
<< diag::Formatter().format(program->Diagnostics()); << diag::Formatter().format(program->Diagnostics());
}(); }();
gen_ = std::make_unique<GeneratorImpl>(program.get()); gen_ = std::make_unique<GeneratorImpl>(program.get(), version);
return *gen_; return *gen_;
} }
@ -61,8 +62,9 @@ class TestHelperBase : public BODY, public ProgramBuilder {
/// and returns a GeneratorImpl from the sanitized program. /// and returns a GeneratorImpl from the sanitized program.
/// @note The generator is only built once. Multiple calls to Build() will /// @note The generator is only built once. Multiple calls to Build() will
/// return the same GeneratorImpl without rebuilding. /// return the same GeneratorImpl without rebuilding.
/// @param version the GLSL version
/// @return the built generator /// @return the built generator
GeneratorImpl& SanitizeAndBuild() { GeneratorImpl& SanitizeAndBuild(Version version = Version()) {
if (gen_) { if (gen_) {
return *gen_; return *gen_;
} }
@ -89,7 +91,7 @@ class TestHelperBase : public BODY, public ProgramBuilder {
<< formatter.format(result.program.Diagnostics()); << formatter.format(result.program.Diagnostics());
}(); }();
*program = std::move(result.program); *program = std::move(result.program);
gen_ = std::make_unique<GeneratorImpl>(program.get()); gen_ = std::make_unique<GeneratorImpl>(program.get(), version);
return *gen_; return *gen_;
} }

56
src/writer/glsl/version.h Normal file
View File

@ -0,0 +1,56 @@
// Copyright 2022 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.
#ifndef SRC_WRITER_GLSL_VERSION_H_
#define SRC_WRITER_GLSL_VERSION_H_
namespace tint::writer::glsl {
/// A structure representing the version of GLSL to be generated.
struct Version {
/// Is this version desktop GLSL, or GLSL ES?
enum class Standard {
kDesktop,
kES,
};
/// Constructor
/// @param standard_ Desktop or ES
/// @param major_ the major version
/// @param minor_ the minor version
Version(Standard standard_, uint32_t major_, uint32_t minor_)
: standard(standard_), major_version(major_), minor_version(minor_) {}
/// Default constructor (see default values below)
Version() = default;
/// @returns true if this version is GLSL ES
bool IsES() const { return standard == Standard::kES; }
/// @returns true if this version is Desktop GLSL
bool IsDesktop() const { return standard == Standard::kDesktop; }
/// Desktop or ES
Standard standard = Standard::kES;
/// Major GLSL version
uint32_t major_version = 3;
/// Minor GLSL version
uint32_t minor_version = 1;
};
} // namespace tint::writer::glsl
#endif // SRC_WRITER_GLSL_VERSION_H_

View File

@ -237,15 +237,15 @@ tint_unittests_source_set("tint_unittests_resolver_src") {
"../src/resolver/assignment_validation_test.cc", "../src/resolver/assignment_validation_test.cc",
"../src/resolver/atomics_test.cc", "../src/resolver/atomics_test.cc",
"../src/resolver/atomics_validation_test.cc", "../src/resolver/atomics_validation_test.cc",
"../src/resolver/attribute_validation_test.cc",
"../src/resolver/bitcast_validation_test.cc", "../src/resolver/bitcast_validation_test.cc",
"../src/resolver/builtins_validation_test.cc",
"../src/resolver/builtin_test.cc", "../src/resolver/builtin_test.cc",
"../src/resolver/builtin_validation_test.cc", "../src/resolver/builtin_validation_test.cc",
"../src/resolver/builtins_validation_test.cc",
"../src/resolver/call_test.cc", "../src/resolver/call_test.cc",
"../src/resolver/call_validation_test.cc", "../src/resolver/call_validation_test.cc",
"../src/resolver/compound_statement_test.cc", "../src/resolver/compound_statement_test.cc",
"../src/resolver/control_block_validation_test.cc", "../src/resolver/control_block_validation_test.cc",
"../src/resolver/attribute_validation_test.cc",
"../src/resolver/dependency_graph_test.cc", "../src/resolver/dependency_graph_test.cc",
"../src/resolver/entry_point_validation_test.cc", "../src/resolver/entry_point_validation_test.cc",
"../src/resolver/function_validation_test.cc", "../src/resolver/function_validation_test.cc",
@ -473,9 +473,9 @@ tint_unittests_source_set("tint_unittests_wgsl_reader_src") {
"../src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc", "../src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc",
"../src/reader/wgsl/parser_impl_external_texture_type_test.cc", "../src/reader/wgsl/parser_impl_external_texture_type_test.cc",
"../src/reader/wgsl/parser_impl_for_stmt_test.cc", "../src/reader/wgsl/parser_impl_for_stmt_test.cc",
"../src/reader/wgsl/parser_impl_function_decl_test.cc",
"../src/reader/wgsl/parser_impl_function_attribute_list_test.cc", "../src/reader/wgsl/parser_impl_function_attribute_list_test.cc",
"../src/reader/wgsl/parser_impl_function_attribute_test.cc", "../src/reader/wgsl/parser_impl_function_attribute_test.cc",
"../src/reader/wgsl/parser_impl_function_decl_test.cc",
"../src/reader/wgsl/parser_impl_function_header_test.cc", "../src/reader/wgsl/parser_impl_function_header_test.cc",
"../src/reader/wgsl/parser_impl_global_constant_decl_test.cc", "../src/reader/wgsl/parser_impl_global_constant_decl_test.cc",
"../src/reader/wgsl/parser_impl_global_decl_test.cc", "../src/reader/wgsl/parser_impl_global_decl_test.cc",
@ -500,10 +500,10 @@ tint_unittests_source_set("tint_unittests_wgsl_reader_src") {
"../src/reader/wgsl/parser_impl_statements_test.cc", "../src/reader/wgsl/parser_impl_statements_test.cc",
"../src/reader/wgsl/parser_impl_storage_class_test.cc", "../src/reader/wgsl/parser_impl_storage_class_test.cc",
"../src/reader/wgsl/parser_impl_storage_texture_type_test.cc", "../src/reader/wgsl/parser_impl_storage_texture_type_test.cc",
"../src/reader/wgsl/parser_impl_struct_body_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_attribute_decl_test.cc", "../src/reader/wgsl/parser_impl_struct_attribute_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_attribute_test.cc", "../src/reader/wgsl/parser_impl_struct_attribute_test.cc",
"../src/reader/wgsl/parser_impl_struct_body_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_member_attribute_decl_test.cc", "../src/reader/wgsl/parser_impl_struct_member_attribute_decl_test.cc",
"../src/reader/wgsl/parser_impl_struct_member_attribute_test.cc", "../src/reader/wgsl/parser_impl_struct_member_attribute_test.cc",
"../src/reader/wgsl/parser_impl_struct_member_test.cc", "../src/reader/wgsl/parser_impl_struct_member_test.cc",
@ -517,9 +517,9 @@ tint_unittests_source_set("tint_unittests_wgsl_reader_src") {
"../src/reader/wgsl/parser_impl_type_alias_test.cc", "../src/reader/wgsl/parser_impl_type_alias_test.cc",
"../src/reader/wgsl/parser_impl_type_decl_test.cc", "../src/reader/wgsl/parser_impl_type_decl_test.cc",
"../src/reader/wgsl/parser_impl_unary_expression_test.cc", "../src/reader/wgsl/parser_impl_unary_expression_test.cc",
"../src/reader/wgsl/parser_impl_variable_decl_test.cc",
"../src/reader/wgsl/parser_impl_variable_attribute_list_test.cc", "../src/reader/wgsl/parser_impl_variable_attribute_list_test.cc",
"../src/reader/wgsl/parser_impl_variable_attribute_test.cc", "../src/reader/wgsl/parser_impl_variable_attribute_test.cc",
"../src/reader/wgsl/parser_impl_variable_decl_test.cc",
"../src/reader/wgsl/parser_impl_variable_ident_decl_test.cc", "../src/reader/wgsl/parser_impl_variable_ident_decl_test.cc",
"../src/reader/wgsl/parser_impl_variable_qualifier_test.cc", "../src/reader/wgsl/parser_impl_variable_qualifier_test.cc",
"../src/reader/wgsl/parser_impl_variable_stmt_test.cc", "../src/reader/wgsl/parser_impl_variable_stmt_test.cc",
@ -674,10 +674,12 @@ tint_unittests_source_set("tint_unittests_glsl_writer_src") {
"../src/writer/glsl/generator_impl_module_constant_test.cc", "../src/writer/glsl/generator_impl_module_constant_test.cc",
"../src/writer/glsl/generator_impl_return_test.cc", "../src/writer/glsl/generator_impl_return_test.cc",
"../src/writer/glsl/generator_impl_sanitizer_test.cc", "../src/writer/glsl/generator_impl_sanitizer_test.cc",
"../src/writer/glsl/generator_impl_storage_buffer_test.cc",
"../src/writer/glsl/generator_impl_switch_test.cc", "../src/writer/glsl/generator_impl_switch_test.cc",
"../src/writer/glsl/generator_impl_test.cc", "../src/writer/glsl/generator_impl_test.cc",
"../src/writer/glsl/generator_impl_type_test.cc", "../src/writer/glsl/generator_impl_type_test.cc",
"../src/writer/glsl/generator_impl_unary_op_test.cc", "../src/writer/glsl/generator_impl_unary_op_test.cc",
"../src/writer/glsl/generator_impl_uniform_buffer_test.cc",
"../src/writer/glsl/generator_impl_variable_decl_statement_test.cc", "../src/writer/glsl/generator_impl_variable_decl_statement_test.cc",
"../src/writer/glsl/generator_impl_workgroup_var_test.cc", "../src/writer/glsl/generator_impl_workgroup_var_test.cc",
"../src/writer/glsl/test_helper.h", "../src/writer/glsl/test_helper.h",