tint: Support multiple extensions per 'enable'

Fixed: tint:1865
Change-Id: I245bd36b12ff23977c2e69deee27f976db820849
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/123900
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2023-03-15 05:06:57 +00:00 committed by Dawn LUCI CQ
parent 0089d47887
commit 8f80d999c4
27 changed files with 439 additions and 88 deletions

View File

@ -495,6 +495,7 @@ libtint_source_set("libtint_ast_hdrs") {
"ast/discard_statement.h",
"ast/enable.h",
"ast/expression.h",
"ast/extension.h",
"ast/float_literal_expression.h",
"ast/for_loop_statement.h",
"ast/function.h",
@ -581,6 +582,7 @@ libtint_source_set("libtint_ast_src") {
"ast/discard_statement.cc",
"ast/enable.cc",
"ast/expression.cc",
"ast/extension.cc",
"ast/float_literal_expression.cc",
"ast/for_loop_statement.cc",
"ast/function.cc",

View File

@ -134,6 +134,8 @@ list(APPEND TINT_LIB_SRCS
ast/enable.h
ast/expression.cc
ast/expression.h
ast/extension.cc
ast/extension.h
ast/float_literal_expression.cc
ast/float_literal_expression.h
ast/for_loop_statement.cc

View File

@ -20,15 +20,29 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Enable);
namespace tint::ast {
Enable::Enable(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext)
: Base(pid, nid, src), extension(ext) {}
Enable::Enable(ProgramID pid,
NodeID nid,
const Source& src,
utils::VectorRef<const Extension*> exts)
: Base(pid, nid, src), extensions(std::move(exts)) {}
Enable::Enable(Enable&&) = default;
Enable::~Enable() = default;
bool Enable::HasExtension(builtin::Extension ext) const {
for (auto* e : extensions) {
if (e->name == ext) {
return true;
}
}
return false;
}
const Enable* Enable::Clone(CloneContext* ctx) const {
auto src = ctx->Clone(source);
return ctx->dst->create<Enable>(src, extension);
auto exts = ctx->Clone(extensions);
return ctx->dst->create<Enable>(src, std::move(exts));
}
} // namespace tint::ast

View File

@ -19,8 +19,7 @@
#include <utility>
#include <vector>
#include "src/tint/ast/node.h"
#include "src/tint/builtin/extension.h"
#include "src/tint/ast/extension.h"
namespace tint::ast {
@ -35,21 +34,24 @@ class Enable final : public Castable<Enable, Node> {
/// @param pid the identifier of the program that owns this node
/// @param nid the unique node identifier
/// @param src the source of this node
/// @param ext the extension
Enable(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext);
/// @param exts the extensions being enabled by this directive
Enable(ProgramID pid, NodeID nid, const Source& src, utils::VectorRef<const Extension*> exts);
/// Move constructor
Enable(Enable&&);
~Enable() override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ext the extension to search for
/// @returns true if this Enable lists the given extension
bool HasExtension(builtin::Extension ext) const;
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const Enable* Clone(CloneContext* ctx) const override;
/// The extension name
const builtin::Extension extension;
/// The extensions being enabled by this directive
const utils::Vector<const Extension*, 4> extensions;
};
} // namespace tint::ast

View File

@ -27,7 +27,14 @@ TEST_F(EnableTest, Creation) {
EXPECT_EQ(ext->source.range.begin.column, 2u);
EXPECT_EQ(ext->source.range.end.line, 20u);
EXPECT_EQ(ext->source.range.end.column, 5u);
EXPECT_EQ(ext->extension, builtin::Extension::kF16);
ASSERT_EQ(ext->extensions.Length(), 1u);
EXPECT_EQ(ext->extensions[0]->name, builtin::Extension::kF16);
}
TEST_F(EnableTest, HasExtension) {
auto* ext = Enable(Source{{{20, 2}, {20, 5}}}, builtin::Extension::kF16);
EXPECT_TRUE(ext->HasExtension(builtin::Extension::kF16));
EXPECT_FALSE(ext->HasExtension(builtin::Extension::kChromiumDisableUniformityAnalysis));
}
} // namespace

40
src/tint/ast/extension.cc Normal file
View File

@ -0,0 +1,40 @@
// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/ast/extension.h"
#include "src/tint/program_builder.h"
//! @cond Doxygen_Suppress
// Doxygen gets confused with tint::ast::Extension and tint::builtin::Extension
TINT_INSTANTIATE_TYPEINFO(tint::ast::Extension);
namespace tint::ast {
Extension::Extension(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext)
: Base(pid, nid, src), name(ext) {}
Extension::Extension(Extension&&) = default;
Extension::~Extension() = default;
const Extension* Extension::Clone(CloneContext* ctx) const {
auto src = ctx->Clone(source);
return ctx->dst->create<Extension>(src, name);
}
} // namespace tint::ast
//! @endcond

52
src/tint/ast/extension.h Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2023 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_TINT_AST_EXTENSION_H_
#define SRC_TINT_AST_EXTENSION_H_
#include "src/tint/ast/node.h"
#include "src/tint/builtin/extension.h"
namespace tint::ast {
/// An extension used in an "enable" directive. Example:
/// ```
/// enable f16;
/// ```
class Extension final : public Castable<Extension, Node> {
public:
/// Create a extension
/// @param pid the identifier of the program that owns this node
/// @param nid the unique node identifier
/// @param src the source of this node
/// @param ext the extension
Extension(ProgramID pid, NodeID nid, const Source& src, builtin::Extension ext);
/// Move constructor
Extension(Extension&&);
~Extension() override;
/// Clones this node and all transitive child nodes using the `CloneContext`
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
const Extension* Clone(CloneContext* ctx) const override;
/// The extension name
const builtin::Extension name;
};
} // namespace tint::ast
#endif // SRC_TINT_AST_EXTENSION_H_

View File

@ -755,8 +755,8 @@ bool GenerateHlsl(const tint::Program* program, const Options& options) {
auto enable_list = program->AST().Enables();
bool dxc_require_16bit_types = false;
for (auto enable : enable_list) {
if (enable->extension == tint::builtin::Extension::kF16) {
for (auto* enable : enable_list) {
if (enable->HasExtension(tint::builtin::Extension::kF16)) {
dxc_require_16bit_types = true;
break;
}

View File

@ -571,8 +571,10 @@ std::vector<std::pair<std::string, Source>> Inspector::GetEnableDirectives() {
// Ast nodes for enable directive are stored within global declarations list
auto global_decls = program_->AST().GlobalDeclarations();
for (auto* node : global_decls) {
if (auto* ext = node->As<ast::Enable>()) {
result.push_back({utils::ToString(ext->extension), ext->source});
if (auto* enable = node->As<ast::Enable>()) {
for (auto* ext : enable->extensions) {
result.push_back({utils::ToString(ext->name), ext->source});
}
}
}

View File

@ -2048,20 +2048,22 @@ class ProgramBuilder {
}
/// Adds the extension to the list of enable directives at the top of the module.
/// @param ext the extension to enable
/// @param extension the extension to enable
/// @return an `ast::Enable` enabling the given extension.
const ast::Enable* Enable(builtin::Extension ext) {
auto* enable = create<ast::Enable>(ext);
const ast::Enable* Enable(builtin::Extension extension) {
auto* ext = create<ast::Extension>(extension);
auto* enable = create<ast::Enable>(utils::Vector{ext});
AST().AddEnable(enable);
return enable;
}
/// Adds the extension to the list of enable directives at the top of the module.
/// @param source the enable source
/// @param ext the extension to enable
/// @param extension the extension to enable
/// @return an `ast::Enable` enabling the given extension.
const ast::Enable* Enable(const Source& source, builtin::Extension ext) {
auto* enable = create<ast::Enable>(source, ext);
const ast::Enable* Enable(const Source& source, builtin::Extension extension) {
auto* ext = create<ast::Extension>(source, extension);
auto* enable = create<ast::Enable>(source, utils::Vector{ext});
AST().AddEnable(enable);
return enable;
}

View File

@ -390,53 +390,52 @@ Maybe<Void> ParserImpl::diagnostic_directive() {
return decl;
}
// enable_directive
// : enable name SEMICLON
// enable_directive :
// | 'enable' identifier (COMMA identifier)* COMMA? SEMICOLON
Maybe<Void> ParserImpl::enable_directive() {
auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
return sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
MultiTokenSource decl_source(this);
if (!match(Token::Type::kEnable)) {
return Failure::kNoMatch;
}
// Match the extension name.
auto& t = peek();
if (handle_error(t)) {
// The token might itself be an error.
return Failure::kErrored;
}
if (t.Is(Token::Type::kParenLeft)) {
if (peek_is(Token::Type::kParenLeft)) {
// A common error case is writing `enable(foo);` instead of `enable foo;`.
synchronized_ = false;
return add_error(t.source(), "enable directives don't take parenthesis");
return add_error(peek().source(), "enable directives don't take parenthesis");
}
auto ext = expect_enum("extension", builtin::ParseExtension, builtin::kExtensionStrings);
if (ext.errored) {
return Failure::kErrored;
utils::Vector<const ast::Extension*, 4> extensions;
while (continue_parsing()) {
Source ext_src = peek().source();
auto ext =
expect_enum("extension", builtin::ParseExtension, builtin::kExtensionStrings);
if (ext.errored) {
return Failure::kErrored;
}
extensions.Push(create<ast::Extension>(ext_src, ext.value));
if (!match(Token::Type::kComma)) {
break;
}
if (peek_is(Token::Type::kSemicolon)) {
break;
}
}
if (!expect("enable directive", Token::Type::kSemicolon)) {
return Failure::kErrored;
}
builder_.AST().AddEnable(create<ast::Enable>(t.source(), ext.value));
builder_.AST().AddEnable(create<ast::Enable>(decl_source.Source(), std::move(extensions)));
return kSuccess;
});
if (decl.errored) {
return Failure::kErrored;
}
if (decl.matched) {
return kSuccess;
}
return Failure::kNoMatch;
}
// requires_directive
// : require identifier (COMMA identifier)? SEMICLON
// : require identifier (COMMA identifier)* COMMA? SEMICOLON
Maybe<Void> ParserImpl::requires_directive() {
auto decl = sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
return sync(Token::Type::kSemicolon, [&]() -> Maybe<Void> {
if (!match(Token::Type::kRequires)) {
return Failure::kNoMatch;
}
@ -483,15 +482,6 @@ Maybe<Void> ParserImpl::requires_directive() {
// conditional.
return add_error(t.source(), "missing feature names in requires directive");
});
if (decl.errored) {
return Failure::kErrored;
}
if (decl.matched) {
return kSuccess;
}
return Failure::kNoMatch;
}
// global_decl

View File

@ -22,7 +22,7 @@ namespace {
using EnableDirectiveTest = ParserImplTest;
// Test a valid enable directive.
TEST_F(EnableDirectiveTest, Valid) {
TEST_F(EnableDirectiveTest, Single) {
auto p = parser("enable f16;");
p->enable_directive();
EXPECT_FALSE(p->has_error()) << p->error();
@ -30,13 +30,105 @@ TEST_F(EnableDirectiveTest, Valid) {
auto& ast = program.AST();
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
EXPECT_EQ(enable->extension, builtin::Extension::kF16);
EXPECT_EQ(enable->source.range.begin.line, 1u);
EXPECT_EQ(enable->source.range.begin.column, 1u);
EXPECT_EQ(enable->source.range.end.line, 1u);
EXPECT_EQ(enable->source.range.end.column, 12u);
ASSERT_EQ(enable->extensions.Length(), 1u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
// Test a valid enable directive.
TEST_F(EnableDirectiveTest, SingleTrailingComma) {
auto p = parser("enable f16, ;");
p->enable_directive();
EXPECT_FALSE(p->has_error()) << p->error();
auto program = p->program();
auto& ast = program.AST();
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
EXPECT_EQ(enable->source.range.begin.line, 1u);
EXPECT_EQ(enable->source.range.begin.column, 1u);
EXPECT_EQ(enable->source.range.end.line, 1u);
EXPECT_EQ(enable->source.range.end.column, 14u);
ASSERT_EQ(enable->extensions.Length(), 1u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
// Test a valid enable directive with multiple extensions.
TEST_F(EnableDirectiveTest, Multiple) {
auto p =
parser("enable f16, chromium_disable_uniformity_analysis, chromium_experimental_dp4a;");
p->enable_directive();
EXPECT_FALSE(p->has_error()) << p->error();
auto program = p->program();
auto& ast = program.AST();
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
ASSERT_EQ(enable->extensions.Length(), 3u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
EXPECT_EQ(enable->extensions[1]->name, builtin::Extension::kChromiumDisableUniformityAnalysis);
EXPECT_EQ(enable->extensions[1]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[1]->source.range.begin.column, 13u);
EXPECT_EQ(enable->extensions[1]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[1]->source.range.end.column, 49u);
EXPECT_EQ(enable->extensions[2]->name, builtin::Extension::kChromiumExperimentalDp4A);
EXPECT_EQ(enable->extensions[2]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[2]->source.range.begin.column, 51u);
EXPECT_EQ(enable->extensions[2]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[2]->source.range.end.column, 77u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
// Test a valid enable directive with multiple extensions.
TEST_F(EnableDirectiveTest, MultipleTrailingComma) {
auto p =
parser("enable f16, chromium_disable_uniformity_analysis, chromium_experimental_dp4a,;");
p->enable_directive();
EXPECT_FALSE(p->has_error()) << p->error();
auto program = p->program();
auto& ast = program.AST();
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
ASSERT_EQ(enable->extensions.Length(), 3u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
EXPECT_EQ(enable->extensions[1]->name, builtin::Extension::kChromiumDisableUniformityAnalysis);
EXPECT_EQ(enable->extensions[1]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[1]->source.range.begin.column, 13u);
EXPECT_EQ(enable->extensions[1]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[1]->source.range.end.column, 49u);
EXPECT_EQ(enable->extensions[2]->name, builtin::Extension::kChromiumExperimentalDp4A);
EXPECT_EQ(enable->extensions[2]->source.range.begin.line, 1u);
EXPECT_EQ(enable->extensions[2]->source.range.begin.column, 51u);
EXPECT_EQ(enable->extensions[2]->source.range.end.line, 1u);
EXPECT_EQ(enable->extensions[2]->source.range.end.column, 77u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}
// Test multiple enable directives for a same extension.
TEST_F(EnableDirectiveTest, EnableMultipleTime) {
TEST_F(EnableDirectiveTest, EnableSameLine) {
auto p = parser(R"(
enable f16;
enable f16;
@ -48,8 +140,18 @@ enable f16;
ASSERT_EQ(ast.Enables().Length(), 2u);
auto* enable_a = ast.Enables()[0];
auto* enable_b = ast.Enables()[1];
EXPECT_EQ(enable_a->extension, builtin::Extension::kF16);
EXPECT_EQ(enable_b->extension, builtin::Extension::kF16);
ASSERT_EQ(enable_a->extensions.Length(), 1u);
EXPECT_EQ(enable_a->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable_a->extensions[0]->source.range.begin.line, 2u);
EXPECT_EQ(enable_a->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable_a->extensions[0]->source.range.end.line, 2u);
EXPECT_EQ(enable_a->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(enable_b->extensions.Length(), 1u);
EXPECT_EQ(enable_b->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable_b->extensions[0]->source.range.begin.line, 3u);
EXPECT_EQ(enable_b->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable_b->extensions[0]->source.range.end.line, 3u);
EXPECT_EQ(enable_b->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable_a);
EXPECT_EQ(ast.GlobalDeclarations()[1], enable_b);
@ -169,7 +271,12 @@ enable f16;
// Accept the enable directive although it caused an error
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
EXPECT_EQ(enable->extension, builtin::Extension::kF16);
ASSERT_EQ(enable->extensions.Length(), 1u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 3u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 3u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 2u);
EXPECT_EQ(ast.GlobalDeclarations()[1], enable);
}
@ -189,7 +296,12 @@ enable f16;
// Accept the enable directive although it cause an error
ASSERT_EQ(ast.Enables().Length(), 1u);
auto* enable = ast.Enables()[0];
EXPECT_EQ(enable->extension, builtin::Extension::kF16);
ASSERT_EQ(enable->extensions.Length(), 1u);
EXPECT_EQ(enable->extensions[0]->name, builtin::Extension::kF16);
EXPECT_EQ(enable->extensions[0]->source.range.begin.line, 3u);
EXPECT_EQ(enable->extensions[0]->source.range.begin.column, 8u);
EXPECT_EQ(enable->extensions[0]->source.range.end.line, 3u);
EXPECT_EQ(enable->extensions[0]->source.range.end.column, 11u);
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
EXPECT_EQ(ast.GlobalDeclarations()[0], enable);
}

View File

@ -3476,7 +3476,10 @@ bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
}
bool Resolver::Enable(const ast::Enable* enable) {
enabled_extensions_.Add(enable->extension);
for (auto* ext : enable->extensions) {
Mark(ext);
enabled_extensions_.Add(ext->name);
}
return true;
}

View File

@ -47,8 +47,9 @@ struct BuiltinPolyfill::State {
State(const Program* program, const Config& config) : src(program), cfg(config) {
has_full_ptr_params = false;
for (auto* enable : src->AST().Enables()) {
if (enable->extension == builtin::Extension::kChromiumExperimentalFullPtrParameters) {
if (enable->HasExtension(builtin::Extension::kChromiumExperimentalFullPtrParameters)) {
has_full_ptr_params = true;
break;
}
}
}

View File

@ -67,8 +67,8 @@ struct PreservePadding::State {
},
[&](const ast::Enable* enable) {
// Check if the full pointer parameters extension is already enabled.
if (enable->extension ==
builtin::Extension::kChromiumExperimentalFullPtrParameters) {
if (enable->HasExtension(
builtin::Extension::kChromiumExperimentalFullPtrParameters)) {
ext_enabled = true;
}
});

View File

@ -33,13 +33,14 @@ bool CheckSupportedExtensions(std::string_view writer_name,
}
for (auto* enable : module.Enables()) {
auto ext = enable->extension;
if (!set.Contains(ext)) {
diags.add_error(diag::System::Writer,
std::string(writer_name) + " backend does not support extension '" +
utils::ToString(ext) + "'",
enable->source);
return false;
for (auto* ext : enable->extensions) {
if (!set.Contains(ext->name)) {
diags.add_error(diag::System::Writer,
std::string(writer_name) + " backend does not support extension '" +
utils::ToString(ext->name) + "'",
ext->source);
return false;
}
}
}
return true;

View File

@ -347,10 +347,10 @@ bool GeneratorImpl::Generate() {
return true;
}
bool GeneratorImpl::RecordExtension(const ast::Enable* ext) {
bool GeneratorImpl::RecordExtension(const ast::Enable* enable) {
// Deal with extension node here, recording it within the generator for later emition.
if (ext->extension == builtin::Extension::kF16) {
if (enable->HasExtension(builtin::Extension::kF16)) {
requires_f16_extension_ = true;
}

View File

@ -4154,10 +4154,7 @@ OpReturn
namespace DP4A_builtin_tests {
TEST_F(BuiltinBuilderTest, Call_Dot4I8Packed) {
auto* ext =
create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
builtin::Extension::kChromiumExperimentalDp4A);
AST().AddEnable(ext);
Enable(builtin::Extension::kChromiumExperimentalDp4A);
auto* val1 = Var("val1", ty.u32());
auto* val2 = Var("val2", ty.u32());
@ -4194,10 +4191,7 @@ OpFunctionEnd
}
TEST_F(BuiltinBuilderTest, Call_Dot4U8Packed) {
auto* ext =
create<ast::Enable>(Source{Source::Range{Source::Location{10, 2}, Source::Location{10, 5}}},
builtin::Extension::kChromiumExperimentalDp4A);
AST().AddEnable(ext);
Enable(builtin::Extension::kChromiumExperimentalDp4A);
auto* val1 = Var("val1", ty.u32());
auto* val2 = Var("val2", ty.u32());

View File

@ -79,7 +79,15 @@ bool GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnost
}
bool GeneratorImpl::EmitEnable(const ast::Enable* enable) {
line() << "Enable [" << enable->extension << "]";
auto l = line();
l << "Enable [";
for (auto* ext : enable->extensions) {
if (ext != enable->extensions.Front()) {
l << ", ";
}
l << ext->name;
}
l << "]";
return true;
}

View File

@ -100,7 +100,14 @@ bool GeneratorImpl::EmitDiagnosticControl(utils::StringStream& out,
bool GeneratorImpl::EmitEnable(const ast::Enable* enable) {
auto out = line();
out << "enable " << enable->extension << ";";
out << "enable ";
for (auto* ext : enable->extensions) {
if (ext != enable->extensions.Front()) {
out << ", ";
}
out << ext->name;
}
out << ";";
return true;
}

View File

@ -0,0 +1,6 @@
enable chromium_experimental_push_constant, f16;
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4<f32>(0.1, 0.2, 0.3, 0.4);
}

View File

@ -0,0 +1,14 @@
struct tint_symbol {
float4 value : SV_Target0;
};
float4 main_inner() {
return float4(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f, 0.40000000596046447754f);
}
tint_symbol main() {
const float4 inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,14 @@
struct tint_symbol {
float4 value : SV_Target0;
};
float4 main_inner() {
return float4(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f, 0.40000000596046447754f);
}
tint_symbol main() {
const float4 inner_result = main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,14 @@
#version 310 es
#extension GL_AMD_gpu_shader_half_float : require
precision highp float;
layout(location = 0) out vec4 value;
vec4 tint_symbol() {
return vec4(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f, 0.40000000596046447754f);
}
void main() {
vec4 inner_result = tint_symbol();
value = inner_result;
return;
}

View File

@ -0,0 +1,18 @@
#include <metal_stdlib>
using namespace metal;
struct tint_symbol_1 {
float4 value [[color(0)]];
};
float4 tint_symbol_inner() {
return float4(0.10000000149011611938f, 0.20000000298023223877f, 0.30000001192092895508f, 0.40000000596046447754f);
}
fragment tint_symbol_1 tint_symbol() {
float4 const inner_result = tint_symbol_inner();
tint_symbol_1 wrapper_result = {};
wrapper_result.value = inner_result;
return wrapper_result;
}

View File

@ -0,0 +1,40 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 19
; Schema: 0
OpCapability Shader
OpCapability Float16
OpCapability UniformAndStorageBuffer16BitAccess
OpCapability StorageBuffer16BitAccess
OpCapability StorageInputOutput16
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %value
OpExecutionMode %main OriginUpperLeft
OpName %value "value"
OpName %main_inner "main_inner"
OpName %main "main"
OpDecorate %value Location 0
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%_ptr_Output_v4float = OpTypePointer Output %v4float
%5 = OpConstantNull %v4float
%value = OpVariable %_ptr_Output_v4float Output %5
%6 = OpTypeFunction %v4float
%float_0_100000001 = OpConstant %float 0.100000001
%float_0_200000003 = OpConstant %float 0.200000003
%float_0_300000012 = OpConstant %float 0.300000012
%float_0_400000006 = OpConstant %float 0.400000006
%13 = OpConstantComposite %v4float %float_0_100000001 %float_0_200000003 %float_0_300000012 %float_0_400000006
%void = OpTypeVoid
%14 = OpTypeFunction %void
%main_inner = OpFunction %v4float None %6
%8 = OpLabel
OpReturnValue %13
OpFunctionEnd
%main = OpFunction %void None %14
%17 = OpLabel
%18 = OpFunctionCall %v4float %main_inner
OpStore %value %18
OpReturn
OpFunctionEnd

View File

@ -0,0 +1,6 @@
enable chromium_experimental_push_constant, f16;
@fragment
fn main() -> @location(0) vec4<f32> {
return vec4<f32>(0.10000000000000000555, 0.2000000000000000111, 0.2999999999999999889, 0.4000000000000000222);
}