tint/writer: Check extensions are supported

If they're not supported by the backend, print an error that includes the line that enables the extension

Fixed: tint:1678
Change-Id: I3732bfba92a8f96c9e5613c5da6f0e197352508f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105760
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
This commit is contained in:
Ben Clayton 2022-10-14 13:38:27 +00:00 committed by Dawn LUCI CQ
parent aecf1a2ab5
commit 1a567780d9
12 changed files with 214 additions and 0 deletions

View File

@ -585,6 +585,8 @@ libtint_source_set("libtint_core_all_src") {
"writer/append_vector.h",
"writer/array_length_from_uniform_options.cc",
"writer/array_length_from_uniform_options.h",
"writer/check_supported_extensions.cc",
"writer/check_supported_extensions.h",
"writer/flatten_bindings.cc",
"writer/flatten_bindings.h",
"writer/float_to_string.cc",
@ -1271,6 +1273,7 @@ if (tint_build_unittests) {
tint_unittests_source_set("tint_unittests_writer_src") {
sources = [
"writer/append_vector_test.cc",
"writer/check_supported_extensions_test.cc",
"writer/flatten_bindings_test.cc",
"writer/float_to_string_test.cc",
"writer/generate_external_texture_bindings_test.cc",

View File

@ -495,6 +495,8 @@ set(TINT_LIB_SRCS
writer/append_vector.h
writer/array_length_from_uniform_options.cc
writer/array_length_from_uniform_options.h
writer/check_supported_extensions.cc
writer/check_supported_extensions.h
writer/flatten_bindings.cc
writer/flatten_bindings.h
writer/float_to_string.cc
@ -889,6 +891,7 @@ if(TINT_BUILD_TESTS)
utils/unique_vector_test.cc
utils/vector_test.cc
writer/append_vector_test.cc
writer/check_supported_extensions_test.cc
writer/flatten_bindings_test.cc
writer/float_to_string_test.cc
writer/generate_external_texture_bindings_test.cc

View File

@ -1642,6 +1642,16 @@ class ProgramBuilder {
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
/// @return an `ast::Enable` enabling the given extension.
const ast::Enable* Enable(const Source& source, ast::Extension ext) {
auto* enable = create<ast::Enable>(source, ext);
AST().AddEnable(enable);
return enable;
}
/// @param name the variable name
/// @param options the extra options passed to the ast::Var constructor
/// Can be any of the following, in any order:

View File

@ -0,0 +1,48 @@
// 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 "src/tint/writer/check_supported_extensions.h"
#include <string>
#include "src/tint/ast/module.h"
#include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/utils/hashset.h"
#include "src/tint/utils/string.h"
namespace tint::writer {
bool CheckSupportedExtensions(std::string_view writer_name,
const ast::Module& module,
diag::List& diags,
utils::VectorRef<ast::Extension> supported) {
utils::Hashset<ast::Extension, 32> set;
for (auto ext : supported) {
set.Add(ext);
}
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;
}
}
return true;
}
} // namespace tint::writer

View File

@ -0,0 +1,43 @@
// 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_TINT_WRITER_CHECK_SUPPORTED_EXTENSIONS_H_
#define SRC_TINT_WRITER_CHECK_SUPPORTED_EXTENSIONS_H_
#include "src/tint/ast/extension.h"
#include "src/tint/utils/vector.h"
namespace tint::ast {
class Module;
} // namespace tint::ast
namespace tint::diag {
class List;
} // namespace tint::diag
namespace tint::writer {
/// Checks that all the extensions enabled in @p module are found in @p supported, raising an error
/// diagnostic if an enabled extension is not supported.
/// @param writer_name the name of the writer making this call
/// @param module the AST module
/// @param diags the diagnostics to append an error to, if needed.
/// @returns true if all extensions in use are supported, otherwise returns false.
bool CheckSupportedExtensions(std::string_view writer_name,
const ast::Module& module,
diag::List& diags,
utils::VectorRef<ast::Extension> supported);
} // namespace tint::writer
#endif // SRC_TINT_WRITER_CHECK_SUPPORTED_EXTENSIONS_H_

View File

@ -0,0 +1,47 @@
// 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 "src/tint/writer/check_supported_extensions.h"
#include "gtest/gtest.h"
#include "src/tint/program_builder.h"
namespace tint::writer {
namespace {
class CheckSupportedExtensionsTest : public ::testing::Test, public ProgramBuilder {};
TEST_F(CheckSupportedExtensionsTest, Supported) {
Enable(ast::Extension::kF16);
ASSERT_TRUE(CheckSupportedExtensions("writer", AST(), Diagnostics(),
utils::Vector{
ast::Extension::kF16,
ast::Extension::kChromiumExperimentalDp4A,
}));
}
TEST_F(CheckSupportedExtensionsTest, Unsupported) {
Enable(Source{{12, 34}}, ast::Extension::kF16);
ASSERT_FALSE(CheckSupportedExtensions("writer", AST(), Diagnostics(),
utils::Vector{
ast::Extension::kChromiumExperimentalDp4A,
}));
EXPECT_EQ(Diagnostics().str(), "12:34 error: writer backend does not support extension 'f16'");
}
} // namespace
} // namespace tint::writer

View File

@ -72,6 +72,7 @@
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/utils/string.h"
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/check_supported_extensions.h"
#include "src/tint/writer/float_to_string.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
@ -254,6 +255,16 @@ GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
GeneratorImpl::~GeneratorImpl() = default;
bool GeneratorImpl::Generate() {
if (!CheckSupportedExtensions("HLSL", program_->AST(), diagnostics_,
utils::Vector{
ast::Extension::kChromiumDisableUniformityAnalysis,
ast::Extension::kChromiumExperimentalDp4A,
ast::Extension::kChromiumExperimentalPushConstant,
ast::Extension::kF16,
})) {
return false;
}
const TypeInfo* last_kind = nullptr;
size_t last_padding_line = 0;

View File

@ -28,6 +28,15 @@ TEST_F(HlslGeneratorImplTest, InvalidProgram) {
EXPECT_EQ(result.error, "input program is not valid");
}
TEST_F(HlslGeneratorImplTest, UnsupportedExtension) {
Enable(Source{{12, 34}}, ast::Extension::kUndefined);
GeneratorImpl& gen = Build();
ASSERT_FALSE(gen.Generate());
EXPECT_EQ(gen.error(), R"(12:34 error: HLSL backend does not support extension 'undefined')");
}
TEST_F(HlslGeneratorImplTest, Generate) {
Func("my_func", {}, ty.void_(), {});

View File

@ -76,6 +76,7 @@
#include "src/tint/utils/defer.h"
#include "src/tint/utils/map.h"
#include "src/tint/utils/scoped_assignment.h"
#include "src/tint/writer/check_supported_extensions.h"
#include "src/tint/writer/float_to_string.h"
#include "src/tint/writer/generate_external_texture_bindings.h"
@ -278,6 +279,15 @@ GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
GeneratorImpl::~GeneratorImpl() = default;
bool GeneratorImpl::Generate() {
if (!CheckSupportedExtensions("MSL", program_->AST(), diagnostics_,
utils::Vector{
ast::Extension::kChromiumDisableUniformityAnalysis,
ast::Extension::kChromiumExperimentalPushConstant,
ast::Extension::kF16,
})) {
return false;
}
line() << "#include <metal_stdlib>";
line();
line() << "using namespace metal;";

View File

@ -31,6 +31,15 @@ TEST_F(MslGeneratorImplTest, InvalidProgram) {
EXPECT_EQ(result.error, "input program is not valid");
}
TEST_F(MslGeneratorImplTest, UnsupportedExtension) {
Enable(Source{{12, 34}}, ast::Extension::kUndefined);
GeneratorImpl& gen = Build();
ASSERT_FALSE(gen.Generate());
EXPECT_EQ(gen.error(), R"(12:34 error: MSL backend does not support extension 'undefined')");
}
TEST_F(MslGeneratorImplTest, Generate) {
Func("my_func", utils::Empty, ty.void_(), utils::Empty,
utils::Vector{

View File

@ -47,6 +47,7 @@
#include "src/tint/utils/defer.h"
#include "src/tint/utils/map.h"
#include "src/tint/writer/append_vector.h"
#include "src/tint/writer/check_supported_extensions.h"
namespace tint::writer::spirv {
namespace {
@ -259,6 +260,17 @@ Builder::Builder(const Program* program, bool zero_initialize_workgroup_memory)
Builder::~Builder() = default;
bool Builder::Build() {
if (!CheckSupportedExtensions("SPIR-V", builder_.AST(), builder_.Diagnostics(),
utils::Vector{
ast::Extension::kChromiumDisableUniformityAnalysis,
ast::Extension::kChromiumExperimentalDp4A,
ast::Extension::kChromiumExperimentalPushConstant,
ast::Extension::kF16,
})) {
error_ = builder_.Diagnostics().str();
return false;
}
push_capability(SpvCapabilityShader);
push_memory_model(spv::Op::OpMemoryModel,

View File

@ -29,6 +29,15 @@ TEST_F(BuilderTest, InvalidProgram) {
EXPECT_EQ(result.error, "input program is not valid");
}
TEST_F(BuilderTest, UnsupportedExtension) {
Enable(Source{{12, 34}}, ast::Extension::kUndefined);
auto program = std::make_unique<Program>(std::move(*this));
auto result = Generate(program.get(), Options{});
EXPECT_EQ(result.error,
R"(12:34 error: SPIR-V backend does not support extension 'undefined')");
}
TEST_F(BuilderTest, TracksIdBounds) {
spirv::Builder& b = Build();