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:
parent
d21ebe74bd
commit
35cc663130
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue