Import Tint changes from Dawn
Manual fixes:
- Add DXC to DEPS
- Add `dawn_dxc_dir` to `build_overrides/dawn.gni`
- Add TINT_WERROR definition and use it to enable -Werror
Changes:
- 1ea04e752a1f85df223e0ba0d2b049a130167fcb [tint] Avoid using function source in diagnostics by James Price <jrprice@google.com>
- 8a594c537587331be4a3c48d9d53717a5cccf461 [tint][ir][fuzz] Fix ClampFragDepth fuzzer by Ben Clayton <bclayton@google.com>
- 5976efe6b4b72c822085cf7ee08ad00036888ab5 [tint] Link libraries for dlopen by James Price <jrprice@google.com>
- 8752d497a948919675cbd4e7c539b0123211c28c [tint] Fix TINT_BEGIN_DISABLE_ALL_WARNINGS for GCC by James Price <jrprice@google.com>
- 1888e152b77a3870d4c930d0fc2bb0828f9e1ffb [tint][spirv] Remove use of locale by Ben Clayton <bclayton@google.com>
- de601a8efdbbdeb56c97c8d44bc34bba63be4b2c [ir] Add Function::AppendParam() helper by James Price <jrprice@google.com>
- d9ca1a8b1a64c83775ceb4f9274f209b7c86a491 [uniformity] Fix ICE for pointer parameters by James Price <jrprice@google.com>
- 6be95cec0b75d0d08cba9b56f56d4ed4ee5ee64e Refactor Inspector::GetTextureQueries by Shrek Shao <shrekshao@google.com>
- c45c5d233a48501220d4e7252e836590128c72cd [msl] Refactor barrier polyfills by James Price <jrprice@google.com>
- 1450d1d7f79b7f684bdac5196c3e06a86655034f CMake: Compile without -Werror by default. by Corentin Wallez <cwallez@chromium.org>
- d3bebe6cf996439ed197d1c83e323baf8a9a7135 Support Coord Transformation for TextureLoadExternal() by Yan,Shaobo <shaobo.yan@intel.com>
- 4975e45e94803c81563f0c290585a526d4c089d1 [spirv-reader] Handle OpIAdd instructions by James Price <jrprice@google.com>
- 15445d1cbae1fef071af596f4b94faa1a5f7c709 [spirv-reader] Accept DepthReplacing by James Price <jrprice@google.com>
- 92c7dbe391f09d42c2c081b96f00a5cb7bffe34d [tint][exe] Use `lower` when reading SPIR-V to IR by James Price <jrprice@google.com>
- 2ee454636849c6debbc85f147a4cdf9d023ce43d [ir] Fix TINT_DUMP_IR_WHEN_VALIDATING by James Price <jrprice@google.com>
- c410a83088d21c03d94e8058ac727c91364b7220 [tint][ast] Skip ClampFragDepth fuzzer if member offsets ... by Ben Clayton <bclayton@google.com>
- 10d27c4c5ec062424acebd221d57a9fa3a670336 [spirv-reader] Handle OpFMul instructions by James Price <jrprice@google.com>
- 9531d78bcf74288ae6d3ebd1132a15282a793857 [spirv-reader] Handle OpFAdd instructions by James Price <jrprice@google.com>
- 415bd731243a5714a60064648b66f8e4491f47fe [tint][diagnostics] Remove System enum by Ben Clayton <bclayton@google.com>
- 9dc707121317b1c7481f6ae0425c716ab1dc8bbb [tint][diagnostics] Remove ICE / Fatal severities by Ben Clayton <bclayton@google.com>
- 5bd57050e50f0480d7753e9589cd4f28328185fa tint: make FindExecutable look in explicit CWD-prefixed p... by Antonio Maiorano <amaiorano@google.com>
- 5350eb99d6d11d3f4d2bf1942d176277eb043621 hlsl ast fuzzer: validate hlsl with dxc by Antonio Maiorano <amaiorano@google.com>
- 2f84301ccb3e4e2eb67c44b253510466094c4fc9 [tint][ir] Set the File on Disassembly's Sources by Ben Clayton <bclayton@google.com>
- 3aebf9ec38e16b4717aa52382c7f7d47a510efba [tint][ir] Validate value scoping by Ben Clayton <bclayton@google.com>
- c28fff58849a1447fe87e558550561706258e4f4 [tint][fuzz] Support passing fuzz::wgsl::Options to the W... by Ben Clayton <bclayton@google.com>
- 833b892ea02779af23e83a244eaa445b5f4c6eb7 [tint][ir] Validate blocks without using recursion by Ben Clayton <bclayton@google.com>
- 9d2a27af4a05926c5fee2e245883c61b1e6d5bec [tint][ir] Don't use capitalized diagnostic messages by Ben Clayton <bclayton@google.com>
- 35db5b565e3a043b33b05c211447b016edc12acd [tint][ir] Have the Validator use the Disassembly::NameOf() by Ben Clayton <bclayton@google.com>
- aaeb83a4fbcd6d5cf04cf62a837270326c3cf7f7 [tint][ir] Refactor the Disassembler, rename to Disassembly by Ben Clayton <bclayton@google.com>
- 4ac690d07be2dfa1fee676558514c11a9d392571 tint_cmd: use DXC via shared library (dxcompiler) rather ... by Antonio Maiorano <amaiorano@google.com>
- 9ae003a28e62d882e6bda2ea1a998dfea61b6bc9 [ir] Remove unused worklist by James Price <jrprice@google.com>
- 425cb428fa9598dcdb549256f6a626236f64344c [tint][ir] Use styled text in validation errors by Ben Clayton <bclayton@google.com>
GitOrigin-RevId: 1ea04e752a1f85df223e0ba0d2b049a130167fcb
Change-Id: I6c6a440e3ecdc72a40f0d8726146eee07ee76e2e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/186661
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9df25d9..1930b90 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -108,6 +108,8 @@
option_if_not_defined(TINT_ENABLE_ASAN "Enable address sanitizer" OFF)
option_if_not_defined(TINT_ENABLE_UBSAN "Enable undefined behaviour sanitizer" OFF)
+option_if_not_defined(TINT_WERROR "Build with -Werror (or equivalent)" OFF)
+
option_if_not_defined(TINT_ENABLE_BREAK_IN_DEBUGGER "Enable tint::debugger::Break()" OFF)
option_if_not_defined(TINT_EMIT_COVERAGE "Emit code coverage information" OFF)
@@ -160,6 +162,10 @@
-Wno-unknown-warning-option
)
+ if (${TINT_WERROR})
+ target_compile_options(${TARGET} PRIVATE -Werror)
+ endif()
+
if (${TINT_ENABLE_MSAN})
target_compile_options(${TARGET} PUBLIC -fsanitize=memory)
target_link_options(${TARGET} PUBLIC -fsanitize=memory)
diff --git a/DEPS b/DEPS
index 55f27cc..d04dd55 100644
--- a/DEPS
+++ b/DEPS
@@ -111,6 +111,10 @@
'url': '{chromium_git}/chromium/src/third_party/abseil-cpp@4ef9b33175828ea46d091e7e5ec28259d39a8ba5',
},
+ 'third_party/dxc': {
+ 'url': '{chromium_git}/external/github.com/microsoft/DirectXShaderCompiler@e7b78ff9c99c19a6a0c98256db9794e0af4eb59d',
+ },
+
# Dependencies required for testing
'testing': {
'url': '{chromium_git}/chromium/src/testing@035a9b18047370df7403758b006e6c9696d6b84d',
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni
index 6440625..b34d77f 100644
--- a/build_overrides/dawn.gni
+++ b/build_overrides/dawn.gni
@@ -37,6 +37,7 @@
dawn_vulkan_loader_dir = "//third_party/vulkan-deps/vulkan-loader/src"
dawn_vulkan_validation_layers_dir =
"//third_party/vulkan-deps/vulkan-validation-layers/src"
+dawn_dxc_dir = "//third_party/dxc"
# Optional path to a one-liner version file. Default is empty path indicating
# that git should be used to figure out the version.
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index f01ff5e..30d21d4 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -139,6 +139,10 @@
}
}
+source_set("dl") {
+ # GN doesn't appear to need to depend on any dl libraries.
+}
+
source_set("thread") {
# GN doesn't appear to need to depend on any thread libraries.
}
@@ -252,6 +256,13 @@
libs = [ "ws2_32.lib" ]
}
+config("dxc-include-config") {
+ include_dirs = [ "${dawn_dxc_dir}/include" ]
+}
+source_set("dxc-include") {
+ public_configs = [ ":dxc-include-config" ]
+}
+
###############################################################################
# Fuzzers
###############################################################################
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 235349c..80cbdfa 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -82,13 +82,15 @@
set(COMMON_GNU_OPTIONS
-Wall
- -Werror
-Wextra
-Wno-documentation-unknown-command
-Wno-padded
-Wno-switch-enum
-Wno-unknown-pragmas
)
+ if (${TINT_WERROR})
+ list(APPEND COMMON_GNU_OPTIONS -Werror)
+ endif()
set(COMMON_CLANG_OPTIONS
-Wno-c++98-compat
@@ -130,7 +132,6 @@
/bigobj
/EHsc
/W4
- /WX
/wd4068 # unknown pragma
/wd4127 # conditional expression is constant
/wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data
@@ -148,6 +149,9 @@
/wd5026 # 'type': move constructor was implicitly defined as deleted
/wd5027 # 'type': move assignment operator was implicitly defined as deleted
)
+ if (${TINT_WERROR})
+ target_compile_options(${TARGET} PRIVATE /WX)
+ endif()
# When building with clang-cl on Windows, try to match our clang build
# options as much as possible.
@@ -501,6 +505,10 @@
target_link_libraries(${TARGET} PRIVATE
absl_strings
)
+ elseif(${DEPENDENCY} STREQUAL "dl")
+ target_link_libraries(${TARGET} PRIVATE ${CMAKE_DL_LIBS})
+ elseif(${DEPENDENCY} STREQUAL "dxc-include")
+ target_include_directories(${TARGET} PRIVATE "${TINT_THIRD_PARTY_DIR}/dxc/include")
elseif(${DEPENDENCY} STREQUAL "jsoncpp")
target_link_libraries(${TARGET} PRIVATE jsoncpp_static)
elseif(${DEPENDENCY} STREQUAL "langsvr")
diff --git a/src/tint/cmd/common/helper.cc b/src/tint/cmd/common/helper.cc
index a461591..49fcf79 100644
--- a/src/tint/cmd/common/helper.cc
+++ b/src/tint/cmd/common/helper.cc
@@ -124,17 +124,23 @@
exit(1);
}
- // Convert the IR module to a WGSL AST program.
- tint::wgsl::writer::ProgramOptions options;
- options.allow_non_uniform_derivatives =
+ // Convert the IR module to a WGSL string.
+ tint::wgsl::writer::ProgramOptions writer_options;
+ writer_options.allow_non_uniform_derivatives =
opts.spirv_reader_options.allow_non_uniform_derivatives;
- options.allowed_features = opts.spirv_reader_options.allowed_features;
- auto ast = tint::wgsl::writer::IRToProgram(result.Get(), options);
- if (!ast.IsValid() || ast.Diagnostics().ContainsErrors()) {
- std::cerr << "Failed to convert IR to AST:\n\n" << ast.Diagnostics() << "\n";
+ writer_options.allowed_features = opts.spirv_reader_options.allowed_features;
+ auto wgsl_result = tint::wgsl::writer::WgslFromIR(result.Get(), writer_options);
+ if (wgsl_result != Success) {
+ std::cerr << "Failed to convert IR to WGSL:\n\n"
+ << wgsl_result.Failure().reason << "\n";
exit(1);
}
- return ast;
+
+ // Parse the WGSL string to produce a WGSL AST.
+ tint::wgsl::reader::Options reader_options;
+ reader_options.allowed_features = tint::wgsl::AllowedFeatures::Everything();
+ auto file = std::make_unique<tint::Source::File>(opts.filename, wgsl_result->wgsl);
+ return tint::wgsl::reader::Parse(file.get(), reader_options);
#else
std::cerr << "Tint not built with the WGSL writer enabled" << std::endl;
exit(1);
diff --git a/src/tint/cmd/fuzz/ir/fuzz.cc b/src/tint/cmd/fuzz/ir/fuzz.cc
index 3ea4363..a74fef3 100644
--- a/src/tint/cmd/fuzz/ir/fuzz.cc
+++ b/src/tint/cmd/fuzz/ir/fuzz.cc
@@ -64,7 +64,8 @@
void Register(const IRFuzzer& fuzzer) {
wgsl::Register({
fuzzer.name,
- [fn = fuzzer.fn](const Program& program, Slice<const std::byte> data) {
+ [fn = fuzzer.fn](const Program& program, const fuzz::wgsl::Options& options,
+ Slice<const std::byte> data) {
if (program.AST().Enables().Any(IsUnsupported)) {
return;
}
diff --git a/src/tint/cmd/fuzz/wgsl/fuzz.cc b/src/tint/cmd/fuzz/wgsl/fuzz.cc
index 23bbe0f..17c2e1c 100644
--- a/src/tint/cmd/fuzz/wgsl/fuzz.cc
+++ b/src/tint/cmd/fuzz/wgsl/fuzz.cc
@@ -67,7 +67,7 @@
Fuzzers().Push(fuzzer);
}
-void Run(std::string_view wgsl, Slice<const std::byte> data, const Options& options) {
+void Run(std::string_view wgsl, const Options& options, Slice<const std::byte> data) {
tint::SetInternalCompilerErrorReporter(&TintInternalCompilerErrorReporter);
#if TINT_BUILD_WGSL_WRITER
@@ -116,7 +116,7 @@
if (options.verbose) {
std::cout << " • [" << i << "] Running: " << currently_running << std::endl;
}
- fuzzer.fn(program, data);
+ fuzzer.fn(program, options, data);
}));
}
for (auto& thread : threads) {
@@ -133,7 +133,7 @@
if (options.verbose) {
std::cout << " • Running: " << currently_running << std::endl;
}
- fuzzer.fn(program, data);
+ fuzzer.fn(program, options, data);
}
}
}
diff --git a/src/tint/cmd/fuzz/wgsl/fuzz.h b/src/tint/cmd/fuzz/wgsl/fuzz.h
index e4bc7a0..d128695 100644
--- a/src/tint/cmd/fuzz/wgsl/fuzz.h
+++ b/src/tint/cmd/fuzz/wgsl/fuzz.h
@@ -37,20 +37,66 @@
#include "src/tint/utils/bytes/decoder.h"
#include "src/tint/utils/containers/slice.h"
#include "src/tint/utils/macros/static_init.h"
-#include "src/tint/utils/reflection/reflection.h"
namespace tint::fuzz::wgsl {
+/// Options for Run()
+struct Options {
+ /// If not empty, only run the fuzzers with the given substring.
+ std::string filter;
+ /// If true, the fuzzers will be run concurrently on separate threads.
+ bool run_concurrently = false;
+ /// If true, print the fuzzer name to stdout before running.
+ bool verbose = false;
+ /// If not empty, load DXC from this path when fuzzing HLSL generation, and fail the fuzzer if
+ /// not found, or if DXC fails to compile.
+ std::string dxc;
+};
+
/// ProgramFuzzer describes a fuzzer function that takes a WGSL program as input
struct ProgramFuzzer {
/// @param name the name of the fuzzer
- /// @param fn the fuzzer function
- /// @returns a ProgramFuzzer that invokes the function @p fn with the Program, along with any
- /// additional arguments which are deserialized from the fuzzer input.
+ /// @param fn the fuzzer function with the signature `void(const Program&, const Options&, ...)`
+ /// @returns a ProgramFuzzer that invokes the function @p fn with the Program, Options, along
+ /// with any additional arguments which are deserialized from the fuzzer input.
+ template <typename... ARGS>
+ static ProgramFuzzer Create(std::string_view name,
+ void (*fn)(const Program&, const Options&, ARGS...)) {
+ if constexpr (sizeof...(ARGS) > 0) {
+ auto fn_with_decode = [fn](const Program& program, const Options& options,
+ Slice<const std::byte> data) {
+ if (!data.data) {
+ return;
+ }
+ bytes::BufferReader reader{data};
+ auto data_args = bytes::Decode<std::tuple<std::decay_t<ARGS>...>>(reader);
+ if (data_args == Success) {
+ auto all_args =
+ std::tuple_cat(std::tuple<const Program&, const Options&>{program, options},
+ data_args.Get());
+ std::apply(*fn, all_args);
+ }
+ };
+ return ProgramFuzzer{name, std::move(fn_with_decode)};
+ } else {
+ return ProgramFuzzer{
+ name,
+ [fn](const Program& program, const Options& options, Slice<const std::byte>) {
+ fn(program, options);
+ },
+ };
+ }
+ }
+
+ /// @param name the name of the fuzzer
+ /// @param fn the fuzzer function with the signature `void(const Program&, ...)`
+ /// @returns a ProgramFuzzer that invokes the function @p fn with the Program, along
+ /// with any additional arguments which are deserialized from the fuzzer input.
template <typename... ARGS>
static ProgramFuzzer Create(std::string_view name, void (*fn)(const Program&, ARGS...)) {
if constexpr (sizeof...(ARGS) > 0) {
- auto fn_with_decode = [fn](const Program& program, Slice<const std::byte> data) {
+ auto fn_with_decode = [fn](const Program& program, const Options&,
+ Slice<const std::byte> data) {
if (!data.data) {
return;
}
@@ -66,7 +112,9 @@
} else {
return ProgramFuzzer{
name,
- [fn](const Program& program, Slice<const std::byte>) { fn(program); },
+ [fn](const Program& program, const Options&, Slice<const std::byte>) {
+ fn(program);
+ },
};
}
}
@@ -74,30 +122,26 @@
/// Name of the fuzzer function
std::string_view name;
/// The fuzzer function
- std::function<void(const Program&, Slice<const std::byte> data)> fn;
-};
-
-/// Options for Run()
-struct Options {
- /// If not empty, only run the fuzzers with the given substring.
- std::string filter;
- /// If true, the fuzzers will be run concurrently on separate threads.
- bool run_concurrently = false;
- /// If true, print the fuzzer name to stdout before running.
- bool verbose = false;
+ std::function<void(const Program&, const Options&, Slice<const std::byte> data)> fn;
};
/// Runs all the registered WGSL fuzzers with the supplied WGSL
/// @param wgsl the input WGSL
-/// @param data additional data used for fuzzing
/// @param options the options for running the fuzzers
-void Run(std::string_view wgsl, Slice<const std::byte> data, const Options& options);
+/// @param data additional data used for fuzzing
+void Run(std::string_view wgsl, const Options& options, Slice<const std::byte> data);
/// Registers the fuzzer function with the WGSL fuzzer executable.
/// @param fuzzer the fuzzer
void Register(const ProgramFuzzer& fuzzer);
/// TINT_WGSL_PROGRAM_FUZZER registers the fuzzer function to run as part of `tint_wgsl_fuzzer`
+/// The function must have one of the signatures:
+/// • `void(const Program&, ...)`
+/// • `void(const Program&, const Options&, ...)`
+/// Where `...` is any number of deserializable parameters which are decoded from the base64
+/// content of the WGSL comments.
+/// @see bytes::Decode()
#define TINT_WGSL_PROGRAM_FUZZER(FUNCTION) \
TINT_STATIC_INIT(::tint::fuzz::wgsl::Register( \
::tint::fuzz::wgsl::ProgramFuzzer::Create(#FUNCTION, FUNCTION)))
diff --git a/src/tint/cmd/fuzz/wgsl/main_fuzz.cc b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
index 3420d40..06489f1 100644
--- a/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
+++ b/src/tint/cmd/fuzz/wgsl/main_fuzz.cc
@@ -26,6 +26,8 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iostream>
+#include <string>
+#include <unordered_map>
#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
#include "src/tint/utils/cli/cli.h"
@@ -42,7 +44,7 @@
if (size > 0) {
std::string_view wgsl(reinterpret_cast<const char*>(input), size);
auto data = tint::DecodeBase64FromComments(wgsl);
- tint::fuzz::wgsl::Run(wgsl, data.Slice(), options);
+ tint::fuzz::wgsl::Run(wgsl, options, data.Slice());
}
return 0;
}
@@ -76,6 +78,7 @@
opts.Add<tint::cli::BoolOption>("concurrent", "runs the fuzzers concurrently");
auto& opt_verbose =
opts.Add<tint::cli::BoolOption>("verbose", "prints the name of each fuzzer before running");
+ auto& opt_dxc = opts.Add<tint::cli::StringOption>("dxc", "path to DXC DLL");
tint::cli::ParseOptions parse_opts;
parse_opts.ignore_unknown = true;
@@ -93,5 +96,6 @@
options.filter = opt_filter.value.value_or("");
options.run_concurrently = opt_concurrent.value.value_or(false);
options.verbose = opt_verbose.value.value_or(false);
+ options.dxc = opt_dxc.value.value_or("");
return 0;
}
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 24ef2fd..f413485 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -43,7 +43,7 @@
#include "src/tint/api/tint.h"
#include "src/tint/cmd/common/generate_external_texture_bindings.h"
#include "src/tint/cmd/common/helper.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/wgsl/ast/module.h"
#include "src/tint/lang/wgsl/ast/transform/first_index_offset.h"
@@ -1009,8 +1009,9 @@
tint::hlsl::validate::Result dxc_res;
bool dxc_found = false;
if (options.validate || must_validate_dxc) {
- auto dxc = tint::Command::LookPath(
- options.dxc_path.empty() ? "dxc" : std::string(options.dxc_path));
+ auto dxc =
+ tint::Command::LookPath(options.dxc_path.empty() ? tint::hlsl::validate::kDxcDLLName
+ : std::string(options.dxc_path));
if (dxc.Found()) {
dxc_found = true;
@@ -1053,7 +1054,7 @@
fxc_res.output = "FXC DLL '" + options.fxc_path + "' not found. Cannot validate";
}
#else
- if (must_validate_dxc) {
+ if (must_validate_fxc) {
fxc_res.failed = true;
fxc_res.output = "FXC can only be used on Windows.";
}
@@ -1222,7 +1223,7 @@
std::cerr << "Failed to build IR from program: " << result.Failure() << "\n";
return false;
}
- options.printer->Print(tint::core::ir::Disassemble(result.Get()));
+ options.printer->Print(tint::core::ir::Disassemble(result.Get()).Text());
options.printer->Print(tint::StyledText{} << "\n");
return true;
#endif
diff --git a/src/tint/externals.json b/src/tint/externals.json
index dbdf96d..8b8bd96 100644
--- a/src/tint/externals.json
+++ b/src/tint/externals.json
@@ -6,7 +6,19 @@
"abseil": {
"IncludePatterns": [
"absl/**"
+ ]
+ },
+ "dl": {
+ "IncludePatterns": [
+ "dlfcn.h"
],
+ "Condition": "tint_build_hlsl_writer"
+ },
+ "dxc-include": {
+ "IncludePatterns": [
+ "dxc/**"
+ ],
+ "Condition": "tint_build_hlsl_writer"
},
"google-benchmark": {
"IncludePatterns": [
diff --git a/src/tint/lang/core/constant/eval.cc b/src/tint/lang/core/constant/eval.cc
index 0b78386..36069fd 100644
--- a/src/tint/lang/core/constant/eval.cc
+++ b/src/tint/lang/core/constant/eval.cc
@@ -281,7 +281,7 @@
// [abstract-numeric -> x] - materialization failure
auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName());
if (ctx.use_runtime_semantics) {
- ctx.diags.AddWarning(tint::diag::System::Resolver, ctx.source) << msg;
+ ctx.diags.AddWarning(ctx.source) << msg;
switch (conv.Failure()) {
case ConversionFailure::kExceedsNegativeLimit:
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Lowest());
@@ -289,7 +289,7 @@
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Highest());
}
} else {
- ctx.diags.AddError(tint::diag::System::Resolver, ctx.source) << msg;
+ ctx.diags.AddError(ctx.source) << msg;
return nullptr;
}
} else if constexpr (IsFloatingPoint<TO>) {
@@ -297,7 +297,7 @@
// https://www.w3.org/TR/WGSL/#floating-point-conversion
auto msg = OverflowErrorMessage(scalar->value, target_ty->FriendlyName());
if (ctx.use_runtime_semantics) {
- ctx.diags.AddWarning(tint::diag::System::Resolver, ctx.source) << msg;
+ ctx.diags.AddWarning(ctx.source) << msg;
switch (conv.Failure()) {
case ConversionFailure::kExceedsNegativeLimit:
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Lowest());
@@ -305,7 +305,7 @@
return ctx.mgr.Get<Scalar<TO>>(target_ty, TO::Highest());
}
} else {
- ctx.diags.AddError(tint::diag::System::Resolver, ctx.source) << msg;
+ ctx.diags.AddError(ctx.source) << msg;
return nullptr;
}
} else if constexpr (IsFloatingPoint<FROM>) {
@@ -4014,18 +4014,18 @@
diag::Diagnostic& Eval::AddError(const Source& source) const {
if (use_runtime_semantics_) {
- return diags.AddWarning(diag::System::Constant, source);
+ return diags.AddWarning(source);
} else {
- return diags.AddError(diag::System::Constant, source);
+ return diags.AddError(source);
}
}
diag::Diagnostic& Eval::AddWarning(const Source& source) const {
- return diags.AddWarning(diag::System::Constant, source);
+ return diags.AddWarning(source);
}
diag::Diagnostic& Eval::AddNote(const Source& source) const {
- return diags.AddNote(diag::System::Constant, source);
+ return diags.AddNote(source);
}
} // namespace tint::core::constant
diff --git a/src/tint/lang/core/ir/BUILD.bazel b/src/tint/lang/core/ir/BUILD.bazel
index a02930e..6617663 100644
--- a/src/tint/lang/core/ir/BUILD.bazel
+++ b/src/tint/lang/core/ir/BUILD.bazel
@@ -57,7 +57,7 @@
"core_binary.cc",
"core_builtin_call.cc",
"core_unary.cc",
- "disassembler.cc",
+ "disassembly.cc",
"discard.cc",
"exit.cc",
"exit_if.cc",
@@ -109,7 +109,7 @@
"core_binary.h",
"core_builtin_call.h",
"core_unary.h",
- "disassembler.h",
+ "disassembly.h",
"discard.h",
"exit.h",
"exit_if.h",
diff --git a/src/tint/lang/core/ir/BUILD.cmake b/src/tint/lang/core/ir/BUILD.cmake
index 94365b4..70bc0d4 100644
--- a/src/tint/lang/core/ir/BUILD.cmake
+++ b/src/tint/lang/core/ir/BUILD.cmake
@@ -78,8 +78,8 @@
lang/core/ir/core_builtin_call.h
lang/core/ir/core_unary.cc
lang/core/ir/core_unary.h
- lang/core/ir/disassembler.cc
- lang/core/ir/disassembler.h
+ lang/core/ir/disassembly.cc
+ lang/core/ir/disassembly.h
lang/core/ir/discard.cc
lang/core/ir/discard.h
lang/core/ir/exit.cc
diff --git a/src/tint/lang/core/ir/BUILD.gn b/src/tint/lang/core/ir/BUILD.gn
index ac59268..9927e42 100644
--- a/src/tint/lang/core/ir/BUILD.gn
+++ b/src/tint/lang/core/ir/BUILD.gn
@@ -80,8 +80,8 @@
"core_builtin_call.h",
"core_unary.cc",
"core_unary.h",
- "disassembler.cc",
- "disassembler.h",
+ "disassembly.cc",
+ "disassembly.h",
"discard.cc",
"discard.h",
"exit.cc",
diff --git a/src/tint/lang/core/ir/binary/roundtrip_fuzz.cc b/src/tint/lang/core/ir/binary/roundtrip_fuzz.cc
index ccc7a9c..7378a3f 100644
--- a/src/tint/lang/core/ir/binary/roundtrip_fuzz.cc
+++ b/src/tint/lang/core/ir/binary/roundtrip_fuzz.cc
@@ -28,7 +28,7 @@
#include "src/tint/cmd/fuzz/ir/fuzz.h"
#include "src/tint/lang/core/ir/binary/decode.h"
#include "src/tint/lang/core/ir/binary/encode.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
namespace tint::core::ir::binary {
namespace {
diff --git a/src/tint/lang/core/ir/binary/roundtrip_test.cc b/src/tint/lang/core/ir/binary/roundtrip_test.cc
index 9d8b368..52a516b 100644
--- a/src/tint/lang/core/ir/binary/roundtrip_test.cc
+++ b/src/tint/lang/core/ir/binary/roundtrip_test.cc
@@ -29,7 +29,7 @@
#include "src/tint/lang/core/ir/binary/decode.h"
#include "src/tint/lang/core/ir/binary/encode.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/type/depth_multisampled_texture.h"
#include "src/tint/lang/core/type/depth_texture.h"
#include "src/tint/lang/core/type/external_texture.h"
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembly.cc
similarity index 84%
rename from src/tint/lang/core/ir/disassembler.cc
rename to src/tint/lang/core/ir/disassembly.cc
index 1664dce..a07033f 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembly.cc
@@ -25,32 +25,26 @@
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
+#include <memory>
+#include <string_view>
#include "src//tint/lang/core/ir/unary.h"
#include "src/tint/lang/core/constant/composite.h"
#include "src/tint/lang/core/constant/scalar.h"
#include "src/tint/lang/core/constant/splat.h"
-#include "src/tint/lang/core/fluent_types.h"
-#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/binary.h"
-#include "src/tint/lang/core/ir/bitcast.h"
#include "src/tint/lang/core/ir/block.h"
#include "src/tint/lang/core/ir/block_param.h"
#include "src/tint/lang/core/ir/break_if.h"
-#include "src/tint/lang/core/ir/construct.h"
#include "src/tint/lang/core/ir/continue.h"
-#include "src/tint/lang/core/ir/convert.h"
-#include "src/tint/lang/core/ir/core_builtin_call.h"
#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/exit_switch.h"
+#include "src/tint/lang/core/ir/function.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/instruction_result.h"
-#include "src/tint/lang/core/ir/let.h"
-#include "src/tint/lang/core/ir/load.h"
-#include "src/tint/lang/core/ir/load_vector_element.h"
#include "src/tint/lang/core/ir/loop.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
@@ -67,7 +61,6 @@
#include "src/tint/lang/core/type/type.h"
#include "src/tint/utils/ice/ice.h"
#include "src/tint/utils/macros/defer.h"
-#include "src/tint/utils/macros/scoped_assignment.h"
#include "src/tint/utils/rtti/switch.h"
#include "src/tint/utils/text/string.h"
#include "src/tint/utils/text/styled_text.h"
@@ -104,85 +97,29 @@
} // namespace
-StyledText Disassemble(const Module& mod) {
- return Disassembler{mod}.Disassemble();
-}
+Disassembly::Disassembly(Disassembly&&) = default;
-Disassembler::Disassembler(const Module& mod) : mod_(mod) {}
+Disassembly::Disassembly(const Module& mod, std::string_view file_name) : mod_(mod) {
+ Disassemble();
+ file_ = std::make_shared<Source::File>(std::string(file_name), Plain());
-Disassembler::~Disassembler() = default;
-
-StyledText& Disassembler::Indent() {
- for (uint32_t i = 0; i < indent_size_; i++) {
- out_ << " ";
- }
- return out_;
-}
-
-void Disassembler::EmitLine() {
- out_ << "\n";
- current_output_line_ += 1;
- current_output_start_pos_ = static_cast<uint32_t>(out_.Length());
-}
-
-size_t Disassembler::IdOf(const Block* node) {
- TINT_ASSERT(node);
- return block_ids_.GetOrAdd(node, [&] { return block_ids_.Count(); });
-}
-
-std::string Disassembler::IdOf(const Value* value) {
- TINT_ASSERT(value);
- return value_ids_.GetOrAdd(value, [&] {
- if (auto sym = mod_.NameOf(value)) {
- if (ids_.Add(sym.Name())) {
- return sym.Name();
- }
- auto prefix = sym.Name() + "_";
- for (size_t i = 1;; i++) {
- auto name = prefix + std::to_string(i);
- if (ids_.Add(name)) {
- return name;
- }
- }
+ auto set_source_file = [&](auto& map) {
+ for (auto& it : map) {
+ it.value.file = file_.get();
}
- return std::to_string(value_ids_.Count());
- });
-}
-
-std::string Disassembler::NameOf(const If* inst) {
- if (!inst) {
- return "undef";
- }
-
- return if_names_.GetOrAdd(inst, [&] { return "if_" + std::to_string(if_names_.Count()); });
-}
-
-std::string Disassembler::NameOf(const Loop* inst) {
- if (!inst) {
- return "undef";
- }
-
- return loop_names_.GetOrAdd(inst,
- [&] { return "loop_" + std::to_string(loop_names_.Count()); });
-}
-
-std::string Disassembler::NameOf(const Switch* inst) {
- if (!inst) {
- return "undef";
- }
-
- return switch_names_.GetOrAdd(
- inst, [&] { return "switch_" + std::to_string(switch_names_.Count()); });
-}
-
-Source::Location Disassembler::MakeCurrentLocation() {
- return Source::Location{
- current_output_line_,
- static_cast<uint32_t>(out_.Length()) - current_output_start_pos_ + 1,
};
+ set_source_file(block_to_src_);
+ set_source_file(block_param_to_src_);
+ set_source_file(instruction_to_src_);
+ set_source_file(operand_to_src_);
+ set_source_file(result_to_src_);
+ set_source_file(function_to_src_);
+ set_source_file(function_param_to_src_);
}
-const StyledText& Disassembler::Disassemble() {
+Disassembly::~Disassembly() = default;
+
+void Disassembly::Disassemble() {
TINT_DEFER(out_ << StylePlain);
out_.Clear();
out_ << StyleCode;
@@ -201,14 +138,33 @@
for (auto& func : mod_.functions) {
EmitFunction(func);
}
+}
+
+StyledText& Disassembly::Indent() {
+ for (uint32_t i = 0; i < indent_size_; i++) {
+ out_ << " ";
+ }
return out_;
}
-void Disassembler::EmitBlock(const Block* blk, std::string_view comment /* = "" */) {
+void Disassembly::EmitLine() {
+ out_ << "\n";
+ current_output_line_ += 1;
+ current_output_start_pos_ = static_cast<uint32_t>(out_.Length());
+}
+
+Source::Location Disassembly::MakeCurrentLocation() {
+ return Source::Location{
+ current_output_line_,
+ static_cast<uint32_t>(out_.Length()) - current_output_start_pos_ + 1,
+ };
+}
+
+void Disassembly::EmitBlock(const Block* blk, std::string_view comment /* = "" */) {
Indent();
SourceMarker sm(this);
- out_ << StyleLabel("$B", IdOf(blk));
+ out_ << NameOf(blk);
if (auto* merge = blk->As<MultiInBlock>()) {
if (!merge->Params().IsEmpty()) {
out_ << " (";
@@ -216,9 +172,12 @@
if (p != merge->Params().Front()) {
out_ << ", ";
}
- SourceMarker psm(this);
- EmitValue(p);
- psm.Store(p);
+ {
+ SourceMarker psm(this);
+ EmitValue(p);
+ psm.Store(p);
+ }
+ out_ << ":" << StyleType(p->Type()->FriendlyName());
}
out_ << ")";
}
@@ -243,12 +202,12 @@
EmitLine();
}
-void Disassembler::EmitBindingPoint(BindingPoint p) {
+void Disassembly::EmitBindingPoint(BindingPoint p) {
out_ << StyleAttribute("@binding_point") << "(" << StyleLiteral(p.group) << ", "
<< StyleLiteral(p.binding) << ")";
}
-void Disassembler::EmitLocation(Location loc) {
+void Disassembly::EmitLocation(Location loc) {
out_ << StyleAttribute("@location") << "(" << loc.value << ")";
if (loc.interpolation.has_value()) {
out_ << ", " << StyleAttribute("@interpolate") << "(";
@@ -261,7 +220,7 @@
}
}
-void Disassembler::EmitParamAttributes(const FunctionParam* p) {
+void Disassembly::EmitParamAttributes(const FunctionParam* p) {
if (!p->Invariant() && !p->Location().has_value() && !p->BindingPoint().has_value() &&
!p->Builtin().has_value()) {
return;
@@ -298,7 +257,7 @@
out_ << "]";
}
-void Disassembler::EmitReturnAttributes(const Function* func) {
+void Disassembly::EmitReturnAttributes(const Function* func) {
if (!func->ReturnInvariant() && !func->ReturnLocation().has_value() &&
!func->ReturnBuiltin().has_value()) {
return;
@@ -330,13 +289,13 @@
out_ << "]";
}
-void Disassembler::EmitFunction(const Function* func) {
+void Disassembly::EmitFunction(const Function* func) {
in_function_ = true;
- std::string fn_id = IdOf(func);
+ auto fn_id = NameOf(func);
{
SourceMarker sm(this);
- Indent() << StyleFunction("%", fn_id);
+ Indent() << fn_id;
sm.Store(func);
}
out_ << " =";
@@ -357,7 +316,7 @@
out_ << ", ";
}
SourceMarker sm(this);
- out_ << StyleVariable("%", IdOf(p)) << ":" << StyleType(p->Type()->FriendlyName());
+ out_ << NameOf(p) << ":" << StyleType(p->Type()->FriendlyName());
sm.Store(p);
EmitParamAttributes(p);
@@ -371,15 +330,15 @@
{ // Add a comment if the function IDs or parameter IDs doesn't match their name
Vector<std::string, 4> names;
if (auto name = mod_.NameOf(func); name.IsValid()) {
- if (name.NameView() != fn_id) {
- names.Push("%" + std::string(fn_id) + ": '" + name.Name() + "'");
+ if ("%" + name.Name() != fn_id.Plain()) {
+ names.Push(fn_id.Plain() + ": '" + name.Name() + "'");
}
}
for (auto* p : func->Params()) {
if (auto name = mod_.NameOf(p); name.IsValid()) {
- auto id = IdOf(p);
- if (name.NameView() != id) {
- names.Push("%" + std::string(id) + ": '" + name.Name() + "'");
+ auto id = NameOf(p);
+ if ("%" + name.Name() != id.Plain()) {
+ names.Push(id.Plain() + ": '" + name.Name() + "'");
}
}
}
@@ -398,27 +357,24 @@
EmitLine();
}
-void Disassembler::EmitValueWithType(const Instruction* val) {
+void Disassembly::EmitValueWithType(const Instruction* val) {
SourceMarker sm(this);
- if (val->Result(0)) {
- EmitValueWithType(val->Result(0));
- } else {
- out_ << "undef";
- }
+ EmitValueWithType(val->Result(0));
sm.StoreResult(IndexedValue{val, 0});
}
-void Disassembler::EmitValueWithType(const Value* val) {
- if (!val) {
- out_ << "undef";
- return;
- }
-
+void Disassembly::EmitValueWithType(const Value* val) {
EmitValue(val);
- out_ << ":" << StyleType(val->Type()->FriendlyName());
+ if (val) {
+ out_ << ":" << StyleType(val->Type()->FriendlyName());
+ }
}
-void Disassembler::EmitValue(const Value* val) {
+void Disassembly::EmitValue(const Value* val) {
+ if (!val) {
+ out_ << StyleLiteral("undef");
+ return;
+ }
tint::Switch(
val,
[&](const ir::Constant* constant) {
@@ -467,28 +423,16 @@
};
emit(constant->Value());
},
- [&](const ir::InstructionResult* rv) { out_ << StyleVariable("%", IdOf(rv)); },
- [&](const ir::BlockParam* p) {
- out_ << StyleVariable("%", IdOf(p)) << ":" << StyleType(p->Type()->FriendlyName());
- },
- [&](const ir::FunctionParam* p) { out_ << StyleVariable("%", IdOf(p)); },
- [&](const ir::Function* f) { out_ << StyleVariable("%", IdOf(f)); },
- [&](Default) {
- if (val == nullptr) {
- out_ << StyleVariable("undef");
- } else {
- out_ << StyleError("unknown value: ", val->TypeInfo().name);
- }
- });
+ [&](Default) { out_ << NameOf(val); });
}
-void Disassembler::EmitInstructionName(const Instruction* inst) {
+void Disassembly::EmitInstructionName(const Instruction* inst) {
SourceMarker sm(this);
out_ << StyleInstruction(inst->FriendlyName());
sm.Store(inst);
}
-void Disassembler::EmitInstruction(const Instruction* inst) {
+void Disassembly::EmitInstruction(const Instruction* inst) {
TINT_DEFER(EmitLine());
if (!inst->Alive()) {
@@ -604,9 +548,9 @@
for (auto* result : inst->Results()) {
if (result) {
if (auto name = mod_.NameOf(result); name.IsValid()) {
- auto id = IdOf(result);
- if (name.NameView() != id) {
- names.Push("%" + std::string(id) + ": '" + name.Name() + "'");
+ auto id = NameOf(result).Plain();
+ if ("%" + name.Name() != id) {
+ names.Push(id + ": '" + name.Name() + "'");
}
}
}
@@ -617,13 +561,13 @@
}
}
-void Disassembler::EmitOperand(const Instruction* inst, size_t index) {
+void Disassembly::EmitOperand(const Instruction* inst, size_t index) {
SourceMarker marker(this);
EmitValue(inst->Operands()[index]);
marker.Store(IndexedValue{inst, static_cast<uint32_t>(index)});
}
-void Disassembler::EmitOperandList(const Instruction* inst, size_t start_index /* = 0 */) {
+void Disassembly::EmitOperandList(const Instruction* inst, size_t start_index /* = 0 */) {
for (size_t i = start_index, n = inst->Operands().Length(); i < n; i++) {
if (i != start_index) {
out_ << ", ";
@@ -632,7 +576,7 @@
}
}
-void Disassembler::EmitIf(const If* if_) {
+void Disassembly::EmitIf(const If* if_) {
SourceMarker sm(this);
if (auto results = if_->Results(); !results.IsEmpty()) {
for (size_t i = 0; i < results.Length(); ++i) {
@@ -650,9 +594,9 @@
bool has_false = !if_->False()->IsEmpty();
- out_ << " [" << StyleKeyword("t") << ": " << StyleLabel("$B", IdOf(if_->True()));
+ out_ << " [" << StyleKeyword("t") << ": " << NameOf(if_->True());
if (has_false) {
- out_ << ", " << StyleKeyword("f") << ": " << StyleLabel("$B", IdOf(if_->False()));
+ out_ << ", " << StyleKeyword("f") << ": " << NameOf(if_->False());
}
out_ << "]";
sm.Store(if_);
@@ -683,7 +627,7 @@
out_ << "}";
}
-void Disassembler::EmitLoop(const Loop* l) {
+void Disassembly::EmitLoop(const Loop* l) {
SourceMarker sm(this);
if (auto results = l->Results(); !results.IsEmpty()) {
for (size_t i = 0; i < results.Length(); ++i) {
@@ -699,17 +643,15 @@
out_ << StyleInstruction("loop") << " [";
if (!l->Initializer()->IsEmpty()) {
- out_ << StyleKeyword("i") << ": "
- << StyleLabel("$B", std::to_string(IdOf(l->Initializer())));
+ out_ << StyleKeyword("i") << ": " << NameOf(l->Initializer());
out_ << ", ";
}
- out_ << StyleKeyword("b") << ": " << StyleLabel("$B", std::to_string(IdOf(l->Body())));
+ out_ << StyleKeyword("b") << ": " << NameOf(l->Body());
if (!l->Continuing()->IsEmpty()) {
out_ << ", ";
- out_ << StyleKeyword("c") << ": "
- << StyleLabel("$B", std::to_string(IdOf(l->Continuing())));
+ out_ << StyleKeyword("c") << ": " << NameOf(l->Continuing());
}
out_ << "]";
@@ -738,7 +680,7 @@
out_ << "}";
}
-void Disassembler::EmitSwitch(const Switch* s) {
+void Disassembly::EmitSwitch(const Switch* s) {
SourceMarker sm(this);
if (auto results = s->Results(); !results.IsEmpty()) {
for (size_t i = 0; i < results.Length(); ++i) {
@@ -770,7 +712,7 @@
EmitValue(selector.val);
}
}
- out_ << ", " << StyleLabel("$B", IdOf(c.block)) << ")";
+ out_ << ", " << NameOf(c.block) << ")";
}
out_ << "]";
sm.Store(s);
@@ -787,7 +729,7 @@
out_ << "}";
}
-void Disassembler::EmitTerminator(const Terminator* b) {
+void Disassembly::EmitTerminator(const Terminator* b) {
SourceMarker sm(this);
size_t args_offset = 0;
tint::Switch(
@@ -835,11 +777,11 @@
b, //
[&](const ir::BreakIf* bi) {
out_ << " "
- << StyleComment("# -> [t: exit_loop ", NameOf(bi->Loop()), ", f: $B",
- IdOf(bi->Loop()->Body()), "]");
+ << StyleComment("# -> [t: exit_loop ", NameOf(bi->Loop()),
+ ", f: ", NameOf(bi->Loop()->Body()), "]");
},
[&](const ir::Continue* c) {
- out_ << " " << StyleComment("# -> $B", IdOf(c->Loop()->Continuing()));
+ out_ << " " << StyleComment("# -> ", NameOf(c->Loop()->Continuing()));
}, //
[&](const ir::ExitIf* e) { out_ << " " << StyleComment("# ", NameOf(e->If())); }, //
[&](const ir::ExitSwitch* e) {
@@ -847,11 +789,11 @@
}, //
[&](const ir::ExitLoop* e) { out_ << " " << StyleComment("# ", NameOf(e->Loop())); }, //
[&](const ir::NextIteration* ni) {
- out_ << " " << StyleComment("# -> $B", IdOf(ni->Loop()->Body()));
+ out_ << " " << StyleComment("# -> ", NameOf(ni->Loop()->Body()));
});
}
-void Disassembler::EmitBinary(const Binary* b) {
+void Disassembly::EmitBinary(const Binary* b) {
SourceMarker sm(this);
EmitValueWithType(b);
out_ << " = ";
@@ -917,7 +859,7 @@
sm.Store(b);
}
-void Disassembler::EmitUnary(const Unary* u) {
+void Disassembly::EmitUnary(const Unary* u) {
SourceMarker sm(this);
EmitValueWithType(u);
out_ << " = ";
@@ -944,7 +886,7 @@
sm.Store(u);
}
-void Disassembler::EmitStructDecl(const core::type::Struct* str) {
+void Disassembly::EmitStructDecl(const core::type::Struct* str) {
out_ << StyleType(str->Name().Name()) << " = " << StyleKeyword("struct") << " "
<< StyleAttribute("@align") << "(" << StyleLiteral(str->Align()) << ")";
if (str->StructFlags().Contains(core::type::StructFlag::kBlock)) {
@@ -982,4 +924,64 @@
EmitLine();
}
+StyledText Disassembly::NameOf(const Block* node) {
+ TINT_ASSERT(node);
+ auto id = block_ids_.GetOrAdd(node, [&] { return block_ids_.Count(); });
+ return StyledText{} << StyleLabel("$B", id);
+}
+
+StyledText Disassembly::NameOf(const Value* value) {
+ TINT_ASSERT(value);
+ auto id = value_ids_.GetOrAdd(value, [&] {
+ if (auto sym = mod_.NameOf(value)) {
+ if (ids_.Add(sym.Name())) {
+ return sym.Name();
+ }
+ auto prefix = sym.Name() + "_";
+ for (size_t i = 1;; i++) {
+ auto name = prefix + std::to_string(i);
+ if (ids_.Add(name)) {
+ return name;
+ }
+ }
+ }
+ return std::to_string(value_ids_.Count());
+ });
+
+ auto style = tint::Switch(
+ value, //
+ [&](const Function*) { return StyleFunction; }, //
+ [&](const InstructionResult*) { return StyleVariable; });
+ return StyledText{} << style("%", id);
+}
+
+StyledText Disassembly::NameOf(const If* inst) {
+ if (!inst) {
+ return StyledText{} << StyleError("undef");
+ }
+
+ auto name = if_names_.GetOrAdd(inst, [&] { return "if_" + std::to_string(if_names_.Count()); });
+ return StyledText{} << StyleInstruction(name);
+}
+
+StyledText Disassembly::NameOf(const Loop* inst) {
+ if (!inst) {
+ return StyledText{} << StyleError("undef");
+ }
+
+ auto name =
+ loop_names_.GetOrAdd(inst, [&] { return "loop_" + std::to_string(loop_names_.Count()); });
+ return StyledText{} << StyleInstruction(name);
+}
+
+StyledText Disassembly::NameOf(const Switch* inst) {
+ if (!inst) {
+ return StyledText{} << StyleError("undef");
+ }
+
+ auto name = switch_names_.GetOrAdd(
+ inst, [&] { return "switch_" + std::to_string(switch_names_.Count()); });
+ return StyledText{} << StyleInstruction(name);
+}
+
} // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/disassembler.h b/src/tint/lang/core/ir/disassembly.h
similarity index 78%
rename from src/tint/lang/core/ir/disassembler.h
rename to src/tint/lang/core/ir/disassembly.h
index df20534..677b386 100644
--- a/src/tint/lang/core/ir/disassembler.h
+++ b/src/tint/lang/core/ir/disassembly.h
@@ -25,10 +25,12 @@
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_
-#define SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_
+#ifndef SRC_TINT_LANG_CORE_IR_DISASSEMBLY_H_
+#define SRC_TINT_LANG_CORE_IR_DISASSEMBLY_H_
+#include <memory>
#include <string>
+#include <string_view>
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/block.h"
@@ -40,7 +42,6 @@
#include "src/tint/lang/core/ir/unary.h"
#include "src/tint/utils/containers/hashmap.h"
#include "src/tint/utils/containers/hashset.h"
-#include "src/tint/utils/text/string_stream.h"
#include "src/tint/utils/text/styled_text.h"
// Forward declarations.
@@ -50,12 +51,8 @@
namespace tint::core::ir {
-/// @returns the disassembly for the module @p mod
-/// @param mod the module to disassemble
-StyledText Disassemble(const Module& mod);
-
-/// Helper class to disassemble the IR
-class Disassembler {
+/// Disassembly holds the disassembly of an IR module.
+class Disassembly {
public:
/// A reference to an instruction's operand or result.
struct IndexedValue {
@@ -75,32 +72,63 @@
}
};
- /// Constructor
- /// @param mod the module
- explicit Disassembler(const Module& mod);
- ~Disassembler();
+ /// Constructor.
+ /// Performs the disassembly of the module @p mod, constructing a Source::File with the name @p
+ /// file_name.
+ /// @param mod the module to disassemble
+ Disassembly(const Module& mod, std::string_view file_name);
- /// Returns the module as a styled text string
+ /// Move constructor
+ Disassembly(Disassembly&&);
+
+ /// Destructor
+ ~Disassembly();
+
/// @returns the string representation of the module
- const StyledText& Disassemble();
+ const StyledText& Text() const { return out_; }
+
+ /// @returns the string representation of the module as plain-text
+ std::string Plain() const { return out_.Plain(); }
+
+ /// @returns the disassembly file
+ const std::shared_ptr<Source::File>& File() const { return file_; }
+
+ /// @returns the disassembled name for the Block @p blk
+ StyledText NameOf(const Block* blk);
+
+ /// @returns the disassembled name for the Value @p node
+ StyledText NameOf(const Value* node);
+
+ /// @returns the disassembled name for the If @p inst
+ StyledText NameOf(const If* inst);
+
+ /// @returns the disassembled name for the Loop @p inst
+ StyledText NameOf(const Loop* inst);
+
+ /// @returns the disassembled name for the Switch @p inst
+ StyledText NameOf(const Switch* inst);
/// @param inst the instruction to retrieve
/// @returns the source for the instruction
- Source InstructionSource(const Instruction* inst) {
+ Source InstructionSource(const Instruction* inst) const {
return instruction_to_src_.GetOr(inst, Source{});
}
/// @param operand the operand to retrieve
/// @returns the source for the operand
- Source OperandSource(IndexedValue operand) { return operand_to_src_.GetOr(operand, Source{}); }
+ Source OperandSource(IndexedValue operand) const {
+ return operand_to_src_.GetOr(operand, Source{});
+ }
/// @param result the result to retrieve
/// @returns the source for the result
- Source ResultSource(IndexedValue result) { return result_to_src_.GetOr(result, Source{}); }
+ Source ResultSource(IndexedValue result) const {
+ return result_to_src_.GetOr(result, Source{});
+ }
/// @param blk the block to retrieve
/// @returns the source for the block
- Source BlockSource(const Block* blk) { return block_to_src_.GetOr(blk, Source{}); }
+ Source BlockSource(const Block* blk) const { return block_to_src_.GetOr(blk, Source{}); }
/// @param param the block parameter to retrieve
/// @returns the source for the parameter
@@ -118,6 +146,10 @@
return function_param_to_src_.GetOr(param, Source{});
}
+ private:
+ /// Performs the disassembling of the module.
+ void Disassemble();
+
/// Stores the given @p src location for @p inst instruction
/// @param inst the instruction to store
/// @param src the source location
@@ -158,10 +190,9 @@
/// @returns the source location for the current emission location
Source::Location MakeCurrentLocation();
- private:
class SourceMarker {
public:
- explicit SourceMarker(Disassembler* d) : dis_(d), begin_(dis_->MakeCurrentLocation()) {}
+ explicit SourceMarker(Disassembly* d) : dis_(d), begin_(dis_->MakeCurrentLocation()) {}
~SourceMarker() = default;
void Store(const Instruction* inst) { dis_->SetSource(inst, MakeSource()); }
@@ -183,18 +214,12 @@
}
private:
- Disassembler* dis_ = nullptr;
+ Disassembly* dis_ = nullptr;
Source::Location begin_;
};
StyledText& Indent();
- size_t IdOf(const Block* blk);
- std::string IdOf(const Value* node);
- std::string NameOf(const If* inst);
- std::string NameOf(const Loop* inst);
- std::string NameOf(const Switch* inst);
-
void EmitBlock(const Block* blk, std::string_view comment = "");
void EmitFunction(const Function* func);
void EmitParamAttributes(const FunctionParam* p);
@@ -219,9 +244,7 @@
const Module& mod_;
StyledText out_;
- Hashmap<const Block*, size_t, 32> block_ids_;
- Hashmap<const Value*, std::string, 32> value_ids_;
- Hashset<std::string, 32> ids_;
+ std::shared_ptr<Source::File> file_;
uint32_t indent_size_ = 0;
bool in_function_ = false;
@@ -235,11 +258,21 @@
Hashmap<IndexedValue, Source, 8> result_to_src_;
Hashmap<const Function*, Source, 8> function_to_src_;
Hashmap<const FunctionParam*, Source, 8> function_param_to_src_;
+
+ // Names / IDs
+ Hashmap<const Block*, size_t, 32> block_ids_;
+ Hashmap<const Value*, std::string, 32> value_ids_;
Hashmap<const If*, std::string, 8> if_names_;
Hashmap<const Loop*, std::string, 8> loop_names_;
Hashmap<const Switch*, std::string, 8> switch_names_;
+ Hashset<std::string, 32> ids_;
};
+/// @returns the disassembly for the module @p mod, using the file name @p file_name
+inline Disassembly Disassemble(const Module& mod, std::string_view file_name = "") {
+ return Disassembly(mod, file_name);
+}
+
} // namespace tint::core::ir
-#endif // SRC_TINT_LANG_CORE_IR_DISASSEMBLER_H_
+#endif // SRC_TINT_LANG_CORE_IR_DISASSEMBLY_H_
diff --git a/src/tint/lang/core/ir/function.cc b/src/tint/lang/core/ir/function.cc
index 5b669c2..1138fbf 100644
--- a/src/tint/lang/core/ir/function.cc
+++ b/src/tint/lang/core/ir/function.cc
@@ -87,6 +87,11 @@
}
}
+void Function::AppendParam(FunctionParam* param) {
+ params_.Push(param);
+ param->SetFunction(this);
+}
+
void Function::Destroy() {
Base::Destroy();
block_->Destroy();
diff --git a/src/tint/lang/core/ir/function.h b/src/tint/lang/core/ir/function.h
index 5cf533f..f7c7ebd 100644
--- a/src/tint/lang/core/ir/function.h
+++ b/src/tint/lang/core/ir/function.h
@@ -146,6 +146,10 @@
/// @param params the function parameters
void SetParams(std::initializer_list<FunctionParam*> params);
+ /// Appends a new function parameter.
+ /// @param param the function parameter to append
+ void AppendParam(FunctionParam* param);
+
/// @returns the function parameters
const VectorRef<FunctionParam*> Params() { return params_; }
diff --git a/src/tint/lang/core/ir/function_test.cc b/src/tint/lang/core/ir/function_test.cc
index 27f332e..65a61ba 100644
--- a/src/tint/lang/core/ir/function_test.cc
+++ b/src/tint/lang/core/ir/function_test.cc
@@ -160,6 +160,11 @@
EXPECT_EQ(param1->Function(), f);
EXPECT_EQ(param2->Function(), nullptr);
EXPECT_EQ(param3->Function(), f);
+
+ f->AppendParam(param2);
+ EXPECT_EQ(param1->Function(), f);
+ EXPECT_EQ(param2->Function(), f);
+ EXPECT_EQ(param3->Function(), f);
}
} // namespace
diff --git a/src/tint/lang/core/ir/ice.h b/src/tint/lang/core/ir/ice.h
index 6487cc3..cdc3e09 100644
--- a/src/tint/lang/core/ir/ice.h
+++ b/src/tint/lang/core/ir/ice.h
@@ -28,10 +28,9 @@
#ifndef SRC_TINT_LANG_CORE_IR_ICE_H_
#define SRC_TINT_LANG_CORE_IR_ICE_H_
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
/// Emit an ICE message with the disassembly of `mod` attached.
-#define TINT_IR_ICE(mod) \
- TINT_ICE() << tint::core::ir::Disassembler{mod}.Disassemble().Plain() << "\n"
+#define TINT_IR_ICE(mod) TINT_ICE() << tint::core::ir::Disassemble(mod).Plain() << "\n"
#endif // SRC_TINT_LANG_CORE_IR_ICE_H_
diff --git a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
index 1e4b39e..7595c2c 100644
--- a/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
+++ b/src/tint/lang/core/ir/transform/bgra8unorm_polyfill_test.cc
@@ -525,7 +525,7 @@
auto* coords = b.FunctionParam("coords", ty.vec2<u32>());
auto* index = b.FunctionParam("index", ty.u32());
auto* value = b.FunctionParam("value", ty.vec4<f32>());
- func->SetParams({value, coords});
+ func->SetParams({value, coords, index, value});
b.Append(func->Block(), [&] {
auto* load = b.Load(var->Result(0));
b.Call(ty.void_(), core::BuiltinFn::kTextureStore, load, coords, index, value);
@@ -537,10 +537,10 @@
%texture:ptr<handle, texture_storage_2d_array<bgra8unorm, write>, read> = var @binding_point(1, 2)
}
-%foo = func(%value:vec4<f32>, %coords:vec2<u32>):void {
+%foo = func(%value:vec4<f32>, %coords:vec2<u32>, %index:u32%value:vec4<f32>):void {
$B2: {
- %5:texture_storage_2d_array<bgra8unorm, write> = load %texture
- %6:void = textureStore %5, %coords, %index, %value
+ %6:texture_storage_2d_array<bgra8unorm, write> = load %texture
+ %7:void = textureStore %6, %coords, %index, %value
ret
}
}
@@ -550,11 +550,11 @@
%texture:ptr<handle, texture_storage_2d_array<rgba8unorm, write>, read> = var @binding_point(1, 2)
}
-%foo = func(%value:vec4<f32>, %coords:vec2<u32>):void {
+%foo = func(%value:vec4<f32>, %coords:vec2<u32>, %index:u32%value:vec4<f32>):void {
$B2: {
- %5:texture_storage_2d_array<rgba8unorm, write> = load %texture
- %6:vec4<f32> = swizzle %value, zyxw
- %7:void = textureStore %5, %coords, %index, %6
+ %6:texture_storage_2d_array<rgba8unorm, write> = load %texture
+ %7:vec4<f32> = swizzle %value, zyxw
+ %8:void = textureStore %6, %coords, %index, %7
ret
}
}
diff --git a/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc b/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc
index 2d07019..404b94b 100644
--- a/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc
+++ b/src/tint/lang/core/ir/transform/combine_access_instructions_test.cc
@@ -677,6 +677,7 @@
auto* func = b.Function("foo", ty.f32());
auto* indices = b.FunctionParam("indices", ty.array<u32, 4>());
auto* values = b.FunctionParam("values", ty.array<f32, 4>());
+ func->SetParams({indices, values});
b.Append(func->Block(), [&] {
auto* access_index = b.Access(ty.u32(), indices, 1_u);
auto* access_value = b.Access(ty.f32(), values, access_index);
@@ -684,11 +685,11 @@
});
auto* src = R"(
-%foo = func():f32 {
+%foo = func(%indices:array<u32, 4>, %values:array<f32, 4>):f32 {
$B1: {
- %2:u32 = access %indices, 1u
- %4:f32 = access %values, %2
- ret %4
+ %4:u32 = access %indices, 1u
+ %5:f32 = access %values, %4
+ ret %5
}
}
)";
diff --git a/src/tint/lang/core/ir/transform/helper_test.h b/src/tint/lang/core/ir/transform/helper_test.h
index ef8e375..8daa4d0 100644
--- a/src/tint/lang/core/ir/transform/helper_test.h
+++ b/src/tint/lang/core/ir/transform/helper_test.h
@@ -35,7 +35,7 @@
#include "gtest/gtest.h"
#include "src/tint/lang/core/ir/builder.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/utils/containers/enum_set.h"
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
index d2d3263..d63e3ba 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
@@ -299,15 +299,20 @@
if (!external_texture_params_struct) {
external_texture_params_struct =
ty.Struct(sym.Register("tint_ExternalTextureParams"),
- {
- {sym.Register("numPlanes"), ty.u32()},
- {sym.Register("doYuvToRgbConversionOnly"), ty.u32()},
- {sym.Register("yuvToRgbConversionMatrix"), ty.mat3x4<f32>()},
- {sym.Register("gammaDecodeParams"), GammaTransferParams()},
- {sym.Register("gammaEncodeParams"), GammaTransferParams()},
- {sym.Register("gamutConversionMatrix"), ty.mat3x3<f32>()},
- {sym.Register("coordTransformationMatrix"), ty.mat3x2<f32>()},
- });
+ {{sym.Register("numPlanes"), ty.u32()},
+ {sym.Register("doYuvToRgbConversionOnly"), ty.u32()},
+ {sym.Register("yuvToRgbConversionMatrix"), ty.mat3x4<f32>()},
+ {sym.Register("gammaDecodeParams"), GammaTransferParams()},
+ {sym.Register("gammaEncodeParams"), GammaTransferParams()},
+ {sym.Register("gamutConversionMatrix"), ty.mat3x3<f32>()},
+ {sym.Register("coordTransformationMatrix"), ty.mat3x2<f32>()},
+ {sym.Register("loadTransformationMatrix"), ty.mat3x2<f32>()},
+ {sym.Register("samplePlane0RectMin"), ty.vec2<f32>()},
+ {sym.Register("samplePlane0RectMax"), ty.vec2<f32>()},
+ {sym.Register("samplePlane1RectMin"), ty.vec2<f32>()},
+ {sym.Register("samplePlane1RectMax"), ty.vec2<f32>()},
+ {sym.Register("displayVisibleRectMax"), ty.vec2<u32>()},
+ {sym.Register("plane1CoordFactor"), ty.vec2<f32>()}});
}
return external_texture_params_struct;
}
@@ -367,32 +372,31 @@
}
// The helper function implements the following:
- // fn tint_TextureLoadExternal(plane0 : texture_2d<f32>,
- // plane1 : texture_2d<f32>,
- // coords : vec2i,
- // params : ExternalTextureParams) -> vec4f {
- // var rgb : vec3f;
- // var alpha : f32;
+ // fn tint_TextureLoadExternal(plane0 : texture_2d<f32>,
+ // plane1 : texture_2d<f32>,
+ // coords : vec2<u32>,
+ // params : ExternalTextureParams) ->vec4f {
+ // let clampedCoords = min(coords, params.displayVisibleRectMax);
+ // let plane0_clamped = vec2<u32>(
+ // round(params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1)));
+ // var color : vec4<f32>;
// if ((params.numPlanes == 1)) {
- // let texel = textureLoad(plane0, coord, 0);
- // rgb = texel.rgb;
- // alpha = texel.a;
+ // color = textureLoad(plane0, plane0_clamped, 0).rgba;
// } else {
- // let y = textureLoad(plane0, coord, 0).r;
- // let coord_uv = (coord >> vec2u(1));
- // let uv = textureLoad(plane1, coord_uv, 0).rg;
- // rgb = vec4f(y, uv, 1) * params.yuvToRgbConversionMatrix;
- // alpha = 1.0;
- // }
+ // let plane1_clamped = vec2<f32>(plane0_clamped) * params.plane1CoordFactor;
//
- // if (params.doYuvToRgbConversionOnly == 0) {
- // rgb = gammaCorrection(rgb, params.gammaDecodeParams);
- // rgb = params.gamutConversionMatrix * rgb;
- // rgb = gammaCorrection(rgb, params.gammaEncodeParams);
+ // color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r,
+ // textureLoad(plane1, plane1_clamped, 0).rg, 1) *
+ // params.yuvToRgbConversionMatrix),
+ // 1);
// }
- //
- // return vec4f(rgb, alpha);
- // }
+ // if ((params.doYuvToRgbConversionOnly == 0)) {
+ // color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
+ // color = vec4<f32>((params.gamutConversionMatrix * color.rgb), color.a);
+ // color = vec4<f32>(gammaCorrection(color.rgb, params.gammaEncodeParams), color.a);
+ // }
+ // return color;
+ // }
texture_load_external = b.Function("tint_TextureLoadExternal", ty.vec4<f32>());
auto* plane_0 = b.FunctionParam("plane_0", SampledTexture());
auto* plane_1 = b.FunctionParam("plane_1", SampledTexture());
@@ -403,8 +407,21 @@
auto* vec2f = ty.vec2<f32>();
auto* vec3f = ty.vec3<f32>();
auto* vec4f = ty.vec4<f32>();
+ auto* vec2u = ty.vec2<u32>();
auto* yuv_to_rgb_conversion_only = b.Access(ty.u32(), params, 1_u);
auto* yuv_to_rgb_conversion = b.Access(ty.mat3x4<f32>(), params, 2_u);
+ auto* load_transform_matrix = b.Access(ty.mat3x2<f32>(), params, 7_u);
+ auto* display_visible_rect_max = b.Access(ty.vec2<u32>(), params, 12_u);
+ auto* plane1_coord_factor = b.Access(ty.vec2<f32>(), params, 13_u);
+
+ auto* clamped_coords =
+ b.Call(vec2u, core::BuiltinFn::kMin, coords, display_visible_rect_max);
+ auto* clamped_coords_f = b.Convert(vec2f, clamped_coords);
+ auto* modified_coords =
+ b.Multiply(vec2f, load_transform_matrix, b.Construct(vec3f, clamped_coords_f, 1_f));
+ auto* plane0_clamped_f = b.Call(vec2f, core::BuiltinFn::kRound, modified_coords);
+
+ auto* plane0_clamped = b.Convert(vec2u, plane0_clamped_f);
auto* rgb_result = b.InstructionResult(vec3f);
auto* alpha_result = b.InstructionResult(ty.f32());
@@ -413,7 +430,8 @@
if_planes_eq_1->SetResults(rgb_result, alpha_result);
b.Append(if_planes_eq_1->True(), [&] {
// Load the texel from the first plane and split into separate rgb and a values.
- auto* texel = b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, coords, 0_u);
+ auto* texel =
+ b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, plane0_clamped, 0_u);
auto* rgb = b.Swizzle(vec3f, texel, {0u, 1u, 2u});
auto* a = b.Access(ty.f32(), texel, 3_u);
b.ExitIf(if_planes_eq_1, rgb, a);
@@ -421,14 +439,17 @@
b.Append(if_planes_eq_1->False(), [&] {
// Load the y value from the first plane.
auto* y = b.Access(
- ty.f32(), b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, coords, 0_u),
+ ty.f32(),
+ b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_0, plane0_clamped, 0_u),
0_u);
// Load the uv value from the second plane.
- auto* coord_uv =
- b.ShiftRight(ty.vec2<u32>(), coords, b.Splat(ty.vec2<u32>(), 1_u, 2u));
+ auto* plane1_clamped_f = b.Multiply(vec2f, plane0_clamped_f, plane1_coord_factor);
+
+ auto* plane1_clamped = b.Convert(vec2u, plane1_clamped_f);
auto* uv = b.Swizzle(
- vec2f, b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_1, coord_uv, 0_u),
+ vec2f,
+ b.Call(vec4f, core::BuiltinFn::kTextureLoad, plane_1, plane1_clamped, 0_u),
{0u, 1u});
// Convert the combined yuv value into rgb and set the alpha to 1.0.
@@ -468,41 +489,36 @@
}
// The helper function implements the following:
- // fn textureSampleExternal(plane0 : texture_2d<f32>,
- // plane1 : texture_2d<f32>,
- // smp : sampler,
- // coord : vec2f,
- // params : ExternalTextureParams) -> vec4f {
- // let modified_coords = params.coordTransformationMatrix * vec3f(coord, 1);
- // let plane0_dims = vec2f(textureDimensions(plane0));
- // let plane0_half_texel = vec2f(0.5) / plane0_dims;
- // let plane0_clamped = clamp(modified_coords, plane0_half_texel,
- // (1 - plane0_half_texel));
- // let plane1_dims = vec2f(textureDimensions(plane1));
- // let plane1_half_texel = vec2f(0.5) / plane1_dims;
- // let plane1_clamped = clamp(modified_coords, plane1_half_texel,
- // (1 - plane1_half_texel));
- // var rgb : vec3f;
- // var alpha : f32;
+ // fn textureSampleExternal(plane0 : texture_2d<f32>,
+ // plane1 : texture_2d<f32>,
+ // smp : sampler,
+ // coord : vec2f,
+ // params : ExternalTextureParams) ->vec4f {
+ // let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
+ // let plane0_clamped =
+ // clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
+ // var color : vec4<f32>;
+ //
// if ((params.numPlanes == 1)) {
- // let texel = textureSampleLevel(plane0, smp, plane0_clamped, 0);
- // rgb = texel.rgb;
- // alpha = texel.a;
+ // color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
// } else {
- // let y = textureSampleLevel(plane0, smp, plane0_clamped, 0).r;
- // let uv = textureSampleLevel(plane1, smp, plane1_clamped, 0).rg;
- // rgb = vec4f(y, uv, 1.0) * params.yuvToRgbConversionMatrix;
- // alpha = 1.0;
+ // let plane1_clamped =
+ // clamp(modifiedCoords, params.samplePlane1RectMin,
+ // params.samplePlane1RectMax);
+ // color = vec4<f32>(
+ // vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r,
+ // textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) *
+ // params.yuvToRgbConversionMatrix), 1);
// }
//
- // if (params.doYuvToRgbConversionOnly == 0) {
- // rgb = gammaCorrection(rgb, params.gammaDecodeParams);
- // rgb = params.gamutConversionMatrix * rgb;
- // rgb = gammaCorrection(rgb, params.gammaEncodeParams);
+ // if ((params.doYuvToRgbConversionOnly == 0)) {
+ // color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
+ // color = vec4<f32>((params.gamutConversionMatrix * color.rgb), color.a);
+ // color = vec4<f32>(gammaCorrection(color.rgb, params.gammaEncodeParams), color.a);
// }
//
- // return vec4f(rgb, alpha);
- // }
+ // return color;
+ // }
texture_sample_external = b.Function("tint_TextureSampleExternal", ty.vec4<f32>());
auto* plane_0 = b.FunctionParam("plane_0", SampledTexture());
auto* plane_1 = b.FunctionParam("plane_1", SampledTexture());
@@ -517,21 +533,15 @@
auto* yuv_to_rgb_conversion_only = b.Access(ty.u32(), params, 1_u);
auto* yuv_to_rgb_conversion = b.Access(ty.mat3x4<f32>(), params, 2_u);
auto* transformation_matrix = b.Access(ty.mat3x2<f32>(), params, 6_u);
+ auto* sample_plane0_rect_min = b.Access(ty.vec2<f32>(), params, 8_u);
+ auto* sample_plane0_rect_max = b.Access(ty.vec2<f32>(), params, 9_u);
+ auto* sample_plane1_rect_min = b.Access(ty.vec2<f32>(), params, 10_u);
+ auto* sample_plane1_rect_max = b.Access(ty.vec2<f32>(), params, 11_u);
auto* modified_coords =
b.Multiply(vec2f, transformation_matrix, b.Construct(vec3f, coords, 1_f));
- auto* plane0_dims = b.Convert(
- vec2f, b.Call(ty.vec2<u32>(), core::BuiltinFn::kTextureDimensions, plane_0));
- auto* plane0_half_texel = b.Divide(vec2f, b.Splat(vec2f, 0.5_f, 2u), plane0_dims);
- auto* plane0_clamped =
- b.Call(vec2f, core::BuiltinFn::kClamp, modified_coords, plane0_half_texel,
- b.Subtract(vec2f, 1_f, plane0_half_texel));
- auto* plane1_dims = b.Convert(
- vec2f, b.Call(ty.vec2<u32>(), core::BuiltinFn::kTextureDimensions, plane_1));
- auto* plane1_half_texel = b.Divide(vec2f, b.Splat(vec2f, 0.5_f, 2u), plane1_dims);
- auto* plane1_clamped =
- b.Call(vec2f, core::BuiltinFn::kClamp, modified_coords, plane1_half_texel,
- b.Subtract(vec2f, 1_f, plane1_half_texel));
+ auto* plane0_clamped = b.Call(vec2f, core::BuiltinFn::kClamp, modified_coords,
+ sample_plane0_rect_min, sample_plane0_rect_max);
auto* rgb_result = b.InstructionResult(vec3f);
auto* alpha_result = b.InstructionResult(ty.f32());
@@ -552,6 +562,8 @@
b.Call(vec4f, core::BuiltinFn::kTextureSampleLevel, plane_0,
sampler, plane0_clamped, 0_f),
0_u);
+ auto* plane1_clamped = b.Call(vec2f, core::BuiltinFn::kClamp, modified_coords,
+ sample_plane1_rect_min, sample_plane1_rect_max);
// Sample the uv value from the second plane.
auto* uv = b.Swizzle(vec2f,
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
index dadb543..6597fb8 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
@@ -98,6 +98,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -164,6 +171,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -236,6 +250,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -311,6 +332,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -332,69 +360,79 @@
$B3: {
%15:u32 = access %params, 1u
%16:mat3x4<f32> = access %params, 2u
- %17:u32 = access %params, 0u
- %18:bool = eq %17, 1u
- %19:vec3<f32>, %20:f32 = if %18 [t: $B4, f: $B5] { # if_1
+ %17:mat3x2<f32> = access %params, 7u
+ %18:vec2<u32> = access %params, 12u
+ %19:vec2<f32> = access %params, 13u
+ %20:vec2<u32> = min %coords_1, %18
+ %21:vec2<f32> = convert %20
+ %22:vec3<f32> = construct %21, 1.0f
+ %23:vec2<f32> = mul %17, %22
+ %24:vec2<f32> = round %23
+ %25:vec2<u32> = convert %24
+ %26:u32 = access %params, 0u
+ %27:bool = eq %26, 1u
+ %28:vec3<f32>, %29:f32 = if %27 [t: $B4, f: $B5] { # if_1
$B4: { # true
- %21:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %22:vec3<f32> = swizzle %21, xyz
- %23:f32 = access %21, 3u
- exit_if %22, %23 # if_1
+ %30:vec4<f32> = textureLoad %plane_0, %25, 0u
+ %31:vec3<f32> = swizzle %30, xyz
+ %32:f32 = access %30, 3u
+ exit_if %31, %32 # if_1
}
$B5: { # false
- %24:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %25:f32 = access %24, 0u
- %26:vec2<u32> = shr %coords_1, vec2<u32>(1u)
- %27:vec4<f32> = textureLoad %plane_1, %26, 0u
- %28:vec2<f32> = swizzle %27, xy
- %29:vec4<f32> = construct %25, %28, 1.0f
- %30:vec3<f32> = mul %29, %16
- exit_if %30, 1.0f # if_1
+ %33:vec4<f32> = textureLoad %plane_0, %25, 0u
+ %34:f32 = access %33, 0u
+ %35:vec2<f32> = mul %24, %19
+ %36:vec2<u32> = convert %35
+ %37:vec4<f32> = textureLoad %plane_1, %36, 0u
+ %38:vec2<f32> = swizzle %37, xy
+ %39:vec4<f32> = construct %34, %38, 1.0f
+ %40:vec3<f32> = mul %39, %16
+ exit_if %40, 1.0f # if_1
}
}
- %31:bool = eq %15, 0u
- %32:vec3<f32> = if %31 [t: $B6, f: $B7] { # if_2
+ %41:bool = eq %15, 0u
+ %42:vec3<f32> = if %41 [t: $B6, f: $B7] { # if_2
$B6: { # true
- %33:tint_GammaTransferParams = access %params, 3u
- %34:tint_GammaTransferParams = access %params, 4u
- %35:mat3x3<f32> = access %params, 5u
- %36:vec3<f32> = call %tint_GammaCorrection, %19, %33
- %38:vec3<f32> = mul %35, %36
- %39:vec3<f32> = call %tint_GammaCorrection, %38, %34
- exit_if %39 # if_2
+ %43:tint_GammaTransferParams = access %params, 3u
+ %44:tint_GammaTransferParams = access %params, 4u
+ %45:mat3x3<f32> = access %params, 5u
+ %46:vec3<f32> = call %tint_GammaCorrection, %28, %43
+ %48:vec3<f32> = mul %45, %46
+ %49:vec3<f32> = call %tint_GammaCorrection, %48, %44
+ exit_if %49 # if_2
}
$B7: { # false
- exit_if %19 # if_2
+ exit_if %28 # if_2
}
}
- %40:vec4<f32> = construct %32, %20
- ret %40
+ %50:vec4<f32> = construct %42, %29
+ ret %50
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
- %43:f32 = access %params_1, 0u
- %44:f32 = access %params_1, 1u
- %45:f32 = access %params_1, 2u
- %46:f32 = access %params_1, 3u
- %47:f32 = access %params_1, 4u
- %48:f32 = access %params_1, 5u
- %49:f32 = access %params_1, 6u
- %50:vec3<f32> = construct %43
- %51:vec3<f32> = construct %47
- %52:vec3<f32> = abs %v
- %53:vec3<f32> = sign %v
- %54:vec3<bool> = lt %52, %51
- %55:vec3<f32> = mul %46, %52
- %56:vec3<f32> = add %55, %49
- %57:vec3<f32> = mul %53, %56
- %58:vec3<f32> = mul %44, %52
- %59:vec3<f32> = add %58, %45
- %60:vec3<f32> = pow %59, %50
- %61:vec3<f32> = add %60, %48
- %62:vec3<f32> = mul %53, %61
- %63:vec3<f32> = select %62, %57, %54
- ret %63
+ %53:f32 = access %params_1, 0u
+ %54:f32 = access %params_1, 1u
+ %55:f32 = access %params_1, 2u
+ %56:f32 = access %params_1, 3u
+ %57:f32 = access %params_1, 4u
+ %58:f32 = access %params_1, 5u
+ %59:f32 = access %params_1, 6u
+ %60:vec3<f32> = construct %53
+ %61:vec3<f32> = construct %57
+ %62:vec3<f32> = abs %v
+ %63:vec3<f32> = sign %v
+ %64:vec3<bool> = lt %62, %61
+ %65:vec3<f32> = mul %56, %62
+ %66:vec3<f32> = add %65, %59
+ %67:vec3<f32> = mul %63, %66
+ %68:vec3<f32> = mul %54, %62
+ %69:vec3<f32> = add %68, %55
+ %70:vec3<f32> = pow %69, %60
+ %71:vec3<f32> = add %70, %58
+ %72:vec3<f32> = mul %63, %71
+ %73:vec3<f32> = select %72, %67, %64
+ ret %73
}
}
)";
@@ -455,6 +493,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -477,69 +522,79 @@
$B3: {
%16:u32 = access %params, 1u
%17:mat3x4<f32> = access %params, 2u
- %18:u32 = access %params, 0u
- %19:bool = eq %18, 1u
- %20:vec3<f32>, %21:f32 = if %19 [t: $B4, f: $B5] { # if_1
+ %18:mat3x2<f32> = access %params, 7u
+ %19:vec2<u32> = access %params, 12u
+ %20:vec2<f32> = access %params, 13u
+ %21:vec2<u32> = min %coords_1, %19
+ %22:vec2<f32> = convert %21
+ %23:vec3<f32> = construct %22, 1.0f
+ %24:vec2<f32> = mul %18, %23
+ %25:vec2<f32> = round %24
+ %26:vec2<u32> = convert %25
+ %27:u32 = access %params, 0u
+ %28:bool = eq %27, 1u
+ %29:vec3<f32>, %30:f32 = if %28 [t: $B4, f: $B5] { # if_1
$B4: { # true
- %22:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %23:vec3<f32> = swizzle %22, xyz
- %24:f32 = access %22, 3u
- exit_if %23, %24 # if_1
+ %31:vec4<f32> = textureLoad %plane_0, %26, 0u
+ %32:vec3<f32> = swizzle %31, xyz
+ %33:f32 = access %31, 3u
+ exit_if %32, %33 # if_1
}
$B5: { # false
- %25:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %26:f32 = access %25, 0u
- %27:vec2<u32> = shr %coords_1, vec2<u32>(1u)
- %28:vec4<f32> = textureLoad %plane_1, %27, 0u
- %29:vec2<f32> = swizzle %28, xy
- %30:vec4<f32> = construct %26, %29, 1.0f
- %31:vec3<f32> = mul %30, %17
- exit_if %31, 1.0f # if_1
+ %34:vec4<f32> = textureLoad %plane_0, %26, 0u
+ %35:f32 = access %34, 0u
+ %36:vec2<f32> = mul %25, %20
+ %37:vec2<u32> = convert %36
+ %38:vec4<f32> = textureLoad %plane_1, %37, 0u
+ %39:vec2<f32> = swizzle %38, xy
+ %40:vec4<f32> = construct %35, %39, 1.0f
+ %41:vec3<f32> = mul %40, %17
+ exit_if %41, 1.0f # if_1
}
}
- %32:bool = eq %16, 0u
- %33:vec3<f32> = if %32 [t: $B6, f: $B7] { # if_2
+ %42:bool = eq %16, 0u
+ %43:vec3<f32> = if %42 [t: $B6, f: $B7] { # if_2
$B6: { # true
- %34:tint_GammaTransferParams = access %params, 3u
- %35:tint_GammaTransferParams = access %params, 4u
- %36:mat3x3<f32> = access %params, 5u
- %37:vec3<f32> = call %tint_GammaCorrection, %20, %34
- %39:vec3<f32> = mul %36, %37
- %40:vec3<f32> = call %tint_GammaCorrection, %39, %35
- exit_if %40 # if_2
+ %44:tint_GammaTransferParams = access %params, 3u
+ %45:tint_GammaTransferParams = access %params, 4u
+ %46:mat3x3<f32> = access %params, 5u
+ %47:vec3<f32> = call %tint_GammaCorrection, %29, %44
+ %49:vec3<f32> = mul %46, %47
+ %50:vec3<f32> = call %tint_GammaCorrection, %49, %45
+ exit_if %50 # if_2
}
$B7: { # false
- exit_if %20 # if_2
+ exit_if %29 # if_2
}
}
- %41:vec4<f32> = construct %33, %21
- ret %41
+ %51:vec4<f32> = construct %43, %30
+ ret %51
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
- %44:f32 = access %params_1, 0u
- %45:f32 = access %params_1, 1u
- %46:f32 = access %params_1, 2u
- %47:f32 = access %params_1, 3u
- %48:f32 = access %params_1, 4u
- %49:f32 = access %params_1, 5u
- %50:f32 = access %params_1, 6u
- %51:vec3<f32> = construct %44
- %52:vec3<f32> = construct %48
- %53:vec3<f32> = abs %v
- %54:vec3<f32> = sign %v
- %55:vec3<bool> = lt %53, %52
- %56:vec3<f32> = mul %47, %53
- %57:vec3<f32> = add %56, %50
- %58:vec3<f32> = mul %54, %57
- %59:vec3<f32> = mul %45, %53
- %60:vec3<f32> = add %59, %46
- %61:vec3<f32> = pow %60, %51
- %62:vec3<f32> = add %61, %49
- %63:vec3<f32> = mul %54, %62
- %64:vec3<f32> = select %63, %58, %55
- ret %64
+ %54:f32 = access %params_1, 0u
+ %55:f32 = access %params_1, 1u
+ %56:f32 = access %params_1, 2u
+ %57:f32 = access %params_1, 3u
+ %58:f32 = access %params_1, 4u
+ %59:f32 = access %params_1, 5u
+ %60:f32 = access %params_1, 6u
+ %61:vec3<f32> = construct %54
+ %62:vec3<f32> = construct %58
+ %63:vec3<f32> = abs %v
+ %64:vec3<f32> = sign %v
+ %65:vec3<bool> = lt %63, %62
+ %66:vec3<f32> = mul %57, %63
+ %67:vec3<f32> = add %66, %60
+ %68:vec3<f32> = mul %64, %67
+ %69:vec3<f32> = mul %55, %63
+ %70:vec3<f32> = add %69, %56
+ %71:vec3<f32> = pow %70, %61
+ %72:vec3<f32> = add %71, %59
+ %73:vec3<f32> = mul %64, %72
+ %74:vec3<f32> = select %73, %68, %65
+ ret %74
}
}
)";
@@ -602,6 +657,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -624,80 +686,76 @@
%17:u32 = access %params, 1u
%18:mat3x4<f32> = access %params, 2u
%19:mat3x2<f32> = access %params, 6u
- %20:vec3<f32> = construct %coords_1, 1.0f
- %21:vec2<f32> = mul %19, %20
- %22:vec2<u32> = textureDimensions %plane_0
- %23:vec2<f32> = convert %22
- %24:vec2<f32> = div vec2<f32>(0.5f), %23
- %25:vec2<f32> = sub 1.0f, %24
- %26:vec2<f32> = clamp %21, %24, %25
- %27:vec2<u32> = textureDimensions %plane_1
- %28:vec2<f32> = convert %27
- %29:vec2<f32> = div vec2<f32>(0.5f), %28
- %30:vec2<f32> = sub 1.0f, %29
- %31:vec2<f32> = clamp %21, %29, %30
- %32:u32 = access %params, 0u
- %33:bool = eq %32, 1u
- %34:vec3<f32>, %35:f32 = if %33 [t: $B4, f: $B5] { # if_1
+ %20:vec2<f32> = access %params, 8u
+ %21:vec2<f32> = access %params, 9u
+ %22:vec2<f32> = access %params, 10u
+ %23:vec2<f32> = access %params, 11u
+ %24:vec3<f32> = construct %coords_1, 1.0f
+ %25:vec2<f32> = mul %19, %24
+ %26:vec2<f32> = clamp %25, %20, %21
+ %27:u32 = access %params, 0u
+ %28:bool = eq %27, 1u
+ %29:vec3<f32>, %30:f32 = if %28 [t: $B4, f: $B5] { # if_1
$B4: { # true
- %36:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
- %37:vec3<f32> = swizzle %36, xyz
- %38:f32 = access %36, 3u
- exit_if %37, %38 # if_1
+ %31:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
+ %32:vec3<f32> = swizzle %31, xyz
+ %33:f32 = access %31, 3u
+ exit_if %32, %33 # if_1
}
$B5: { # false
- %39:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
- %40:f32 = access %39, 0u
- %41:vec4<f32> = textureSampleLevel %plane_1, %sampler_1, %31, 0.0f
- %42:vec2<f32> = swizzle %41, xy
- %43:vec4<f32> = construct %40, %42, 1.0f
- %44:vec3<f32> = mul %43, %18
- exit_if %44, 1.0f # if_1
+ %34:vec4<f32> = textureSampleLevel %plane_0, %sampler_1, %26, 0.0f
+ %35:f32 = access %34, 0u
+ %36:vec2<f32> = clamp %25, %22, %23
+ %37:vec4<f32> = textureSampleLevel %plane_1, %sampler_1, %36, 0.0f
+ %38:vec2<f32> = swizzle %37, xy
+ %39:vec4<f32> = construct %35, %38, 1.0f
+ %40:vec3<f32> = mul %39, %18
+ exit_if %40, 1.0f # if_1
}
}
- %45:bool = eq %17, 0u
- %46:vec3<f32> = if %45 [t: $B6, f: $B7] { # if_2
+ %41:bool = eq %17, 0u
+ %42:vec3<f32> = if %41 [t: $B6, f: $B7] { # if_2
$B6: { # true
- %47:tint_GammaTransferParams = access %params, 3u
- %48:tint_GammaTransferParams = access %params, 4u
- %49:mat3x3<f32> = access %params, 5u
- %50:vec3<f32> = call %tint_GammaCorrection, %34, %47
- %52:vec3<f32> = mul %49, %50
- %53:vec3<f32> = call %tint_GammaCorrection, %52, %48
- exit_if %53 # if_2
+ %43:tint_GammaTransferParams = access %params, 3u
+ %44:tint_GammaTransferParams = access %params, 4u
+ %45:mat3x3<f32> = access %params, 5u
+ %46:vec3<f32> = call %tint_GammaCorrection, %29, %43
+ %48:vec3<f32> = mul %45, %46
+ %49:vec3<f32> = call %tint_GammaCorrection, %48, %44
+ exit_if %49 # if_2
}
$B7: { # false
- exit_if %34 # if_2
+ exit_if %29 # if_2
}
}
- %54:vec4<f32> = construct %46, %35
- ret %54
+ %50:vec4<f32> = construct %42, %30
+ ret %50
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
- %57:f32 = access %params_1, 0u
- %58:f32 = access %params_1, 1u
- %59:f32 = access %params_1, 2u
- %60:f32 = access %params_1, 3u
- %61:f32 = access %params_1, 4u
- %62:f32 = access %params_1, 5u
- %63:f32 = access %params_1, 6u
- %64:vec3<f32> = construct %57
- %65:vec3<f32> = construct %61
- %66:vec3<f32> = abs %v
- %67:vec3<f32> = sign %v
- %68:vec3<bool> = lt %66, %65
- %69:vec3<f32> = mul %60, %66
- %70:vec3<f32> = add %69, %63
- %71:vec3<f32> = mul %67, %70
- %72:vec3<f32> = mul %58, %66
- %73:vec3<f32> = add %72, %59
- %74:vec3<f32> = pow %73, %64
- %75:vec3<f32> = add %74, %62
- %76:vec3<f32> = mul %67, %75
- %77:vec3<f32> = select %76, %71, %68
- ret %77
+ %53:f32 = access %params_1, 0u
+ %54:f32 = access %params_1, 1u
+ %55:f32 = access %params_1, 2u
+ %56:f32 = access %params_1, 3u
+ %57:f32 = access %params_1, 4u
+ %58:f32 = access %params_1, 5u
+ %59:f32 = access %params_1, 6u
+ %60:vec3<f32> = construct %53
+ %61:vec3<f32> = construct %57
+ %62:vec3<f32> = abs %v
+ %63:vec3<f32> = sign %v
+ %64:vec3<bool> = lt %62, %61
+ %65:vec3<f32> = mul %56, %62
+ %66:vec3<f32> = add %65, %59
+ %67:vec3<f32> = mul %63, %66
+ %68:vec3<f32> = mul %54, %62
+ %69:vec3<f32> = add %68, %55
+ %70:vec3<f32> = pow %69, %60
+ %71:vec3<f32> = add %70, %58
+ %72:vec3<f32> = mul %63, %71
+ %73:vec3<f32> = select %72, %67, %64
+ ret %73
}
}
)";
@@ -781,6 +839,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -809,80 +874,76 @@
%24:u32 = access %params, 1u
%25:mat3x4<f32> = access %params, 2u
%26:mat3x2<f32> = access %params, 6u
- %27:vec3<f32> = construct %coords_2, 1.0f
- %28:vec2<f32> = mul %26, %27
- %29:vec2<u32> = textureDimensions %plane_0
- %30:vec2<f32> = convert %29
- %31:vec2<f32> = div vec2<f32>(0.5f), %30
- %32:vec2<f32> = sub 1.0f, %31
- %33:vec2<f32> = clamp %28, %31, %32
- %34:vec2<u32> = textureDimensions %plane_1
- %35:vec2<f32> = convert %34
- %36:vec2<f32> = div vec2<f32>(0.5f), %35
- %37:vec2<f32> = sub 1.0f, %36
- %38:vec2<f32> = clamp %28, %36, %37
- %39:u32 = access %params, 0u
- %40:bool = eq %39, 1u
- %41:vec3<f32>, %42:f32 = if %40 [t: $B5, f: $B6] { # if_1
+ %27:vec2<f32> = access %params, 8u
+ %28:vec2<f32> = access %params, 9u
+ %29:vec2<f32> = access %params, 10u
+ %30:vec2<f32> = access %params, 11u
+ %31:vec3<f32> = construct %coords_2, 1.0f
+ %32:vec2<f32> = mul %26, %31
+ %33:vec2<f32> = clamp %32, %27, %28
+ %34:u32 = access %params, 0u
+ %35:bool = eq %34, 1u
+ %36:vec3<f32>, %37:f32 = if %35 [t: $B5, f: $B6] { # if_1
$B5: { # true
- %43:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
- %44:vec3<f32> = swizzle %43, xyz
- %45:f32 = access %43, 3u
- exit_if %44, %45 # if_1
+ %38:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
+ %39:vec3<f32> = swizzle %38, xyz
+ %40:f32 = access %38, 3u
+ exit_if %39, %40 # if_1
}
$B6: { # false
- %46:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
- %47:f32 = access %46, 0u
- %48:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %38, 0.0f
- %49:vec2<f32> = swizzle %48, xy
- %50:vec4<f32> = construct %47, %49, 1.0f
- %51:vec3<f32> = mul %50, %25
- exit_if %51, 1.0f # if_1
+ %41:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %33, 0.0f
+ %42:f32 = access %41, 0u
+ %43:vec2<f32> = clamp %32, %29, %30
+ %44:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %43, 0.0f
+ %45:vec2<f32> = swizzle %44, xy
+ %46:vec4<f32> = construct %42, %45, 1.0f
+ %47:vec3<f32> = mul %46, %25
+ exit_if %47, 1.0f # if_1
}
}
- %52:bool = eq %24, 0u
- %53:vec3<f32> = if %52 [t: $B7, f: $B8] { # if_2
+ %48:bool = eq %24, 0u
+ %49:vec3<f32> = if %48 [t: $B7, f: $B8] { # if_2
$B7: { # true
- %54:tint_GammaTransferParams = access %params, 3u
- %55:tint_GammaTransferParams = access %params, 4u
- %56:mat3x3<f32> = access %params, 5u
- %57:vec3<f32> = call %tint_GammaCorrection, %41, %54
- %59:vec3<f32> = mul %56, %57
- %60:vec3<f32> = call %tint_GammaCorrection, %59, %55
- exit_if %60 # if_2
+ %50:tint_GammaTransferParams = access %params, 3u
+ %51:tint_GammaTransferParams = access %params, 4u
+ %52:mat3x3<f32> = access %params, 5u
+ %53:vec3<f32> = call %tint_GammaCorrection, %36, %50
+ %55:vec3<f32> = mul %52, %53
+ %56:vec3<f32> = call %tint_GammaCorrection, %55, %51
+ exit_if %56 # if_2
}
$B8: { # false
- exit_if %41 # if_2
+ exit_if %36 # if_2
}
}
- %61:vec4<f32> = construct %53, %42
- ret %61
+ %57:vec4<f32> = construct %49, %37
+ ret %57
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B9: {
- %64:f32 = access %params_1, 0u
- %65:f32 = access %params_1, 1u
- %66:f32 = access %params_1, 2u
- %67:f32 = access %params_1, 3u
- %68:f32 = access %params_1, 4u
- %69:f32 = access %params_1, 5u
- %70:f32 = access %params_1, 6u
- %71:vec3<f32> = construct %64
- %72:vec3<f32> = construct %68
- %73:vec3<f32> = abs %v
- %74:vec3<f32> = sign %v
- %75:vec3<bool> = lt %73, %72
- %76:vec3<f32> = mul %67, %73
- %77:vec3<f32> = add %76, %70
- %78:vec3<f32> = mul %74, %77
- %79:vec3<f32> = mul %65, %73
- %80:vec3<f32> = add %79, %66
- %81:vec3<f32> = pow %80, %71
- %82:vec3<f32> = add %81, %69
- %83:vec3<f32> = mul %74, %82
- %84:vec3<f32> = select %83, %78, %75
- ret %84
+ %60:f32 = access %params_1, 0u
+ %61:f32 = access %params_1, 1u
+ %62:f32 = access %params_1, 2u
+ %63:f32 = access %params_1, 3u
+ %64:f32 = access %params_1, 4u
+ %65:f32 = access %params_1, 5u
+ %66:f32 = access %params_1, 6u
+ %67:vec3<f32> = construct %60
+ %68:vec3<f32> = construct %64
+ %69:vec3<f32> = abs %v
+ %70:vec3<f32> = sign %v
+ %71:vec3<bool> = lt %69, %68
+ %72:vec3<f32> = mul %63, %69
+ %73:vec3<f32> = add %72, %66
+ %74:vec3<f32> = mul %70, %73
+ %75:vec3<f32> = mul %61, %69
+ %76:vec3<f32> = add %75, %62
+ %77:vec3<f32> = pow %76, %67
+ %78:vec3<f32> = add %77, %65
+ %79:vec3<f32> = mul %70, %78
+ %80:vec3<f32> = select %79, %74, %71
+ ret %80
}
}
)";
@@ -984,6 +1045,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -1026,80 +1094,76 @@
%38:u32 = access %params, 1u
%39:mat3x4<f32> = access %params, 2u
%40:mat3x2<f32> = access %params, 6u
- %41:vec3<f32> = construct %coords_2, 1.0f
- %42:vec2<f32> = mul %40, %41
- %43:vec2<u32> = textureDimensions %plane_0
- %44:vec2<f32> = convert %43
- %45:vec2<f32> = div vec2<f32>(0.5f), %44
- %46:vec2<f32> = sub 1.0f, %45
- %47:vec2<f32> = clamp %42, %45, %46
- %48:vec2<u32> = textureDimensions %plane_1
- %49:vec2<f32> = convert %48
- %50:vec2<f32> = div vec2<f32>(0.5f), %49
- %51:vec2<f32> = sub 1.0f, %50
- %52:vec2<f32> = clamp %42, %50, %51
- %53:u32 = access %params, 0u
- %54:bool = eq %53, 1u
- %55:vec3<f32>, %56:f32 = if %54 [t: $B5, f: $B6] { # if_1
+ %41:vec2<f32> = access %params, 8u
+ %42:vec2<f32> = access %params, 9u
+ %43:vec2<f32> = access %params, 10u
+ %44:vec2<f32> = access %params, 11u
+ %45:vec3<f32> = construct %coords_2, 1.0f
+ %46:vec2<f32> = mul %40, %45
+ %47:vec2<f32> = clamp %46, %41, %42
+ %48:u32 = access %params, 0u
+ %49:bool = eq %48, 1u
+ %50:vec3<f32>, %51:f32 = if %49 [t: $B5, f: $B6] { # if_1
$B5: { # true
- %57:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
- %58:vec3<f32> = swizzle %57, xyz
- %59:f32 = access %57, 3u
- exit_if %58, %59 # if_1
+ %52:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
+ %53:vec3<f32> = swizzle %52, xyz
+ %54:f32 = access %52, 3u
+ exit_if %53, %54 # if_1
}
$B6: { # false
- %60:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
- %61:f32 = access %60, 0u
- %62:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %52, 0.0f
- %63:vec2<f32> = swizzle %62, xy
- %64:vec4<f32> = construct %61, %63, 1.0f
- %65:vec3<f32> = mul %64, %39
- exit_if %65, 1.0f # if_1
+ %55:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
+ %56:f32 = access %55, 0u
+ %57:vec2<f32> = clamp %46, %43, %44
+ %58:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %57, 0.0f
+ %59:vec2<f32> = swizzle %58, xy
+ %60:vec4<f32> = construct %56, %59, 1.0f
+ %61:vec3<f32> = mul %60, %39
+ exit_if %61, 1.0f # if_1
}
}
- %66:bool = eq %38, 0u
- %67:vec3<f32> = if %66 [t: $B7, f: $B8] { # if_2
+ %62:bool = eq %38, 0u
+ %63:vec3<f32> = if %62 [t: $B7, f: $B8] { # if_2
$B7: { # true
- %68:tint_GammaTransferParams = access %params, 3u
- %69:tint_GammaTransferParams = access %params, 4u
- %70:mat3x3<f32> = access %params, 5u
- %71:vec3<f32> = call %tint_GammaCorrection, %55, %68
- %73:vec3<f32> = mul %70, %71
- %74:vec3<f32> = call %tint_GammaCorrection, %73, %69
- exit_if %74 # if_2
+ %64:tint_GammaTransferParams = access %params, 3u
+ %65:tint_GammaTransferParams = access %params, 4u
+ %66:mat3x3<f32> = access %params, 5u
+ %67:vec3<f32> = call %tint_GammaCorrection, %50, %64
+ %69:vec3<f32> = mul %66, %67
+ %70:vec3<f32> = call %tint_GammaCorrection, %69, %65
+ exit_if %70 # if_2
}
$B8: { # false
- exit_if %55 # if_2
+ exit_if %50 # if_2
}
}
- %75:vec4<f32> = construct %67, %56
- ret %75
+ %71:vec4<f32> = construct %63, %51
+ ret %71
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B9: {
- %78:f32 = access %params_1, 0u
- %79:f32 = access %params_1, 1u
- %80:f32 = access %params_1, 2u
- %81:f32 = access %params_1, 3u
- %82:f32 = access %params_1, 4u
- %83:f32 = access %params_1, 5u
- %84:f32 = access %params_1, 6u
- %85:vec3<f32> = construct %78
- %86:vec3<f32> = construct %82
- %87:vec3<f32> = abs %v
- %88:vec3<f32> = sign %v
- %89:vec3<bool> = lt %87, %86
- %90:vec3<f32> = mul %81, %87
- %91:vec3<f32> = add %90, %84
- %92:vec3<f32> = mul %88, %91
- %93:vec3<f32> = mul %79, %87
- %94:vec3<f32> = add %93, %80
- %95:vec3<f32> = pow %94, %85
- %96:vec3<f32> = add %95, %83
- %97:vec3<f32> = mul %88, %96
- %98:vec3<f32> = select %97, %92, %89
- ret %98
+ %74:f32 = access %params_1, 0u
+ %75:f32 = access %params_1, 1u
+ %76:f32 = access %params_1, 2u
+ %77:f32 = access %params_1, 3u
+ %78:f32 = access %params_1, 4u
+ %79:f32 = access %params_1, 5u
+ %80:f32 = access %params_1, 6u
+ %81:vec3<f32> = construct %74
+ %82:vec3<f32> = construct %78
+ %83:vec3<f32> = abs %v
+ %84:vec3<f32> = sign %v
+ %85:vec3<bool> = lt %83, %82
+ %86:vec3<f32> = mul %77, %83
+ %87:vec3<f32> = add %86, %80
+ %88:vec3<f32> = mul %84, %87
+ %89:vec3<f32> = mul %75, %83
+ %90:vec3<f32> = add %89, %76
+ %91:vec3<f32> = pow %90, %81
+ %92:vec3<f32> = add %91, %79
+ %93:vec3<f32> = mul %84, %92
+ %94:vec3<f32> = select %93, %88, %85
+ ret %94
}
}
)";
@@ -1177,6 +1241,13 @@
gammaEncodeParams:tint_GammaTransferParams @offset(96)
gamutConversionMatrix:mat3x3<f32> @offset(128)
coordTransformationMatrix:mat3x2<f32> @offset(176)
+ loadTransformationMatrix:mat3x2<f32> @offset(200)
+ samplePlane0RectMin:vec2<f32> @offset(224)
+ samplePlane0RectMax:vec2<f32> @offset(232)
+ samplePlane1RectMin:vec2<f32> @offset(240)
+ samplePlane1RectMax:vec2<f32> @offset(248)
+ displayVisibleRectMax:vec2<u32> @offset(256)
+ plane1CoordFactor:vec2<f32> @offset(264)
}
$B1: { # root
@@ -1212,69 +1283,79 @@
$B3: {
%29:u32 = access %params, 1u
%30:mat3x4<f32> = access %params, 2u
- %31:u32 = access %params, 0u
- %32:bool = eq %31, 1u
- %33:vec3<f32>, %34:f32 = if %32 [t: $B4, f: $B5] { # if_1
+ %31:mat3x2<f32> = access %params, 7u
+ %32:vec2<u32> = access %params, 12u
+ %33:vec2<f32> = access %params, 13u
+ %34:vec2<u32> = min %coords_1, %32
+ %35:vec2<f32> = convert %34
+ %36:vec3<f32> = construct %35, 1.0f
+ %37:vec2<f32> = mul %31, %36
+ %38:vec2<f32> = round %37
+ %39:vec2<u32> = convert %38
+ %40:u32 = access %params, 0u
+ %41:bool = eq %40, 1u
+ %42:vec3<f32>, %43:f32 = if %41 [t: $B4, f: $B5] { # if_1
$B4: { # true
- %35:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %36:vec3<f32> = swizzle %35, xyz
- %37:f32 = access %35, 3u
- exit_if %36, %37 # if_1
+ %44:vec4<f32> = textureLoad %plane_0, %39, 0u
+ %45:vec3<f32> = swizzle %44, xyz
+ %46:f32 = access %44, 3u
+ exit_if %45, %46 # if_1
}
$B5: { # false
- %38:vec4<f32> = textureLoad %plane_0, %coords_1, 0u
- %39:f32 = access %38, 0u
- %40:vec2<u32> = shr %coords_1, vec2<u32>(1u)
- %41:vec4<f32> = textureLoad %plane_1, %40, 0u
- %42:vec2<f32> = swizzle %41, xy
- %43:vec4<f32> = construct %39, %42, 1.0f
- %44:vec3<f32> = mul %43, %30
- exit_if %44, 1.0f # if_1
+ %47:vec4<f32> = textureLoad %plane_0, %39, 0u
+ %48:f32 = access %47, 0u
+ %49:vec2<f32> = mul %38, %33
+ %50:vec2<u32> = convert %49
+ %51:vec4<f32> = textureLoad %plane_1, %50, 0u
+ %52:vec2<f32> = swizzle %51, xy
+ %53:vec4<f32> = construct %48, %52, 1.0f
+ %54:vec3<f32> = mul %53, %30
+ exit_if %54, 1.0f # if_1
}
}
- %45:bool = eq %29, 0u
- %46:vec3<f32> = if %45 [t: $B6, f: $B7] { # if_2
+ %55:bool = eq %29, 0u
+ %56:vec3<f32> = if %55 [t: $B6, f: $B7] { # if_2
$B6: { # true
- %47:tint_GammaTransferParams = access %params, 3u
- %48:tint_GammaTransferParams = access %params, 4u
- %49:mat3x3<f32> = access %params, 5u
- %50:vec3<f32> = call %tint_GammaCorrection, %33, %47
- %52:vec3<f32> = mul %49, %50
- %53:vec3<f32> = call %tint_GammaCorrection, %52, %48
- exit_if %53 # if_2
+ %57:tint_GammaTransferParams = access %params, 3u
+ %58:tint_GammaTransferParams = access %params, 4u
+ %59:mat3x3<f32> = access %params, 5u
+ %60:vec3<f32> = call %tint_GammaCorrection, %42, %57
+ %62:vec3<f32> = mul %59, %60
+ %63:vec3<f32> = call %tint_GammaCorrection, %62, %58
+ exit_if %63 # if_2
}
$B7: { # false
- exit_if %33 # if_2
+ exit_if %42 # if_2
}
}
- %54:vec4<f32> = construct %46, %34
- ret %54
+ %64:vec4<f32> = construct %56, %43
+ ret %64
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B8: {
- %57:f32 = access %params_1, 0u
- %58:f32 = access %params_1, 1u
- %59:f32 = access %params_1, 2u
- %60:f32 = access %params_1, 3u
- %61:f32 = access %params_1, 4u
- %62:f32 = access %params_1, 5u
- %63:f32 = access %params_1, 6u
- %64:vec3<f32> = construct %57
- %65:vec3<f32> = construct %61
- %66:vec3<f32> = abs %v
- %67:vec3<f32> = sign %v
- %68:vec3<bool> = lt %66, %65
- %69:vec3<f32> = mul %60, %66
- %70:vec3<f32> = add %69, %63
- %71:vec3<f32> = mul %67, %70
- %72:vec3<f32> = mul %58, %66
- %73:vec3<f32> = add %72, %59
- %74:vec3<f32> = pow %73, %64
- %75:vec3<f32> = add %74, %62
- %76:vec3<f32> = mul %67, %75
- %77:vec3<f32> = select %76, %71, %68
- ret %77
+ %67:f32 = access %params_1, 0u
+ %68:f32 = access %params_1, 1u
+ %69:f32 = access %params_1, 2u
+ %70:f32 = access %params_1, 3u
+ %71:f32 = access %params_1, 4u
+ %72:f32 = access %params_1, 5u
+ %73:f32 = access %params_1, 6u
+ %74:vec3<f32> = construct %67
+ %75:vec3<f32> = construct %71
+ %76:vec3<f32> = abs %v
+ %77:vec3<f32> = sign %v
+ %78:vec3<bool> = lt %76, %75
+ %79:vec3<f32> = mul %70, %76
+ %80:vec3<f32> = add %79, %73
+ %81:vec3<f32> = mul %77, %80
+ %82:vec3<f32> = mul %68, %76
+ %83:vec3<f32> = add %82, %69
+ %84:vec3<f32> = pow %83, %74
+ %85:vec3<f32> = add %84, %72
+ %86:vec3<f32> = mul %77, %85
+ %87:vec3<f32> = select %86, %81, %78
+ ret %87
}
}
)";
diff --git a/src/tint/lang/core/ir/transform/preserve_padding_test.cc b/src/tint/lang/core/ir/transform/preserve_padding_test.cc
index 83f5942..188029c 100644
--- a/src/tint/lang/core/ir/transform/preserve_padding_test.cc
+++ b/src/tint/lang/core/ir/transform/preserve_padding_test.cc
@@ -661,19 +661,19 @@
next_iteration 0u # -> $B5
}
$B5 (%idx:u32): { # body
- %9:bool = gte %idx:u32, 4u
+ %9:bool = gte %idx, 4u
if %9 [t: $B7] { # if_1
$B7: { # true
exit_loop # loop_1
}
}
- %10:ptr<storage, MyStruct, read_write> = access %target, %idx:u32
- %11:MyStruct = access %value_param, %idx:u32
+ %10:ptr<storage, MyStruct, read_write> = access %target, %idx
+ %11:MyStruct = access %value_param, %idx
%12:void = call %tint_store_and_preserve_padding_1, %10, %11
continue # -> $B6
}
$B6: { # continuing
- %14:u32 = add %idx:u32, 1u
+ %14:u32 = add %idx, 1u
next_iteration %14 # -> $B5
}
}
@@ -893,19 +893,19 @@
next_iteration 0u # -> $B5
}
$B5 (%idx:u32): { # body
- %9:bool = gte %idx:u32, 4u
+ %9:bool = gte %idx, 4u
if %9 [t: $B7] { # if_1
$B7: { # true
exit_loop # loop_1
}
}
- %10:ptr<storage, mat3x3<f32>, read_write> = access %target, %idx:u32
- %11:mat3x3<f32> = access %value_param, %idx:u32
+ %10:ptr<storage, mat3x3<f32>, read_write> = access %target, %idx
+ %11:mat3x3<f32> = access %value_param, %idx
%12:void = call %tint_store_and_preserve_padding_1, %10, %11
continue # -> $B6
}
$B6: { # continuing
- %14:u32 = add %idx:u32, 1u
+ %14:u32 = add %idx, 1u
next_iteration %14 # -> $B5
}
}
@@ -980,19 +980,19 @@
next_iteration 0u # -> $B5
}
$B5 (%idx:u32): { # body
- %9:bool = gte %idx:u32, 4u
+ %9:bool = gte %idx, 4u
if %9 [t: $B7] { # if_1
$B7: { # true
exit_loop # loop_1
}
}
- %10:ptr<storage, vec3<f32>, read_write> = access %target, %idx:u32
- %11:vec3<f32> = access %value_param, %idx:u32
+ %10:ptr<storage, vec3<f32>, read_write> = access %target, %idx
+ %11:vec3<f32> = access %value_param, %idx
store %10, %11
continue # -> $B6
}
$B6: { # continuing
- %12:u32 = add %idx:u32, 1u
+ %12:u32 = add %idx, 1u
next_iteration %12 # -> $B5
}
}
@@ -1095,19 +1095,19 @@
next_iteration 0u # -> $B5
}
$B5 (%idx:u32): { # body
- %9:bool = gte %idx:u32, 3u
+ %9:bool = gte %idx, 3u
if %9 [t: $B7] { # if_1
$B7: { # true
exit_loop # loop_1
}
}
- %10:ptr<storage, Outer, read_write> = access %target, %idx:u32
- %11:Outer = access %value_param, %idx:u32
+ %10:ptr<storage, Outer, read_write> = access %target, %idx
+ %11:Outer = access %value_param, %idx
%12:void = call %tint_store_and_preserve_padding_1, %10, %11
continue # -> $B6
}
$B6: { # continuing
- %14:u32 = add %idx:u32, 1u
+ %14:u32 = add %idx, 1u
next_iteration %14 # -> $B5
}
}
@@ -1155,19 +1155,19 @@
next_iteration 0u # -> $B12
}
$B12 (%idx_1:u32): { # body
- %46:bool = gte %idx_1:u32, 4u
+ %46:bool = gte %idx_1, 4u
if %46 [t: $B14] { # if_2
$B14: { # true
exit_loop # loop_2
}
}
- %47:ptr<storage, vec3<f32>, read_write> = access %target_3, %idx_1:u32
- %48:vec3<f32> = access %value_param_3, %idx_1:u32
+ %47:ptr<storage, vec3<f32>, read_write> = access %target_3, %idx_1
+ %48:vec3<f32> = access %value_param_3, %idx_1
store %47, %48
continue # -> $B13
}
$B13: { # continuing
- %49:u32 = add %idx_1:u32, 1u
+ %49:u32 = add %idx_1, 1u
next_iteration %49 # -> $B12
}
}
@@ -1195,19 +1195,19 @@
next_iteration 0u # -> $B18
}
$B18 (%idx_2:u32): { # body
- %61:bool = gte %idx_2:u32, 4u
+ %61:bool = gte %idx_2, 4u
if %61 [t: $B20] { # if_3
$B20: { # true
exit_loop # loop_3
}
}
- %62:ptr<storage, Inner, read_write> = access %target_5, %idx_2:u32
- %63:Inner = access %value_param_5, %idx_2:u32
+ %62:ptr<storage, Inner, read_write> = access %target_5, %idx_2
+ %63:Inner = access %value_param_5, %idx_2
%64:void = call %tint_store_and_preserve_padding_2, %62, %63
continue # -> $B19
}
$B19: { # continuing
- %65:u32 = add %idx_2:u32, 1u
+ %65:u32 = add %idx_2, 1u
next_iteration %65 # -> $B18
}
}
diff --git a/src/tint/lang/core/ir/transform/std140_test.cc b/src/tint/lang/core/ir/transform/std140_test.cc
index 4b819bb..dd55108 100644
--- a/src/tint/lang/core/ir/transform/std140_test.cc
+++ b/src/tint/lang/core/ir/transform/std140_test.cc
@@ -565,20 +565,20 @@
next_iteration 0u # -> $B5
}
$B5 (%idx:u32): { # body
- %10:bool = gte %idx:u32, 4u
+ %10:bool = gte %idx, 4u
if %10 [t: $B7] { # if_1
$B7: { # true
exit_loop # loop_1
}
}
- %11:ptr<function, Inner, read_write> = access %8, %idx:u32
- %12:Inner_std140 = access %7, %idx:u32
+ %11:ptr<function, Inner, read_write> = access %8, %idx
+ %12:Inner_std140 = access %7, %idx
%13:Inner = call %convert_Inner, %12
store %11, %13
continue # -> $B6
}
$B6: { # continuing
- %15:u32 = add %idx:u32, 1u
+ %15:u32 = add %idx, 1u
next_iteration %15 # -> $B5
}
}
@@ -906,20 +906,20 @@
next_iteration 0u # -> $B4
}
$B4 (%idx:u32): { # body
- %16:bool = gte %idx:u32, 4u
+ %16:bool = gte %idx, 4u
if %16 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %17:ptr<function, Inner, read_write> = access %14, %idx:u32
- %18:Inner_std140 = access %13, %idx:u32
+ %17:ptr<function, Inner, read_write> = access %14, %idx
+ %18:Inner_std140 = access %13, %idx
%19:Inner = call %convert_Inner, %18
store %17, %19
continue # -> $B5
}
$B5: { # continuing
- %21:u32 = add %idx:u32, 1u
+ %21:u32 = add %idx, 1u
next_iteration %21 # -> $B4
}
}
@@ -1081,20 +1081,20 @@
next_iteration 0u # -> $B4
}
$B4 (%idx:u32): { # body
- %16:bool = gte %idx:u32, 4u
+ %16:bool = gte %idx, 4u
if %16 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %17:ptr<function, Inner, read_write> = access %14, %idx:u32
- %18:Inner_std140 = access %13, %idx:u32
+ %17:ptr<function, Inner, read_write> = access %14, %idx
+ %18:Inner_std140 = access %13, %idx
%19:Inner = call %convert_Inner, %18
store %17, %19
continue # -> $B5
}
$B5: { # continuing
- %21:u32 = add %idx:u32, 1u
+ %21:u32 = add %idx, 1u
next_iteration %21 # -> $B4
}
}
@@ -1255,20 +1255,20 @@
next_iteration 0u # -> $B4
}
$B4 (%idx:u32): { # body
- %19:bool = gte %idx:u32, 4u
+ %19:bool = gte %idx, 4u
if %19 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %20:ptr<function, Inner, read_write> = access %17, %idx:u32
- %21:Inner_std140 = access %16, %idx:u32
+ %20:ptr<function, Inner, read_write> = access %17, %idx
+ %21:Inner_std140 = access %16, %idx
%22:Inner = call %convert_Inner, %21
store %20, %22
continue # -> $B5
}
$B5: { # continuing
- %24:u32 = add %idx:u32, 1u
+ %24:u32 = add %idx, 1u
next_iteration %24 # -> $B4
}
}
diff --git a/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc b/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
index b8c7703..37bdb03 100644
--- a/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
+++ b/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
@@ -54,7 +54,6 @@
/// Process the module.
void Process() {
// Find and replace matrix constructors that take scalar operands.
- Vector<Construct*, 8> worklist;
for (auto inst : ir.Instructions()) {
if (auto* construct = inst->As<Construct>()) {
if (construct->Result(0)->Type()->As<type::Matrix>()) {
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
index eeef8b2..8390ff6 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory.cc
@@ -292,11 +292,9 @@
}
// No local invocation index was found, so add one to the parameter list and use that.
- Vector<FunctionParam*, 4> params = func->Params();
auto* param = b.FunctionParam("tint_local_index", ty.u32());
+ func->AppendParam(param);
param->SetBuiltin(BuiltinValue::kLocalInvocationIndex);
- params.Push(param);
- func->SetParams(params);
return param;
}
diff --git a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
index 0e9c0b1..bf1a82b 100644
--- a/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
+++ b/src/tint/lang/core/ir/transform/zero_init_workgroup_memory_test.cc
@@ -480,18 +480,18 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 4u
+ %5:bool = gte %idx, 4u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:ptr<workgroup, i32, read_write> = access %wgvar, %idx:u32
+ %6:ptr<workgroup, i32, read_write> = access %wgvar, %idx
store %6, 0i
continue # -> $B5
}
$B5: { # continuing
- %7:u32 = add %idx:u32, 66u
+ %7:u32 = add %idx, 66u
next_iteration %7 # -> $B4
}
}
@@ -542,20 +542,20 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 35u
+ %5:bool = gte %idx, 35u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %idx:u32, 5u
- %7:u32 = div %idx:u32, 5u
+ %6:u32 = mod %idx, 5u
+ %7:u32 = div %idx, 5u
%8:ptr<workgroup, u32, read_write> = access %wgvar, %7, %6
store %8, 0u
continue # -> $B5
}
$B5: { # continuing
- %9:u32 = add %idx:u32, 66u
+ %9:u32 = add %idx, 66u
next_iteration %9 # -> $B4
}
}
@@ -606,22 +606,22 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 105u
+ %5:bool = gte %idx, 105u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %idx:u32, 7u
- %7:u32 = div %idx:u32, 7u
+ %6:u32 = mod %idx, 7u
+ %7:u32 = div %idx, 7u
%8:u32 = mod %7, 5u
- %9:u32 = div %idx:u32, 35u
+ %9:u32 = div %idx, 35u
%10:ptr<workgroup, i32, read_write> = access %wgvar, %9, %8, %6
store %10, 0i
continue # -> $B5
}
$B5: { # continuing
- %11:u32 = add %idx:u32, 1u
+ %11:u32 = add %idx, 1u
next_iteration %11 # -> $B4
}
}
@@ -672,20 +672,20 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 15u
+ %5:bool = gte %idx, 15u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %idx:u32, 5u
- %7:u32 = div %idx:u32, 5u
+ %6:u32 = mod %idx, 5u
+ %7:u32 = div %idx, 5u
%8:ptr<workgroup, i32, read_write> = access %wgvar, %7, %6, 0u
store %8, 0i
continue # -> $B5
}
$B5: { # continuing
- %9:u32 = add %idx:u32, 1u
+ %9:u32 = add %idx, 1u
next_iteration %9 # -> $B4
}
}
@@ -736,20 +736,20 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 15u
+ %5:bool = gte %idx, 15u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %idx:u32, 3u
- %7:u32 = div %idx:u32, 3u
+ %6:u32 = mod %idx, 3u
+ %7:u32 = div %idx, 3u
%8:ptr<workgroup, i32, read_write> = access %wgvar, %7, 0u, %6
store %8, 0i
continue # -> $B5
}
$B5: { # continuing
- %9:u32 = add %idx:u32, 1u
+ %9:u32 = add %idx, 1u
next_iteration %9 # -> $B4
}
}
@@ -800,20 +800,20 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 15u
+ %5:bool = gte %idx, 15u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:u32 = mod %idx:u32, 3u
- %7:u32 = div %idx:u32, 3u
+ %6:u32 = mod %idx, 3u
+ %7:u32 = div %idx, 3u
%8:ptr<workgroup, i32, read_write> = access %wgvar, 0u, %7, %6
store %8, 0i
continue # -> $B5
}
$B5: { # continuing
- %9:u32 = add %idx:u32, 1u
+ %9:u32 = add %idx, 1u
next_iteration %9 # -> $B4
}
}
@@ -1179,20 +1179,20 @@
next_iteration %tint_local_index # -> $B4
}
$B4 (%idx:u32): { # body
- %5:bool = gte %idx:u32, 7u
+ %5:bool = gte %idx, 7u
if %5 [t: $B6] { # if_1
$B6: { # true
exit_loop # loop_1
}
}
- %6:ptr<workgroup, f32, read_write> = access %wgvar, %idx:u32, 0u
+ %6:ptr<workgroup, f32, read_write> = access %wgvar, %idx, 0u
store %6, 0.0f
- %7:ptr<workgroup, bool, read_write> = access %wgvar, %idx:u32, 2u
+ %7:ptr<workgroup, bool, read_write> = access %wgvar, %idx, 2u
store %7, false
continue # -> $B5
}
$B5: { # continuing
- %8:u32 = add %idx:u32, 42u
+ %8:u32 = add %idx, 42u
next_iteration %8 # -> $B4
}
}
@@ -1201,24 +1201,24 @@
next_iteration %tint_local_index # -> $B8
}
$B8 (%idx_1:u32): { # body
- %10:bool = gte %idx_1:u32, 91u
+ %10:bool = gte %idx_1, 91u
if %10 [t: $B10] { # if_2
$B10: { # true
exit_loop # loop_2
}
}
- %11:u32 = mod %idx_1:u32, 13u
- %12:u32 = div %idx_1:u32, 13u
+ %11:u32 = mod %idx_1, 13u
+ %12:u32 = div %idx_1, 13u
%13:ptr<workgroup, i32, read_write> = access %wgvar, %12, 1u, %11, 0u
store %13, 0i
- %14:u32 = mod %idx_1:u32, 13u
- %15:u32 = div %idx_1:u32, 13u
+ %14:u32 = mod %idx_1, 13u
+ %15:u32 = div %idx_1, 13u
%16:ptr<workgroup, atomic<u32>, read_write> = access %wgvar, %15, 1u, %14, 1u
%17:void = atomicStore %16, 0u
continue # -> $B9
}
$B9: { # continuing
- %18:u32 = add %idx_1:u32, 42u
+ %18:u32 = add %idx_1, 42u
next_iteration %18 # -> $B8
}
}
@@ -1286,18 +1286,18 @@
next_iteration %tint_local_index # -> $B5
}
$B5 (%idx:u32): { # body
- %8:bool = gte %idx:u32, 4u
+ %8:bool = gte %idx, 4u
if %8 [t: $B7] { # if_2
$B7: { # true
exit_loop # loop_1
}
}
- %9:ptr<workgroup, i32, read_write> = access %var_b, %idx:u32
+ %9:ptr<workgroup, i32, read_write> = access %var_b, %idx
store %9, 0i
continue # -> $B6
}
$B6: { # continuing
- %10:u32 = add %idx:u32, 66u
+ %10:u32 = add %idx, 66u
next_iteration %10 # -> $B5
}
}
@@ -1306,20 +1306,20 @@
next_iteration %tint_local_index # -> $B9
}
$B9 (%idx_1:u32): { # body
- %12:bool = gte %idx_1:u32, 35u
+ %12:bool = gte %idx_1, 35u
if %12 [t: $B11] { # if_3
$B11: { # true
exit_loop # loop_2
}
}
- %13:u32 = mod %idx_1:u32, 5u
- %14:u32 = div %idx_1:u32, 5u
+ %13:u32 = mod %idx_1, 5u
+ %14:u32 = div %idx_1, 5u
%15:ptr<workgroup, u32, read_write> = access %var_c, %14, %13
store %15, 0u
continue # -> $B10
}
$B10: { # continuing
- %16:u32 = add %idx_1:u32, 66u
+ %16:u32 = add %idx_1, 66u
next_iteration %16 # -> $B9
}
}
@@ -1395,22 +1395,22 @@
next_iteration %tint_local_index # -> $B5
}
$B5 (%idx:u32): { # body
- %9:bool = gte %idx:u32, 42u
+ %9:bool = gte %idx, 42u
if %9 [t: $B7] { # if_2
$B7: { # true
exit_loop # loop_1
}
}
- %10:ptr<workgroup, i32, read_write> = access %var_c, %idx:u32
+ %10:ptr<workgroup, i32, read_write> = access %var_c, %idx
store %10, 0i
- %11:u32 = mod %idx:u32, 6u
- %12:u32 = div %idx:u32, 6u
+ %11:u32 = mod %idx, 6u
+ %12:u32 = div %idx, 6u
%13:ptr<workgroup, u32, read_write> = access %var_d, %12, %11
store %13, 0u
continue # -> $B6
}
$B6: { # continuing
- %14:u32 = add %idx:u32, 66u
+ %14:u32 = add %idx, 66u
next_iteration %14 # -> $B5
}
}
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index c9db3d3..e945cc6 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -32,23 +32,26 @@
#include <string>
#include <utility>
-#include "src/tint/lang/core/fluent_types.h"
#include "src/tint/lang/core/intrinsic/table.h"
#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/binary.h"
#include "src/tint/lang/core/ir/bitcast.h"
+#include "src/tint/lang/core/ir/block_param.h"
#include "src/tint/lang/core/ir/break_if.h"
+#include "src/tint/lang/core/ir/constant.h"
#include "src/tint/lang/core/ir/construct.h"
#include "src/tint/lang/core/ir/continue.h"
#include "src/tint/lang/core/ir/convert.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/exit_switch.h"
#include "src/tint/lang/core/ir/function.h"
+#include "src/tint/lang/core/ir/function_param.h"
#include "src/tint/lang/core/ir/if.h"
+#include "src/tint/lang/core/ir/instruction_result.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
#include "src/tint/lang/core/ir/load_vector_element.h"
@@ -72,16 +75,21 @@
#include "src/tint/lang/core/type/type.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
+#include "src/tint/utils/containers/hashset.h"
#include "src/tint/utils/containers/reverse.h"
#include "src/tint/utils/containers/transform.h"
+#include "src/tint/utils/ice/ice.h"
+#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/macros/scoped_assignment.h"
#include "src/tint/utils/rtti/switch.h"
+#include "src/tint/utils/text/styled_text.h"
#include "src/tint/utils/text/text_style.h"
/// If set to 1 then the Tint will dump the IR when validating.
#define TINT_DUMP_IR_WHEN_VALIDATING 0
#if TINT_DUMP_IR_WHEN_VALIDATING
#include <iostream>
+#include "src/tint/utils/text/styled_text_printer.h"
#endif
using namespace tint::core::fluent_types; // NOLINT
@@ -139,7 +147,10 @@
/// @returns success or failure
Result<SuccessType> Run();
- protected:
+ private:
+ /// @returns the IR disassembly, performing a disassemble if this is the first call.
+ ir::Disassembly& Disassembly();
+
/// Adds an error for the @p inst and highlights the instruction in the disassembly
/// @param inst the instruction
/// @returns the diagnostic
@@ -147,7 +158,7 @@
/// Adds an error for the @p inst operand at @p idx and highlights the operand in the
/// disassembly
- /// @param inst the instaruction
+ /// @param inst the instruction
/// @param idx the operand index
/// @returns the diagnostic
diag::Diagnostic& AddError(const Instruction* inst, size_t idx);
@@ -191,11 +202,15 @@
/// @param func the function
diag::Diagnostic& AddNote(const Function* func);
- /// Adds a note to @p inst for operand @p idx and highlights the operand in the
- /// disassembly
+ /// Adds a note to @p inst for operand @p idx and highlights the operand in the disassembly
/// @param inst the instruction
/// @param idx the operand index
- diag::Diagnostic& AddNote(const Instruction* inst, size_t idx);
+ diag::Diagnostic& AddOperandNote(const Instruction* inst, size_t idx);
+
+ /// Adds a note to @p inst for result @p idx and highlights the result in the disassembly
+ /// @param inst the instruction
+ /// @param idx the result index
+ diag::Diagnostic& AddResultNote(const Instruction* inst, size_t idx);
/// Adds a note to @p blk and highlights the block in the disassembly
/// @param blk the block
@@ -205,9 +220,14 @@
/// @param src the source lines to highlight
diag::Diagnostic& AddNote(Source src = {});
+ /// Adds a note to the diagnostics highlighting where the value was declared, if it has a source
+ /// location.
+ /// @param value the value
+ void AddDeclarationNote(const Value* value);
+
/// @param v the value to get the name for
/// @returns the name for the given value
- std::string Name(const Value* v);
+ StyledText NameOf(const Value* v);
/// Checks the given operand is not null
/// @param inst the instruction
@@ -231,10 +251,6 @@
/// @param func the function validate
void CheckFunction(const Function* func);
- /// Validates the given block
- /// @param blk the block to validate
- void CheckBlock(const Block* blk);
-
/// Validates the given instruction
/// @param inst the instruction to validate
void CheckInstruction(const Instruction* inst);
@@ -334,18 +350,50 @@
/// @returns the vector pointer type for the given instruction operand
const core::type::Type* GetVectorPtrElementType(const Instruction* inst, size_t idx);
- private:
+ /// Executes all the pending tasks
+ void ProcessTasks();
+
+ /// Queues the block to be validated with ProcessTasks()
+ /// @param blk the block to validate
+ void QueueBlock(const Block* blk);
+
+ /// Queues the list of instructions starting with @p inst to be validated
+ /// @param inst the first instruction
+ void QueueInstructions(const Instruction* inst);
+
+ /// Begins validation of the block @p blk, and its instructions.
+ /// BeginBlock() pushes a new scope for values.
+ /// Must be paired with a call to EndBlock().
+ void BeginBlock(const Block* blk);
+
+ /// Ends validation of the block opened with BeginBlock() and closes the block's scope for
+ /// values.
+ void EndBlock();
+
+ /// ScopeStack holds a stack of values that are currently in scope
+ struct ScopeStack {
+ void Push() { stack_.Push({}); }
+ void Pop() { stack_.Pop(); }
+ void Add(const Value* value) { stack_.Back().Add(value); }
+ bool Contains(const Value* value) {
+ return stack_.Any([&](auto& v) { return v.Contains(value); });
+ }
+ bool IsEmpty() const { return stack_.IsEmpty(); }
+
+ private:
+ Vector<Hashset<const Value*, 8>, 4> stack_;
+ };
+
const Module& mod_;
Capabilities capabilities_;
- std::shared_ptr<Source::File> disassembly_file;
+ std::optional<ir::Disassembly> disassembly_; // Use Disassembly()
diag::List diagnostics_;
- Disassembler dis_{mod_};
- const Block* current_block_ = nullptr;
Hashset<const Function*, 4> all_functions_;
Hashset<const Instruction*, 4> visited_instructions_;
Vector<const ControlInstruction*, 8> control_stack_;
-
- void DisassembleIfNeeded();
+ Vector<const Block*, 8> block_stack_;
+ ScopeStack scope_stack_;
+ Vector<std::function<void()>, 16> tasks_;
};
Validator::Validator(const Module& mod, Capabilities capabilities)
@@ -353,21 +401,30 @@
Validator::~Validator() = default;
-void Validator::DisassembleIfNeeded() {
- if (disassembly_file) {
- return;
+Disassembly& Validator::Disassembly() {
+ if (!disassembly_) {
+ disassembly_.emplace(Disassemble(mod_));
}
- disassembly_file = std::make_unique<Source::File>("", dis_.Disassemble().Plain());
+ return *disassembly_;
}
Result<SuccessType> Validator::Run() {
+ scope_stack_.Push();
+ TINT_DEFER({
+ scope_stack_.Pop();
+ TINT_ASSERT(scope_stack_.IsEmpty());
+ TINT_ASSERT(tasks_.IsEmpty());
+ TINT_ASSERT(control_stack_.IsEmpty());
+ TINT_ASSERT(block_stack_.IsEmpty());
+ });
CheckRootBlock(mod_.root_block);
for (auto& func : mod_.functions) {
if (!all_functions_.Add(func.Get())) {
- AddError(func) << "function " << style::Function(Name(func.Get()))
+ AddError(func) << "function " << NameOf(func.Get())
<< " added to module multiple times";
}
+ scope_stack_.Add(func);
}
for (auto& func : mod_.functions) {
@@ -384,116 +441,134 @@
}
if (diagnostics_.ContainsErrors()) {
- DisassembleIfNeeded();
- diagnostics_.AddNote(tint::diag::System::IR, Source{}) << "# Disassembly\n"
- << disassembly_file->content.data;
+ diagnostics_.AddNote(Source{}) << "# Disassembly\n" << Disassembly().Text();
return Failure{std::move(diagnostics_)};
}
return Success;
}
diag::Diagnostic& Validator::AddError(const Instruction* inst) {
- DisassembleIfNeeded();
- auto src = dis_.InstructionSource(inst);
+ auto src = Disassembly().InstructionSource(inst);
auto& diag = AddError(src) << inst->FriendlyName() << ": ";
- if (current_block_) {
- AddNote(current_block_) << "In block";
+ if (!block_stack_.IsEmpty()) {
+ AddNote(block_stack_.Back()) << "in block";
}
return diag;
}
diag::Diagnostic& Validator::AddError(const Instruction* inst, size_t idx) {
- DisassembleIfNeeded();
- auto src = dis_.OperandSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
+ auto src =
+ Disassembly().OperandSource(Disassembly::IndexedValue{inst, static_cast<uint32_t>(idx)});
auto& diag = AddError(src) << inst->FriendlyName() << ": ";
- if (current_block_) {
- AddNote(current_block_) << "In block";
+ if (!block_stack_.IsEmpty()) {
+ AddNote(block_stack_.Back()) << "in block";
}
-
return diag;
}
diag::Diagnostic& Validator::AddResultError(const Instruction* inst, size_t idx) {
- DisassembleIfNeeded();
- auto src = dis_.ResultSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
+ auto src =
+ Disassembly().ResultSource(Disassembly::IndexedValue{inst, static_cast<uint32_t>(idx)});
auto& diag = AddError(src) << inst->FriendlyName() << ": ";
- if (current_block_) {
- AddNote(current_block_) << "In block";
+ if (!block_stack_.IsEmpty()) {
+ AddNote(block_stack_.Back()) << "in block";
}
return diag;
}
diag::Diagnostic& Validator::AddError(const Block* blk) {
- DisassembleIfNeeded();
- auto src = dis_.BlockSource(blk);
+ auto src = Disassembly().BlockSource(blk);
return AddError(src);
}
diag::Diagnostic& Validator::AddError(const BlockParam* param) {
- DisassembleIfNeeded();
- auto src = dis_.BlockParamSource(param);
+ auto src = Disassembly().BlockParamSource(param);
return AddError(src);
}
diag::Diagnostic& Validator::AddError(const Function* func) {
- DisassembleIfNeeded();
- auto src = dis_.FunctionSource(func);
+ auto src = Disassembly().FunctionSource(func);
return AddError(src);
}
diag::Diagnostic& Validator::AddError(const FunctionParam* param) {
- DisassembleIfNeeded();
- auto src = dis_.FunctionParamSource(param);
+ auto src = Disassembly().FunctionParamSource(param);
return AddError(src);
}
diag::Diagnostic& Validator::AddNote(const Instruction* inst) {
- DisassembleIfNeeded();
- auto src = dis_.InstructionSource(inst);
+ auto src = Disassembly().InstructionSource(inst);
return AddNote(src);
}
diag::Diagnostic& Validator::AddNote(const Function* func) {
- DisassembleIfNeeded();
- auto src = dis_.FunctionSource(func);
+ auto src = Disassembly().FunctionSource(func);
return AddNote(src);
}
-diag::Diagnostic& Validator::AddNote(const Instruction* inst, size_t idx) {
- DisassembleIfNeeded();
- auto src = dis_.OperandSource(Disassembler::IndexedValue{inst, static_cast<uint32_t>(idx)});
+diag::Diagnostic& Validator::AddOperandNote(const Instruction* inst, size_t idx) {
+ auto src =
+ Disassembly().OperandSource(Disassembly::IndexedValue{inst, static_cast<uint32_t>(idx)});
+ return AddNote(src);
+}
+
+diag::Diagnostic& Validator::AddResultNote(const Instruction* inst, size_t idx) {
+ auto src =
+ Disassembly().ResultSource(Disassembly::IndexedValue{inst, static_cast<uint32_t>(idx)});
return AddNote(src);
}
diag::Diagnostic& Validator::AddNote(const Block* blk) {
- DisassembleIfNeeded();
- auto src = dis_.BlockSource(blk);
+ auto src = Disassembly().BlockSource(blk);
return AddNote(src);
}
diag::Diagnostic& Validator::AddError(Source src) {
- auto& diag = diagnostics_.AddError(tint::diag::System::IR, src);
- if (src.range != Source::Range{{}}) {
- diag.source.file = disassembly_file.get();
- diag.owned_file = disassembly_file;
- }
+ auto& diag = diagnostics_.AddError(src);
+ diag.owned_file = Disassembly().File();
return diag;
}
diag::Diagnostic& Validator::AddNote(Source src) {
- auto& diag = diagnostics_.AddNote(tint::diag::System::IR, src);
- if (src.range != Source::Range{{}}) {
- diag.source.file = disassembly_file.get();
- diag.owned_file = disassembly_file;
- }
+ auto& diag = diagnostics_.AddNote(src);
+ diag.owned_file = Disassembly().File();
return diag;
}
-std::string Validator::Name(const Value* v) {
- return mod_.NameOf(v).Name();
+void Validator::AddDeclarationNote(const Value* value) {
+ tint::Switch(
+ value, //
+ [&](const InstructionResult* res) {
+ if (auto* inst = res->Instruction()) {
+ auto results = inst->Results();
+ for (size_t i = 0; i < results.Length(); i++) {
+ if (results[i] == value) {
+ AddResultNote(res->Instruction(), i) << NameOf(value) << " declared here";
+ return;
+ }
+ }
+ }
+ },
+ [&](const FunctionParam* param) {
+ auto src = Disassembly().FunctionParamSource(param);
+ if (src.file) {
+ AddNote(src) << NameOf(value) << " declared here";
+ }
+ },
+ [&](const BlockParam* param) {
+ auto src = Disassembly().BlockParamSource(param);
+ if (src.file) {
+ AddNote(src) << NameOf(value) << " declared here";
+ }
+ },
+ [&](const Function* fn) { AddNote(fn) << NameOf(value) << " declared here"; });
+}
+
+StyledText Validator::NameOf(const Value* value) {
+ return Disassembly().NameOf(value);
}
void Validator::CheckOperandNotNull(const Instruction* inst, const ir::Value* operand, size_t idx) {
@@ -512,7 +587,8 @@
}
void Validator::CheckRootBlock(const Block* blk) {
- TINT_SCOPED_ASSIGNMENT(current_block_, blk);
+ block_stack_.Push(blk);
+ TINT_DEFER(block_stack_.Pop());
for (auto* inst : *blk) {
if (inst->Block() != blk) {
@@ -529,7 +605,9 @@
}
void Validator::CheckFunction(const Function* func) {
- CheckBlock(func->Block());
+ // Scope holds the parameters and block
+ scope_stack_.Push();
+ TINT_DEFER(scope_stack_.Pop());
for (auto* param : func->Params()) {
if (!param->Alive()) {
@@ -549,14 +627,31 @@
if (HoldsType<type::Reference>(param->Type())) {
AddError(param) << "references are not permitted as parameter types";
}
+
+ scope_stack_.Add(param);
}
if (HoldsType<type::Reference>(func->ReturnType())) {
AddError(func) << "references are not permitted as return types";
}
+
+ QueueBlock(func->Block());
+ ProcessTasks();
}
-void Validator::CheckBlock(const Block* blk) {
- TINT_SCOPED_ASSIGNMENT(current_block_, blk);
+void Validator::ProcessTasks() {
+ while (!tasks_.IsEmpty()) {
+ tasks_.Pop()();
+ }
+}
+
+void Validator::QueueBlock(const Block* blk) {
+ tasks_.Push([this] { EndBlock(); });
+ tasks_.Push([this, blk] { BeginBlock(blk); });
+}
+
+void Validator::BeginBlock(const Block* blk) {
+ scope_stack_.Push();
+ block_stack_.Push(blk);
if (auto* mb = blk->As<MultiInBlock>()) {
for (auto* param : mb->Params()) {
@@ -572,26 +667,45 @@
AddNote(param->Block()) << "parent block declared here";
return;
}
+ scope_stack_.Add(param);
}
}
if (!blk->Terminator()) {
- AddError(blk) << "block: does not end in a terminator instruction";
+ AddError(blk) << "block does not end in a terminator instruction";
}
+ // Validate the instructions w.r.t. the parent block
for (auto* inst : *blk) {
if (inst->Block() != blk) {
AddError(inst) << "block instruction does not have same block as parent";
- AddNote(current_block_) << "In block";
+ AddNote(blk) << "in block";
continue;
}
if (inst->Is<ir::Terminator>() && inst != blk->Terminator()) {
- AddError(inst) << "block: terminator which isn't the final instruction";
+ AddError(inst) << "block terminator which isn't the final instruction";
continue;
}
-
- CheckInstruction(inst);
}
+
+ // Enqueue validation of the instructions of the block
+ if (!blk->IsEmpty()) {
+ QueueInstructions(blk->Instructions());
+ }
+}
+
+void Validator::EndBlock() {
+ scope_stack_.Pop();
+ block_stack_.Pop();
+}
+
+void Validator::QueueInstructions(const Instruction* inst) {
+ tasks_.Push([this, inst] {
+ CheckInstruction(inst);
+ if (inst->next) {
+ QueueInstructions(inst->next);
+ }
+ });
}
void Validator::CheckInstruction(const Instruction* inst) {
@@ -632,10 +746,13 @@
// for `nullptr` here.
if (!op->Alive()) {
AddError(inst, i) << "operand is not alive";
- }
-
- if (!op->HasUsage(inst, i)) {
+ } else if (!op->HasUsage(inst, i)) {
AddError(inst, i) << "operand missing usage";
+ } else if (auto fn = op->As<Function>(); fn && !all_functions_.Contains(fn)) {
+ AddError(inst, i) << NameOf(op) << " is not part of the module";
+ } else if (!op->Is<Constant>() && !scope_stack_.Contains(op)) {
+ AddError(inst, i) << NameOf(op) << " is not in scope";
+ AddDeclarationNote(op);
}
if (!capabilities_.Contains(Capability::kAllowRefTypes)) {
@@ -663,6 +780,10 @@
[&](const Unary* u) { CheckUnary(u); }, //
[&](const Var* var) { CheckVar(var); }, //
[&](const Default) { AddError(inst) << "missing validation"; });
+
+ for (auto* result : results) {
+ scope_stack_.Add(result);
+ }
}
void Validator::CheckVar(const Var* var) {
@@ -721,10 +842,6 @@
}
void Validator::CheckUserCall(const UserCall* call) {
- if (!all_functions_.Contains(call->Target())) {
- AddError(call, UserCall::kFunctionOperandOffset) << "call target is not part of the module";
- }
-
if (call->Target()->Stage() != Function::PipelineStage::kUndefined) {
AddError(call, UserCall::kFunctionOperandOffset)
<< "call target must not have a pipeline stage";
@@ -778,7 +895,7 @@
return AddError(a, i + Access::kIndicesOperandOffset);
};
auto note = [&]() -> diag::Diagnostic& {
- return AddNote(a, i + Access::kIndicesOperandOffset);
+ return AddOperandNote(a, i + Access::kIndicesOperandOffset);
};
auto* index = a->Indices()[i];
@@ -912,36 +1029,50 @@
AddError(if_, If::kConditionOperandOffset) << "condition must be a `bool` type";
}
- control_stack_.Push(if_);
- TINT_DEFER(control_stack_.Pop());
+ tasks_.Push([this] { control_stack_.Pop(); });
- CheckBlock(if_->True());
if (!if_->False()->IsEmpty()) {
- CheckBlock(if_->False());
+ QueueBlock(if_->False());
}
+
+ QueueBlock(if_->True());
+
+ tasks_.Push([this, if_] { control_stack_.Push(if_); });
}
void Validator::CheckLoop(const Loop* l) {
- control_stack_.Push(l);
- TINT_DEFER(control_stack_.Pop());
-
+ // Note: Tasks are queued in reverse order of their execution
+ tasks_.Push([this] { control_stack_.Pop(); });
if (!l->Initializer()->IsEmpty()) {
- CheckBlock(l->Initializer());
+ tasks_.Push([this] { EndBlock(); });
}
- CheckBlock(l->Body());
+ tasks_.Push([this] { EndBlock(); });
+ if (!l->Continuing()->IsEmpty()) {
+ tasks_.Push([this] { EndBlock(); });
+ }
+
+ // ⎡Initializer ⎤
+ // ⎢ ⎡Body ⎤⎥
+ // ⎣ ⎣ [Continuing ] ⎦⎦
if (!l->Continuing()->IsEmpty()) {
- CheckBlock(l->Continuing());
+ tasks_.Push([this, l] { BeginBlock(l->Continuing()); });
}
+ tasks_.Push([this, l] { BeginBlock(l->Body()); });
+ if (!l->Initializer()->IsEmpty()) {
+ tasks_.Push([this, l] { BeginBlock(l->Initializer()); });
+ }
+ tasks_.Push([this, l] { control_stack_.Push(l); });
}
void Validator::CheckSwitch(const Switch* s) {
- control_stack_.Push(s);
- TINT_DEFER(control_stack_.Pop());
+ tasks_.Push([this] { control_stack_.Pop(); });
for (auto& cse : s->Cases()) {
- CheckBlock(cse.block);
+ QueueBlock(cse.block);
}
+
+ tasks_.Push([this, s] { control_stack_.Push(s); });
}
void Validator::CheckTerminator(const Terminator* b) {
@@ -1169,10 +1300,11 @@
[[maybe_unused]] const char* msg,
[[maybe_unused]] Capabilities capabilities) {
#if TINT_DUMP_IR_WHEN_VALIDATING
+ auto printer = StyledTextPrinter::Create(stdout);
std::cout << "=========================================================" << std::endl;
std::cout << "== IR dump before " << msg << ":" << std::endl;
std::cout << "=========================================================" << std::endl;
- std::cout << Disassemble(ir);
+ printer->Print(Disassemble(ir).Text());
#endif
#ifndef NDEBUG
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 16bb823..864e24d 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -71,7 +71,7 @@
loop [b: $B2] { # loop_1
^^^^^^^^^^^^^
-:1:1 note: In block
+:1:1 note: in block
$B1: { # root
^^^
@@ -102,7 +102,7 @@
%1:ptr<private, i32, read_write> = var
^^^
-:1:1 note: In block
+:1:1 note: in block
$B1: { # root
^^^
@@ -139,7 +139,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:1:1 error: function 'my_func' added to module multiple times
+ R"(:1:1 error: function %my_func added to module multiple times
%my_func = func(%2:i32, %3:f32):void {
^^^^^^^^
@@ -253,11 +253,11 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:20 error: call: call target is not part of the module
+ R"(:3:20 error: call: %g is not part of the module
%2:void = call %g
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -288,7 +288,7 @@
%2:void = call %g
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -325,7 +325,7 @@
%5:void = call %g, 42i
^^
-:7:3 note: In block
+:7:3 note: in block
$B2: {
^^^
@@ -362,7 +362,7 @@
%5:void = call %g, 1i, 2i, 3i
^^
-:7:3 note: In block
+:7:3 note: in block
$B2: {
^^^
@@ -399,7 +399,7 @@
%6:void = call %g, 1i, 2.0f, 3i
^^^^
-:7:3 note: In block
+:7:3 note: in block
$B2: {
^^^
@@ -424,7 +424,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:2:3 error: block: does not end in a terminator instruction
+ R"(:2:3 error: block does not end in a terminator instruction
$B1: {
^^^
@@ -455,11 +455,11 @@
%2:ptr<function, i32, read_write> = var
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -496,7 +496,7 @@
EXPECT_EQ(res.Failure().reason.Str(),
R"(:4:12 error: destroyed parameter found in block parameter list
$B2 (%my_param:f32): { # body
- ^^^^^^^^^^^^^
+ ^^^^^^^^^
note: # Disassembly
%my_func = func():void {
@@ -530,7 +530,7 @@
EXPECT_EQ(res.Failure().reason.Str(),
R"(:4:12 error: block parameter has nullptr parent block
$B2 (%my_param:f32): { # body
- ^^^^^^^^^^^^^
+ ^^^^^^^^^
note: # Disassembly
%my_func = func():void {
@@ -564,7 +564,7 @@
EXPECT_EQ(res.Failure().reason.Str(),
R"(:4:12 error: block parameter has incorrect parent block
$B2 (%my_param:f32): { # body
- ^^^^^^^^^^^^^
+ ^^^^^^^^^
:7:7 note: parent block declared here
$B3 (%my_param:f32): { # continuing
@@ -575,10 +575,10 @@
$B1: {
loop [b: $B2, c: $B3] { # loop_1
$B2 (%my_param:f32): { # body
- continue %my_param:f32 # -> $B3
+ continue %my_param # -> $B3
}
$B3 (%my_param:f32): { # continuing
- next_iteration %my_param:f32 # -> $B2
+ next_iteration %my_param # -> $B2
}
}
ret
@@ -604,7 +604,7 @@
%3:f32 = access %2, -1i
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -635,7 +635,7 @@
%3:f32 = access %2, 1u, 3u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -671,7 +671,7 @@
%3:ptr<private, f32, read_write> = access %2, 1u, 3u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -705,7 +705,7 @@
%3:f32 = access %2, 1u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -736,7 +736,7 @@
%3:ptr<private, f32, read_write> = access %2, 1u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -773,7 +773,7 @@
%4:i32 = access %2, %3
^^
-:7:3 note: In block
+:7:3 note: in block
$B1: {
^^^
@@ -816,7 +816,7 @@
%4:i32 = access %2, %3
^^
-:7:3 note: In block
+:7:3 note: in block
$B1: {
^^^
@@ -852,7 +852,7 @@
%3:i32 = access %2, 1u, 1u
^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -884,7 +884,7 @@
%3:ptr<private, i32, read_write> = access %2, 1u, 1u
^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -916,7 +916,7 @@
%3:f32 = access %2, 1u, 1u
^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -947,7 +947,7 @@
%3:f32 = access %2, 1u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -992,7 +992,7 @@
%3:f32 = access %2, 1u, 1u
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1038,7 +1038,7 @@
%3:ptr<uniform, f32, read> = access %2, 1u
^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1070,7 +1070,7 @@
%3:ptr<storage, f32, read_write> = access %2, 1u
^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1123,11 +1123,11 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:3:5 error: return: block: terminator which isn't the final instruction
+ R"(:3:5 error: return: block terminator which isn't the final instruction
ret
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1165,7 +1165,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:7 error: block: does not end in a terminator instruction
+ R"(:4:7 error: block does not end in a terminator instruction
$B2: { # true
^^^
@@ -1201,7 +1201,7 @@
if 1i [t: $B2, f: $B3] { # if_1
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1238,7 +1238,7 @@
if undef [t: $B2, f: $B3] { # if_1
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1277,7 +1277,7 @@
undef = if true [t: $B2, f: $B3] { # if_1
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1321,7 +1321,7 @@
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(),
- R"(:4:7 error: block: does not end in a terminator instruction
+ R"(:4:7 error: block does not end in a terminator instruction
$B2: { # body
^^^
@@ -1348,7 +1348,7 @@
undef = var
^^^^^
-:1:1 note: In block
+:1:1 note: in block
$B1: { # root
^^^
@@ -1375,7 +1375,7 @@
undef = var
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1392,27 +1392,26 @@
TEST_F(IR_ValidatorTest, Var_Init_WrongType) {
auto* f = b.Function("my_func", ty.void_());
- auto sb = b.Append(f->Block());
- auto* v = sb.Var(ty.ptr<function, f32>());
- sb.Return(f);
-
- auto* result = sb.InstructionResult(ty.i32());
- v->SetInitializer(result);
+ b.Append(f->Block(), [&] {
+ auto* v = b.Var<function, f32>();
+ v->SetInitializer(b.Constant(1_i));
+ b.Return(f);
+ });
auto res = ir::Validate(mod);
ASSERT_NE(res, Success);
EXPECT_EQ(res.Failure().reason.Str(), R"(:3:41 error: var: initializer has incorrect type
- %2:ptr<function, f32, read_write> = var, %3
+ %2:ptr<function, f32, read_write> = var, 1i
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
note: # Disassembly
%my_func = func():void {
$B1: {
- %2:ptr<function, f32, read_write> = var, %3
+ %2:ptr<function, f32, read_write> = var, 1i
ret
}
}
@@ -1434,7 +1433,7 @@
undef = let 1i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1463,7 +1462,7 @@
%2:f32 = let undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1493,7 +1492,7 @@
%2:f32 = let 1i
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1524,7 +1523,7 @@
<destroyed tint::core::ir::Var $ADDRESS>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^$ARROWS^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1561,7 +1560,7 @@
%2:ptr<function, f32, read_write> = var
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1592,7 +1591,7 @@
%2:ptr<function, f32, read_write> = var, %3
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1623,7 +1622,7 @@
%2:ptr<function, f32, read_write> = var, %3
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1673,7 +1672,7 @@
%2:i32 = add undef, 2i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1700,7 +1699,7 @@
%2:i32 = add 2i, undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1730,7 +1729,7 @@
undef = add 3i, 2i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1757,7 +1756,7 @@
%2:i32 = negation undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1787,7 +1786,7 @@
undef = negation 2i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1818,7 +1817,7 @@
%2:f32 = complement 2i
^^^^^^^^^^^^^^^^^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -1859,7 +1858,7 @@
exit_if # undef
^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # true
^^^
@@ -1898,7 +1897,7 @@
exit_if 1i # if_1
^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # true
^^^
@@ -1942,7 +1941,7 @@
exit_if 1i, 2.0f, 3i # if_1
^^^^^^^^^^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # true
^^^
@@ -2003,7 +2002,7 @@
exit_if 1i, 2i # if_1
^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # true
^^^
@@ -2043,7 +2042,7 @@
exit_if # if_1
^^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -2086,7 +2085,7 @@
exit_if # if_1
^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B3: { # true
^^^
@@ -2139,7 +2138,7 @@
exit_if # if_1
^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B3: { # case
^^^
@@ -2191,7 +2190,7 @@
exit_if # if_1
^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B3: { # body
^^^
@@ -2250,7 +2249,7 @@
exit_switch # undef
^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # case
^^^
@@ -2291,7 +2290,7 @@
exit_switch 1i # switch_1
^^^^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # case
^^^
@@ -2335,7 +2334,7 @@
exit_switch 1i, 2.0f, 3i # switch_1
^^^^^^^^^^^^^^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # case
^^^
@@ -2397,7 +2396,7 @@
exit_switch 1i, 2i # switch_1
^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # case
^^^
@@ -2441,7 +2440,7 @@
exit_switch # switch_1
^^^^^^^^^^^
-:9:7 note: In block
+:9:7 note: in block
$B3: { # true
^^^
@@ -2522,7 +2521,7 @@
exit_switch # switch_1
^^^^^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B3: { # case
^^^
@@ -2573,7 +2572,7 @@
exit_switch # switch_1
^^^^^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B3: { # body
^^^
@@ -2630,7 +2629,7 @@
exit_loop # undef
^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # body
^^^
@@ -2673,7 +2672,7 @@
exit_loop 1i # loop_1
^^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # body
^^^
@@ -2720,7 +2719,7 @@
exit_loop 1i, 2.0f, 3i # loop_1
^^^^^^^^^^^^^^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # body
^^^
@@ -2785,7 +2784,7 @@
exit_loop 1i, 2i # loop_1
^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # body
^^^
@@ -2831,7 +2830,7 @@
exit_loop # loop_1
^^^^^^^^^
-:12:7 note: In block
+:12:7 note: in block
$B4: { # true
^^^
@@ -2914,7 +2913,7 @@
exit_loop # loop_1
^^^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B4: { # case
^^^
@@ -2969,7 +2968,7 @@
exit_loop # loop_1
^^^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B4: { # body
^^^
@@ -3019,7 +3018,7 @@
exit_loop # loop_1
^^^^^^^^^
-:7:7 note: In block
+:7:7 note: in block
$B3: { # continuing
^^^
@@ -3065,7 +3064,7 @@
exit_loop # loop_1
^^^^^^^^^
-:9:11 note: In block
+:9:11 note: in block
$B4: { # true
^^^
@@ -3117,7 +3116,7 @@
exit_loop # loop_1
^^^^^^^^^
-:4:7 note: In block
+:4:7 note: in block
$B2: { # initializer
^^^
@@ -3167,7 +3166,7 @@
exit_loop # loop_1
^^^^^^^^^
-:6:11 note: In block
+:6:11 note: in block
$B5: { # true
^^^
@@ -3230,7 +3229,7 @@
ret
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3255,7 +3254,7 @@
ret 42i
^^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3280,7 +3279,7 @@
ret
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3306,7 +3305,7 @@
ret 42.0f
^^^^^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3334,7 +3333,7 @@
%2:i32 = load undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3365,7 +3364,7 @@
%3:f32 = load %l
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3397,7 +3396,7 @@
%3:f32 = load %2
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3426,7 +3425,7 @@
store undef, 42i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3455,7 +3454,7 @@
store %2, undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3486,7 +3485,7 @@
store %l, 42u
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3517,7 +3516,7 @@
store %2, 42u
^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3549,7 +3548,7 @@
undef = load_vector_element %2, 1i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3579,7 +3578,7 @@
%2:f32 = load_vector_element undef, 1i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3609,7 +3608,7 @@
%3:f32 = load_vector_element %2, undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3639,7 +3638,7 @@
store_vector_element undef, 1i, 2i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3669,7 +3668,7 @@
store_vector_element %2, undef, 2i
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3677,7 +3676,7 @@
store_vector_element %2, undef, 2i
^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3708,7 +3707,7 @@
store_vector_element %2, 1i, undef
^^^^^
-:2:3 note: In block
+:2:3 note: in block
$B1: {
^^^
@@ -3723,6 +3722,42 @@
)");
}
+TEST_F(IR_ValidatorTest, Scoping_UseBeforeDecl) {
+ auto* f = b.Function("my_func", ty.void_());
+
+ auto* y = b.Add<i32>(2_i, 3_i);
+ auto* x = b.Add<i32>(y, 1_i);
+
+ f->Block()->Append(x);
+ f->Block()->Append(y);
+ f->Block()->Append(b.Return(f));
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:3:18 error: binary: %3 is not in scope
+ %2:i32 = add %3, 1i
+ ^^
+
+:2:3 note: in block
+ $B1: {
+ ^^^
+
+:4:5 note: %3 declared here
+ %3:i32 = add 2i, 3i
+ ^^^^^^
+
+note: # Disassembly
+%my_func = func():void {
+ $B1: {
+ %2:i32 = add %3, 1i
+ %3:i32 = add 2i, 3i
+ ret
+ }
+}
+)");
+}
+
template <typename T>
static const type::Type* TypeBuilder(type::Manager& m) {
return m.Get<T>();
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 067f38c..92b6cad 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -397,7 +397,7 @@
auto* dst_type = TypeOf(call);
if (!dst_type->is_integer_scalar_or_vector() && !dst_type->is_float_scalar_or_vector()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "Unable to do bitcast to type " << dst_type->FriendlyName();
return;
}
@@ -1744,8 +1744,7 @@
case wgsl::BuiltinFn::kUnpack4X8Unorm:
return "unpackUnorm4x8";
default:
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "Unknown builtin method: " << builtin;
+ diagnostics_.AddError(Source{}) << "Unknown builtin method: " << builtin;
}
return "";
@@ -1923,7 +1922,7 @@
[&](const ast::Let* let) { EmitProgramConstVariable(let); },
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "override-expressions should have been removed with the "
"SubstituteOverride transform";
},
@@ -2192,7 +2191,7 @@
out << "local_size_" << (i == 0 ? "x" : i == 1 ? "y" : "z") << " = ";
if (!wgsize[i].has_value()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "override-expressions should have been removed with the SubstituteOverride "
"transform";
return;
@@ -2295,8 +2294,7 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return;
}
@@ -2347,8 +2345,7 @@
return;
}
}
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown integer literal suffix type";
+ diagnostics_.AddError(Source{}) << "unknown integer literal suffix type";
}, //
TINT_ICE_ON_NO_MATCH);
}
@@ -2400,8 +2397,7 @@
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return;
}
@@ -2412,7 +2408,7 @@
EmitZeroValue(out, arr->ElemType());
}
} else {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "Invalid type for zero emission: " << type->FriendlyName();
}
}
@@ -2688,8 +2684,7 @@
} else {
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return;
}
sizes.push_back(count.value());
@@ -2844,7 +2839,7 @@
} else if (type->Is<core::type::Void>()) {
out << "void";
} else {
- diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown type in EmitType";
+ diagnostics_.AddError(Source{}) << "unknown type in EmitType";
}
}
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
index 4c8c40c..125afe8 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer_test.cc
@@ -35,7 +35,7 @@
using GlslASTPrinterTest = TestHelper;
TEST_F(GlslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
+ Diagnostics().AddError(Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
index 9b09f57..fcaef5e 100644
--- a/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/combine_samplers.cc
@@ -441,8 +441,7 @@
auto* binding_info = inputs.Get<BindingInfo>();
if (!binding_info) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
index 89cebe1..d0e8c71 100644
--- a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
@@ -74,7 +74,7 @@
ApplyResult Run() {
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "missing transform data for "
<< tint::TypeInfo::Of<TextureBuiltinsFromUniform>().name;
return resolver::Resolve(b);
diff --git a/src/tint/lang/hlsl/validate/BUILD.bazel b/src/tint/lang/hlsl/validate/BUILD.bazel
index 512dfd0..41ec67c 100644
--- a/src/tint/lang/hlsl/validate/BUILD.bazel
+++ b/src/tint/lang/hlsl/validate/BUILD.bazel
@@ -56,7 +56,13 @@
"//src/tint/utils/rtti",
"//src/tint/utils/text",
"//src/tint/utils/traits",
- ],
+ ] + select({
+ ":tint_build_hlsl_writer": [
+
+
+ ],
+ "//conditions:default": [],
+ }),
copts = COPTS,
visibility = ["//visibility:public"],
)
diff --git a/src/tint/lang/hlsl/validate/BUILD.cmake b/src/tint/lang/hlsl/validate/BUILD.cmake
index a16018e..272eae6 100644
--- a/src/tint/lang/hlsl/validate/BUILD.cmake
+++ b/src/tint/lang/hlsl/validate/BUILD.cmake
@@ -59,4 +59,11 @@
tint_utils_traits
)
+if(TINT_BUILD_HLSL_WRITER)
+ tint_target_add_external_dependencies(tint_lang_hlsl_validate lib
+ "dl"
+ "dxc-include"
+ )
+endif(TINT_BUILD_HLSL_WRITER)
+
endif(TINT_BUILD_HLSL_WRITER)
\ No newline at end of file
diff --git a/src/tint/lang/hlsl/validate/BUILD.gn b/src/tint/lang/hlsl/validate/BUILD.gn
index 44d66c5..b22d7b8 100644
--- a/src/tint/lang/hlsl/validate/BUILD.gn
+++ b/src/tint/lang/hlsl/validate/BUILD.gn
@@ -56,5 +56,12 @@
"${tint_src_dir}/utils/text",
"${tint_src_dir}/utils/traits",
]
+
+ if (tint_build_hlsl_writer) {
+ deps += [
+ "${tint_src_dir}:dl",
+ "${tint_src_dir}:dxc-include",
+ ]
+ }
}
}
diff --git a/src/tint/lang/hlsl/validate/validate.cc b/src/tint/lang/hlsl/validate/validate.cc
index cfca843..027756f 100644
--- a/src/tint/lang/hlsl/validate/validate.cc
+++ b/src/tint/lang/hlsl/validate/validate.cc
@@ -31,17 +31,32 @@
#include "src/tint/utils/command/command.h"
#include "src/tint/utils/file/tmpfile.h"
+#include "src/tint/utils/macros/defer.h"
#include "src/tint/utils/text/string.h"
#ifdef _WIN32
#include <Windows.h>
+#include <atlbase.h>
#include <d3dcommon.h>
#include <d3dcompiler.h>
-
#include <wrl.h>
-using Microsoft::WRL::ComPtr;
+#else
+#include <dlfcn.h>
#endif // _WIN32
+// dxc headers
+TINT_BEGIN_DISABLE_ALL_WARNINGS();
+#ifdef __clang__
+// # Use UUID emulation with clang to avoid compiling with ms-extensions
+#define __EMULATE_UUID
+#endif
+#include "dxc/dxcapi.h"
+TINT_END_DISABLE_ALL_WARNINGS();
+
+// Disable warnings about old-style casts which result from using
+// the SUCCEEDED and FAILED macros that C-style cast to HRESULT.
+TINT_DISABLE_WARNING_OLD_STYLE_CAST
+
namespace tint::hlsl::validate {
Result ValidateUsingDXC(const std::string& dxc_path,
@@ -51,9 +66,8 @@
uint32_t hlsl_shader_model) {
Result result;
- auto dxc = tint::Command(dxc_path);
- if (!dxc.Found()) {
- result.output = "DXC not found at '" + std::string(dxc_path) + "'";
+ if (entry_points.empty()) {
+ result.output = "No entrypoint found";
result.failed = true;
return result;
}
@@ -70,64 +84,140 @@
result.failed = true;
return result;
}
- std::string shader_model_version =
- std::to_string(hlsl_shader_model / 10) + "_" + std::to_string(hlsl_shader_model % 10);
- tint::TmpFile file;
- file << source;
+#define CHECK_HR(hr, error_msg) \
+ do { \
+ if (FAILED(hr)) { \
+ result.output = error_msg; \
+ result.failed = true; \
+ return result; \
+ } \
+ } while (false)
+
+ HRESULT hr;
+
+ // Load the dll and get the DxcCreateInstance function
+ using PFN_DXC_CREATE_INSTANCE =
+ HRESULT(__stdcall*)(REFCLSID rclsid, REFIID riid, LPVOID * ppCompiler);
+ PFN_DXC_CREATE_INSTANCE dxc_create_instance = nullptr;
+#ifdef _WIN32
+ HMODULE dxcLib = LoadLibraryA(dxc_path.c_str());
+ if (dxcLib == nullptr) {
+ result.output = "Failed to load dxc: " + dxc_path;
+ result.failed = true;
+ return result;
+ }
+ // Avoid ASAN false positives when unloading DLL: https://github.com/google/sanitizers/issues/89
+#if !defined(TINT_ASAN_ENABLED)
+ TINT_DEFER({ FreeLibrary(dxcLib); });
+#endif
+
+ dxc_create_instance =
+ reinterpret_cast<PFN_DXC_CREATE_INSTANCE>(GetProcAddress(dxcLib, "DxcCreateInstance"));
+#else
+ void* dxcLib = dlopen(dxc_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
+ if (dxcLib == nullptr) {
+ result.output = "Failed to load dxc: " + dxc_path;
+ result.failed = true;
+ return result;
+ }
+ // Avoid ASAN false positives when unloading DLL: https://github.com/google/sanitizers/issues/89
+#if !defined(TINT_ASAN_ENABLED)
+ TINT_DEFER({ dlclose(dxcLib); });
+#endif
+
+ dxc_create_instance =
+ reinterpret_cast<PFN_DXC_CREATE_INSTANCE>(dlsym(dxcLib, "DxcCreateInstance"));
+#endif
+ if (dxc_create_instance == nullptr) {
+ result.output = "GetProcAccess failed";
+ result.failed = true;
+ return result;
+ }
+
+ CComPtr<IDxcCompiler3> dxc_compiler;
+ hr = dxc_create_instance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxc_compiler));
+ CHECK_HR(hr, "DxcCreateInstance failed");
for (auto ep : entry_points) {
- const char* stage_prefix = "";
-
+ const wchar_t* stage_prefix = L"";
switch (ep.second) {
case ast::PipelineStage::kNone:
result.output = "Invalid PipelineStage";
result.failed = true;
return result;
case ast::PipelineStage::kVertex:
- stage_prefix = "vs";
+ stage_prefix = L"vs";
break;
case ast::PipelineStage::kFragment:
- stage_prefix = "ps";
+ stage_prefix = L"ps";
break;
case ast::PipelineStage::kCompute:
- stage_prefix = "cs";
+ stage_prefix = L"cs";
break;
}
// Match Dawn's compile flags
// See dawn\src\dawn_native\d3d12\RenderPipelineD3D12.cpp
// and dawn_native\d3d\ShaderUtils.cpp (GetDXCArguments)
- auto res =
- dxc("-T " + std::string(stage_prefix) + "_" + shader_model_version, // Profile
- "-HV 2018", // Use HLSL 2018
- "-E " + ep.first, // Entry point
- "/Zpr", // D3DCOMPILE_PACK_MATRIX_ROW_MAJOR
- "/Gis", // D3DCOMPILE_IEEE_STRICTNESS
- require_16bit_types ? "-enable-16bit-types" : "", // Enable 16-bit if required
- file.Path());
- if (!res.out.empty()) {
- if (!result.output.empty()) {
- result.output += "\n";
- }
- result.output += res.out;
- }
- if (!res.err.empty()) {
- if (!result.output.empty()) {
- result.output += "\n";
- }
- result.output += res.err;
- }
- result.failed = (res.error_code != 0);
+ std::wstring shader_model_version = std::to_wstring(hlsl_shader_model / 10) + L"_" +
+ std::to_wstring(hlsl_shader_model % 10);
+ std::wstring profile = std::wstring(stage_prefix) + L"_" + shader_model_version;
+ std::wstring entry_point = std::wstring(ep.first.begin(), ep.first.end());
+ std::vector<const wchar_t*> args{
+ L"-T", // Profile
+ profile.c_str(), //
+ L"-HV 2018", // Use HLSL 2018
+ L"-E", // Entry point
+ entry_point.c_str(), //
+ L"/Zpr", // D3DCOMPILE_PACK_MATRIX_ROW_MAJOR
+ L"/Gis", // D3DCOMPILE_IEEE_STRICTNESS
+ require_16bit_types ? L"-enable-16bit-types" : L"" // Enable 16-bit if required
+ };
- // Remove the temporary file name from the output to keep output deterministic
- result.output = tint::ReplaceAll(result.output, file.Path(), "shader.hlsl");
- }
+ DxcBuffer source_buffer;
+ source_buffer.Ptr = source.c_str();
+ source_buffer.Size = source.length();
+ source_buffer.Encoding = DXC_CP_UTF8;
+ CComPtr<IDxcResult> compile_result;
+ hr = dxc_compiler->Compile(&source_buffer, args.data(), static_cast<UINT32>(args.size()),
+ nullptr, IID_PPV_ARGS(&compile_result));
+ CHECK_HR(hr, "Compile call failed");
- if (entry_points.empty()) {
- result.output = "No entrypoint found";
- result.failed = true;
- return result;
+ HRESULT compile_status;
+ hr = compile_result->GetStatus(&compile_status);
+ CHECK_HR(hr, "GetStatus call failed");
+
+ if (FAILED(compile_status)) {
+ CComPtr<IDxcBlobEncoding> errors;
+ hr = compile_result->GetErrorBuffer(&errors);
+ CHECK_HR(hr, "GetErrorBuffer call failed");
+ result.output = static_cast<char*>(errors->GetBufferPointer());
+ result.failed = true;
+ return result;
+ }
+
+ // Compilation succeeded, get compiled shader blob and disassamble it
+ CComPtr<IDxcBlob> compiled_shader;
+ hr = compile_result->GetResult(&compiled_shader);
+ CHECK_HR(hr, "GetResult call failed");
+
+ DxcBuffer compiled_shader_buffer;
+ compiled_shader_buffer.Ptr = compiled_shader->GetBufferPointer();
+ compiled_shader_buffer.Size = compiled_shader->GetBufferSize();
+ compiled_shader_buffer.Encoding = DXC_CP_UTF8;
+ CComPtr<IDxcResult> dis_result;
+ hr = dxc_compiler->Disassemble(&compiled_shader_buffer, IID_PPV_ARGS(&dis_result));
+ CHECK_HR(hr, "Disassemble call failed");
+
+ CComPtr<IDxcBlobEncoding> disassembly;
+ if (dis_result && dis_result->HasOutput(DXC_OUT_DISASSEMBLY) &&
+ SUCCEEDED(
+ dis_result->GetOutput(DXC_OUT_DISASSEMBLY, IID_PPV_ARGS(&disassembly), nullptr))) {
+ result.output = static_cast<char*>(disassembly->GetBufferPointer());
+ } else {
+ result.output = "Failed to disassemble shader";
+ }
}
return result;
@@ -139,6 +229,12 @@
const EntryPointList& entry_points) {
Result result;
+ if (entry_points.empty()) {
+ result.output = "No entrypoint found";
+ result.failed = true;
+ return result;
+ }
+
// This library leaks if an error happens in this function, but it is ok
// because it is loaded at most once, and the executables using UsingFXC
// are short-lived.
@@ -188,8 +284,8 @@
UINT compileFlags = D3DCOMPILE_OPTIMIZATION_LEVEL0 | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR |
D3DCOMPILE_IEEE_STRICTNESS;
- ComPtr<ID3DBlob> compiledShader;
- ComPtr<ID3DBlob> errors;
+ CComPtr<ID3DBlob> compiledShader;
+ CComPtr<ID3DBlob> errors;
HRESULT res = d3dCompile(source.c_str(), // pSrcData
source.length(), // SrcDataSize
nullptr, // pSourceName
@@ -206,11 +302,11 @@
result.failed = true;
return result;
} else {
- ComPtr<ID3DBlob> disassembly;
+ CComPtr<ID3DBlob> disassembly;
res = d3dDisassemble(compiledShader->GetBufferPointer(),
compiledShader->GetBufferSize(), 0, "", &disassembly);
if (FAILED(res)) {
- result.output = "failed to disassemble shader";
+ result.output = "Failed to disassemble shader";
} else {
result.output = static_cast<char*>(disassembly->GetBufferPointer());
}
@@ -219,12 +315,6 @@
FreeLibrary(fxcLib);
- if (entry_points.empty()) {
- result.output = "No entrypoint found";
- result.failed = true;
- return result;
- }
-
return result;
}
#endif // _WIN32
diff --git a/src/tint/lang/hlsl/validate/validate.h b/src/tint/lang/hlsl/validate/validate.h
index 8efb4fb..67ce25e 100644
--- a/src/tint/lang/hlsl/validate/validate.h
+++ b/src/tint/lang/hlsl/validate/validate.h
@@ -46,6 +46,16 @@
/// Name of the FXC compiler DLL
static constexpr const char kFxcDLLName[] = "d3dcompiler_47.dll";
+#if TINT_BUILD_IS_WIN
+static constexpr const char* kDxcDLLName = "dxcompiler.dll";
+#elif TINT_BUILD_IS_LINUX
+static constexpr const char* kDxcDLLName = "libdxcompiler.so";
+#elif TINT_BUILD_IS_MAC
+static constexpr const char* kDxcDLLName = "libdxcompiler.dylib";
+#else
+static constexpr const char* kDxcDLLName = "Invalid";
+#endif
+
/// The return structure of Validate()
struct Result {
/// True if validation passed
diff --git a/src/tint/lang/hlsl/writer/BUILD.cmake b/src/tint/lang/hlsl/writer/BUILD.cmake
index a40f368..67af1a7 100644
--- a/src/tint/lang/hlsl/writer/BUILD.cmake
+++ b/src/tint/lang/hlsl/writer/BUILD.cmake
@@ -159,6 +159,7 @@
tint_lang_wgsl_program
tint_lang_wgsl_sem
tint_utils_bytes
+ tint_utils_command
tint_utils_containers
tint_utils_diagnostic
tint_utils_ice
@@ -176,6 +177,7 @@
if(TINT_BUILD_HLSL_WRITER)
tint_target_add_dependencies(tint_lang_hlsl_writer_fuzz fuzz
+ tint_lang_hlsl_validate
tint_lang_hlsl_writer
)
endif(TINT_BUILD_HLSL_WRITER)
diff --git a/src/tint/lang/hlsl/writer/BUILD.gn b/src/tint/lang/hlsl/writer/BUILD.gn
index 4c8f704..2111f1c 100644
--- a/src/tint/lang/hlsl/writer/BUILD.gn
+++ b/src/tint/lang/hlsl/writer/BUILD.gn
@@ -140,6 +140,7 @@
"${tint_src_dir}/lang/wgsl/program",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/bytes",
+ "${tint_src_dir}/utils/command",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
@@ -156,7 +157,10 @@
]
if (tint_build_hlsl_writer) {
- deps += [ "${tint_src_dir}/lang/hlsl/writer" ]
+ deps += [
+ "${tint_src_dir}/lang/hlsl/validate",
+ "${tint_src_dir}/lang/hlsl/writer",
+ ]
}
if (tint_build_wgsl_reader) {
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index 13b1fd6..35a7140 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -709,7 +709,7 @@
auto* dst_el_type = dst_type->DeepestElement();
if (!dst_el_type->is_integer_scalar() && !dst_el_type->is_float_scalar()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "Unable to do bitcast to type " << dst_el_type->FriendlyName();
return false;
}
@@ -3122,8 +3122,7 @@
case wgsl::BuiltinFn::kSubgroupBroadcast:
return "WaveReadLaneAt";
default:
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "Unknown builtin method: " << builtin->str();
+ diagnostics_.AddError(Source{}) << "Unknown builtin method: " << builtin->str();
}
return "";
@@ -3394,7 +3393,7 @@
case core::AddressSpace::kWorkgroup:
return EmitWorkgroupVariable(sem);
case core::AddressSpace::kPushConstant:
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "unhandled address space " << sem->AddressSpace();
return false;
default: {
@@ -3405,7 +3404,7 @@
},
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "override-expressions should have been removed with the SubstituteOverride "
"transform";
return false;
@@ -3630,7 +3629,7 @@
out << ", ";
}
if (!wgsize[i].has_value()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "override-expressions should have been removed with the "
"SubstituteOverride transform";
return false;
@@ -3784,8 +3783,7 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -3880,8 +3878,7 @@
out << "u";
return true;
}
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown integer literal suffix type";
+ diagnostics_.AddError(Source{}) << "unknown integer literal suffix type";
return false;
}, //
TINT_ICE_ON_NO_MATCH);
@@ -4348,8 +4345,7 @@
}
const auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -4588,7 +4584,7 @@
if (auto builtin = attributes.builtin) {
auto name = builtin_to_attribute(builtin.value());
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, Source{}) << "unsupported builtin";
+ diagnostics_.AddError(Source{}) << "unsupported builtin";
return false;
}
post += " : " + name;
@@ -4596,8 +4592,7 @@
if (auto interpolation = attributes.interpolation) {
auto mod = interpolation_to_modifiers(interpolation->type, interpolation->sampling);
if (mod.empty()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unsupported interpolation";
+ diagnostics_.AddError(Source{}) << "unsupported interpolation";
return false;
}
pre += mod;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
index 8348b54..1a99d1f 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer_test.cc
@@ -35,7 +35,7 @@
using HlslASTPrinterTest = TestHelper;
TEST_F(HlslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
+ Diagnostics().AddError(Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc b/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
index f266d83..bee8ba5 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/num_workgroups_from_uniform.cc
@@ -90,8 +90,7 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc b/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
index fd59677..d193740 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/pixel_local.cc
@@ -469,7 +469,7 @@
uint32_t ROVRegisterIndex(uint32_t field_index) {
auto idx = cfg.pls_member_to_rov_reg.Get(field_index);
if (TINT_UNLIKELY(!idx)) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "PixelLocal::Config::attachments missing entry for field " << field_index;
return 0;
}
@@ -501,8 +501,7 @@
auto* cfg = inputs.Get<Config>();
if (!cfg) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
index 7028093..07dd208 100644
--- a/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
+++ b/src/tint/lang/hlsl/writer/ast_raise/truncate_interstage_variables.cc
@@ -70,7 +70,7 @@
const auto* data = config.Get<Config>();
if (data == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "missing transform data for "
<< tint::TypeInfo::Of<TruncateInterstageVariables>().name;
return resolver::Resolve(b);
diff --git a/src/tint/lang/hlsl/writer/common/option_helpers.cc b/src/tint/lang/hlsl/writer/common/option_helpers.cc
index 416569d..ec26be9 100644
--- a/src/tint/lang/hlsl/writer/common/option_helpers.cc
+++ b/src/tint/lang/hlsl/writer/common/option_helpers.cc
@@ -54,8 +54,7 @@
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Get(src)) {
if (*binding != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
- << "found duplicate WGSL binding point: " << src;
+ diagnostics.AddError(Source{}) << "found duplicate WGSL binding point: " << src;
return true;
}
}
@@ -67,7 +66,7 @@
const tint::BindingPoint& dst) -> bool {
if (auto binding = map.Get(src)) {
if (*binding != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
+ diagnostics.AddError(Source{})
<< "found duplicate MSL binding point: [binding: " << src.binding << "]";
return true;
}
@@ -94,27 +93,27 @@
// Storage and uniform are both [[buffer()]]
if (!valid(seen_hlsl_buffer_bindings, options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
+ diagnostics.AddNote(Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_hlsl_buffer_bindings, options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
+ diagnostics.AddNote(Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
// Sampler is [[sampler()]]
if (!valid(seen_hlsl_sampler_bindings, options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
+ diagnostics.AddNote(Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
// Texture and storage texture are [[texture()]]
if (!valid(seen_hlsl_texture_bindings, options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
+ diagnostics.AddNote(Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_hlsl_texture_bindings, options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
+ diagnostics.AddNote(Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
@@ -126,26 +125,22 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Plane0 & Plane1 are [[texture()]]
if (hlsl_seen(seen_hlsl_texture_bindings, plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (hlsl_seen(seen_hlsl_texture_bindings, plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Metadata is [[buffer()]]
if (hlsl_seen(seen_hlsl_buffer_bindings, metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc b/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
index a2865f9..12497e6 100644
--- a/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
+++ b/src/tint/lang/hlsl/writer/writer_ast_fuzz.cc
@@ -27,19 +27,58 @@
// GEN_BUILD:CONDITION(tint_build_wgsl_reader)
+#include <string>
+#include <unordered_map>
+
#include "src/tint/cmd/fuzz/wgsl/fuzz.h"
+#include "src/tint/lang/hlsl/validate/validate.h"
#include "src/tint/lang/hlsl/writer/writer.h"
#include "src/tint/lang/wgsl/ast/module.h"
+#include "src/tint/utils/command/command.h"
namespace tint::hlsl::writer {
namespace {
-void ASTFuzzer(const tint::Program& program, Options options) {
+void ASTFuzzer(const tint::Program& program,
+ const fuzz::wgsl::Options& fuzz_options,
+ Options options) {
if (program.AST().HasOverrides()) {
return;
}
- [[maybe_unused]] auto res = tint::hlsl::writer::Generate(program, options);
+ auto res = tint::hlsl::writer::Generate(program, options);
+ if (res == Success) {
+ const char* dxc_path = validate::kDxcDLLName;
+ bool must_validate = false;
+ if (!fuzz_options.dxc.empty()) {
+ must_validate = true;
+ dxc_path = fuzz_options.dxc.c_str();
+ }
+
+ auto dxc = tint::Command::LookPath(dxc_path);
+ if (dxc.Found()) {
+ uint32_t hlsl_shader_model = 60;
+ bool require_16bit_types = false;
+ auto enable_list = program.AST().Enables();
+ for (auto* enable : enable_list) {
+ if (enable->HasExtension(tint::wgsl::Extension::kF16)) {
+ hlsl_shader_model = 62;
+ require_16bit_types = true;
+ break;
+ }
+ }
+
+ auto validate_res = validate::ValidateUsingDXC(dxc.Path(), res->hlsl, res->entry_points,
+ require_16bit_types, hlsl_shader_model);
+
+ if (must_validate && validate_res.failed) {
+ TINT_ICE() << "DXC was expected to succeed, but failed: " << validate_res.output;
+ }
+
+ } else if (must_validate) {
+ TINT_ICE() << "DXC path was explicitly specified, but was not found: " << dxc_path;
+ }
+ }
}
} // namespace
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index bb583cd..0ba01d6 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -314,7 +314,7 @@
},
[&](const ast::Override*) {
// Override is removed with SubstituteOverride
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "override-expressions should have been removed with the "
"SubstituteOverride transform.";
return false;
@@ -373,8 +373,7 @@
return false;
}
} else {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown alias type: " << ty->FriendlyName();
+ diagnostics_.AddError(Source{}) << "unknown alias type: " << ty->FriendlyName();
return false;
}
@@ -1073,8 +1072,7 @@
std::vector<const char*> dims;
switch (texture_type->dim()) {
case core::type::TextureDimension::kNone:
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "texture dimension is kNone";
+ diagnostics_.AddError(Source{}) << "texture dimension is kNone";
return false;
case core::type::TextureDimension::k1d:
dims = {"width"};
@@ -1273,7 +1271,7 @@
out << "gradientcube(";
break;
default: {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "MSL does not support gradients for " << dim << " textures";
return false;
}
@@ -1630,13 +1628,12 @@
out += "unpack_unorm2x16_to_float";
break;
case wgsl::BuiltinFn::kArrayLength:
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "Unable to translate builtin: " << builtin->Fn()
<< "\nDid you forget to pass array_length_from_uniform generator options?";
return "";
default:
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "Unknown import method: " << builtin->Fn();
+ diagnostics_.AddError(Source{}) << "Unknown import method: " << builtin->Fn();
return "";
}
return out;
@@ -1811,8 +1808,7 @@
auto count = a->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -1882,8 +1878,7 @@
return true;
}
}
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown integer literal suffix type";
+ diagnostics_.AddError(Source{}) << "unknown integer literal suffix type";
return false;
}, //
TINT_ICE_ON_NO_MATCH);
@@ -2078,8 +2073,7 @@
auto name = BuiltinToAttribute(builtin);
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown builtin";
+ diagnostics_.AddError(Source{}) << "unknown builtin";
return false;
}
out << " [[" << name << "]]";
@@ -2536,8 +2530,7 @@
} else {
auto count = arr->ConstantCount();
if (!count) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ diagnostics_.AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return false;
}
@@ -2632,8 +2625,7 @@
out << "cube_array";
break;
default:
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "Invalid texture dimensions";
+ diagnostics_.AddError(Source{}) << "Invalid texture dimensions";
return false;
}
if (tex->IsAnyOf<core::type::MultisampledTexture,
@@ -2666,7 +2658,7 @@
} else if (storage->access() == core::Access::kWrite) {
out << ", access::write";
} else {
- diagnostics_.AddError(diag::System::Writer, Source{})
+ diagnostics_.AddError(Source{})
<< "Invalid access control for storage texture";
return false;
}
@@ -2808,7 +2800,7 @@
if (auto builtin = attributes.builtin) {
auto name = BuiltinToAttribute(builtin.value());
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown builtin";
+ diagnostics_.AddError(Source{}) << "unknown builtin";
return false;
}
out << " [[" << name << "]]";
@@ -2850,8 +2842,7 @@
if (auto interpolation = attributes.interpolation) {
auto name = InterpolationToAttribute(interpolation->type, interpolation->sampling);
if (name.empty()) {
- diagnostics_.AddError(diag::System::Writer, Source{})
- << "unknown interpolation attribute";
+ diagnostics_.AddError(Source{}) << "unknown interpolation attribute";
return false;
}
out << " [[" << name << "]]";
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
index 5a1e8c0..4f60358 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
@@ -39,7 +39,7 @@
using MslASTPrinterTest = TestHelper;
TEST_F(MslASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
+ Diagnostics().AddError(Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
index 0084d30..370164a 100644
--- a/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
+++ b/src/tint/lang/msl/writer/ast_raise/module_scope_var_to_entry_point_param.cc
@@ -244,7 +244,7 @@
case core::AddressSpace::kWorkgroup:
break;
case core::AddressSpace::kPushConstant: {
- ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ ctx.dst->Diagnostics().AddError(Source{})
<< "unhandled module-scope address space (" << sc << ")";
break;
}
diff --git a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc b/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
index c6cc55a..a9a79d8 100644
--- a/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
+++ b/src/tint/lang/msl/writer/ast_raise/pixel_local.cc
@@ -257,7 +257,7 @@
uint32_t AttachmentIndex(uint32_t field_index) {
auto idx = cfg.attachments.Get(field_index);
if (TINT_UNLIKELY(!idx)) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "PixelLocal::Config::attachments missing entry for field " << field_index;
return 0;
}
@@ -275,8 +275,7 @@
auto* cfg = inputs.Get<Config>();
if (!cfg) {
ProgramBuilder b;
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/msl/writer/common/option_helpers.cc b/src/tint/lang/msl/writer/common/option_helpers.cc
index ab4857b..ace6898 100644
--- a/src/tint/lang/msl/writer/common/option_helpers.cc
+++ b/src/tint/lang/msl/writer/common/option_helpers.cc
@@ -53,8 +53,7 @@
auto wgsl_seen = [&diagnostics, &seen_wgsl_bindings](const tint::BindingPoint& src,
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Add(src, dst); binding.value != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
- << "found duplicate WGSL binding point: " << src;
+ diagnostics.AddError(Source{}) << "found duplicate WGSL binding point: " << src;
return true;
}
return false;
@@ -63,7 +62,7 @@
auto msl_seen = [&diagnostics](InfoToPointMap& map, const binding::BindingInfo& src,
const tint::BindingPoint& dst) -> bool {
if (auto binding = map.Add(src, dst); binding.value != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
+ diagnostics.AddError(Source{})
<< "found duplicate MSL binding point: [binding: " << src.binding << "]";
return true;
}
@@ -88,27 +87,27 @@
// Storage and uniform are both [[buffer()]]
if (!valid(seen_msl_buffer_bindings, options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
+ diagnostics.AddNote(Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_msl_buffer_bindings, options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
+ diagnostics.AddNote(Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
// Sampler is [[sampler()]]
if (!valid(seen_msl_sampler_bindings, options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
+ diagnostics.AddNote(Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
// Texture and storage texture are [[texture()]]
if (!valid(seen_msl_texture_bindings, options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
+ diagnostics.AddNote(Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(seen_msl_texture_bindings, options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
+ diagnostics.AddNote(Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
@@ -120,26 +119,22 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Plane0 & Plane1 are [[texture()]]
if (msl_seen(seen_msl_texture_bindings, plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (msl_seen(seen_msl_texture_bindings, plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
// Metadata is [[buffer()]]
if (msl_seen(seen_msl_buffer_bindings, metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
index 9788113..5887c3e 100644
--- a/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/msl/writer/raise/builtin_polyfill.cc
@@ -76,13 +76,13 @@
core::ir::Value* replacement = nullptr;
switch (builtin->Func()) {
case core::BuiltinFn::kStorageBarrier:
- replacement = StorageBarrier(builtin);
+ replacement = ThreadgroupBarrier(builtin, BarrierType::kDevice);
break;
case core::BuiltinFn::kWorkgroupBarrier:
- replacement = WorkgroupBarrier(builtin);
+ replacement = ThreadgroupBarrier(builtin, BarrierType::kThreadGroup);
break;
case core::BuiltinFn::kTextureBarrier:
- replacement = TextureBarrier(builtin);
+ replacement = ThreadgroupBarrier(builtin, BarrierType::kTexture);
break;
default:
break;
@@ -98,39 +98,13 @@
}
}
- /// Handle a `workgroupBarrier()` builtin.
+ /// Replace a barrier builtin with the `threadgroupBarrier()` intrinsic.
/// @param builtin the builtin call instruction
+ /// @param type the barrier type
/// @returns the replacement value
- core::ir::Value* WorkgroupBarrier(core::ir::CoreBuiltinCall* builtin) {
+ core::ir::Value* ThreadgroupBarrier(core::ir::CoreBuiltinCall* builtin, BarrierType type) {
// Replace the builtin call with a call to the msl.threadgroup_barrier intrinsic.
- auto args = Vector<core::ir::Value*, 4>{b.Constant(u32(BarrierType::kThreadGroup))};
-
- auto* call = b.Call<msl::ir::BuiltinCall>(
- builtin->Result(0)->Type(), msl::BuiltinFn::kThreadgroupBarrier, std::move(args));
- call->InsertBefore(builtin);
- return call->Result(0);
- }
-
- /// Handle a `storageBarrier()` builtin.
- /// @param builtin the builtin call instruction
- /// @returns the replacement value
- core::ir::Value* StorageBarrier(core::ir::CoreBuiltinCall* builtin) {
- // Replace the builtin call with a call to the msl.threadgroup_barrier intrinsic.
- auto args = Vector<core::ir::Value*, 4>{b.Constant(u32(BarrierType::kDevice))};
-
- auto* call = b.Call<msl::ir::BuiltinCall>(
- builtin->Result(0)->Type(), msl::BuiltinFn::kThreadgroupBarrier, std::move(args));
- call->InsertBefore(builtin);
- return call->Result(0);
- }
-
- /// Handle a `textureBarrier()` builtin.
- /// @param builtin the builtin call instruction
- /// @returns the replacement value
- core::ir::Value* TextureBarrier(core::ir::CoreBuiltinCall* builtin) {
- // Replace the builtin call with a call to the msl.threadgroup_barrier intrinsic.
- auto args = Vector<core::ir::Value*, 4>{b.Constant(u32(BarrierType::kTexture))};
-
+ auto args = Vector<core::ir::Value*, 1>{b.Constant(u32(type))};
auto* call = b.Call<msl::ir::BuiltinCall>(
builtin->Result(0)->Type(), msl::BuiltinFn::kThreadgroupBarrier, std::move(args));
call->InsertBefore(builtin);
diff --git a/src/tint/lang/spirv/reader/ast_lower/atomics.cc b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
index 181ab19..8b74df7 100644
--- a/src/tint/lang/spirv/reader/ast_lower/atomics.cc
+++ b/src/tint/lang/spirv/reader/ast_lower/atomics.cc
@@ -224,7 +224,7 @@
}
auto count = arr->ConstantCount();
if (!count) {
- ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ ctx.dst->Diagnostics().AddError(Source{})
<< "the Atomics transform does not currently support array counts that use "
"override values";
count = 1;
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
index e4cf3ef..efb14a2 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.cc
@@ -29,7 +29,7 @@
#include <algorithm>
#include <limits>
-#include <locale>
+#include <string_view>
#include <utility>
#include "source/opt/build_module.h"
@@ -775,11 +775,10 @@
return true;
}
-bool ASTParser::IsValidIdentifier(const std::string& str) {
+bool ASTParser::IsValidIdentifier(std::string_view str) {
if (str.empty()) {
return false;
}
- std::locale c_locale("C");
if (str[0] == '_') {
if (str.length() == 1u || str[1] == '_') {
// https://www.w3.org/TR/WGSL/#identifiers
@@ -787,14 +786,28 @@
// must not start with two underscores
return false;
}
- } else if (!std::isalpha(str[0], c_locale)) {
- return false;
}
- for (const char& ch : str) {
- if ((ch != '_') && !std::isalnum(ch, c_locale)) {
+
+ // Must begin with an XID_Source unicode character, or underscore
+ {
+ auto* utf8 = reinterpret_cast<const uint8_t*>(str.data());
+ auto [code_point, n] = tint::utf8::Decode(utf8, str.size());
+ if (code_point != tint::CodePoint('_') && !code_point.IsXIDStart()) {
return false;
}
+ str = str.substr(n);
}
+
+ // Must continue with an XID_Continue unicode character
+ while (!str.empty()) {
+ auto* utf8 = reinterpret_cast<const uint8_t*>(str.data());
+ auto [code_point, n] = tint::utf8::Decode(utf8, str.size());
+ if (!code_point.IsXIDContinue()) {
+ return false;
+ }
+ str = str.substr(n);
+ }
+
return true;
}
diff --git a/src/tint/lang/spirv/reader/ast_parser/ast_parser.h b/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
index 86f60e7..8f755f7 100644
--- a/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
+++ b/src/tint/lang/spirv/reader/ast_parser/ast_parser.h
@@ -628,7 +628,7 @@
/// @param str a candidate identifier
/// @returns true if the given string is a valid WGSL identifier.
- static bool IsValidIdentifier(const std::string& str);
+ static bool IsValidIdentifier(std::string_view str);
/// Returns true if the given SPIR-V ID is a declared specialization constant,
/// generated by one of OpConstantTrue, OpConstantFalse, or OpSpecConstant
diff --git a/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc b/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
index 7fa6c89..aef7e09 100644
--- a/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/barrier_test.cc
@@ -51,7 +51,7 @@
auto p = std::make_unique<ASTParser>(test::Assemble(preamble + spirv));
if (!p->BuildAndParseInternalModule()) {
ProgramBuilder builder;
- builder.Diagnostics().AddError(diag::System::Reader, Source{}) << p->error();
+ builder.Diagnostics().AddError(Source{}) << p->error();
return Program(std::move(builder));
}
return p->Program();
diff --git a/src/tint/lang/spirv/reader/ast_parser/parse.cc b/src/tint/lang/spirv/reader/ast_parser/parse.cc
index ac50d1e..48f9443 100644
--- a/src/tint/lang/spirv/reader/ast_parser/parse.cc
+++ b/src/tint/lang/spirv/reader/ast_parser/parse.cc
@@ -82,7 +82,7 @@
ProgramBuilder& builder = parser.builder();
if (!parsed) {
- builder.Diagnostics().AddError(diag::System::Reader, Source{}) << parser.error();
+ builder.Diagnostics().AddError(Source{}) << parser.error();
return Program(std::move(builder));
}
diff --git a/src/tint/lang/spirv/reader/lower/vector_element_pointer_test.cc b/src/tint/lang/spirv/reader/lower/vector_element_pointer_test.cc
index ade391c..bd30d05 100644
--- a/src/tint/lang/spirv/reader/lower/vector_element_pointer_test.cc
+++ b/src/tint/lang/spirv/reader/lower/vector_element_pointer_test.cc
@@ -42,16 +42,17 @@
TEST_F(SpirvReader_VectorElementPointerTest, NonPointerAccess) {
auto* vec = b.FunctionParam("vec", ty.vec4<u32>());
auto* foo = b.Function("foo", ty.u32());
+ foo->SetParams({vec});
b.Append(foo->Block(), [&] {
auto* access = b.Access<u32>(vec, 2_u);
b.Return(foo, access);
});
auto* src = R"(
-%foo = func():u32 {
+%foo = func(%vec:vec4<u32>):u32 {
$B1: {
- %2:u32 = access %vec, 2u
- ret %2
+ %3:u32 = access %vec, 2u
+ ret %3
}
}
)";
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.bazel b/src/tint/lang/spirv/reader/parser/BUILD.bazel
index 22ae352..556a767 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/parser/BUILD.bazel
@@ -79,6 +79,7 @@
name = "test",
alwayslink = True,
srcs = [
+ "binary_test.cc",
"composite_test.cc",
"constant_test.cc",
"function_test.cc",
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.cmake b/src/tint/lang/spirv/reader/parser/BUILD.cmake
index 52c7c0c..20ea525 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/parser/BUILD.cmake
@@ -85,6 +85,7 @@
# Condition: TINT_BUILD_SPV_READER
################################################################################
tint_add_target(tint_lang_spirv_reader_parser_test test
+ lang/spirv/reader/parser/binary_test.cc
lang/spirv/reader/parser/composite_test.cc
lang/spirv/reader/parser/constant_test.cc
lang/spirv/reader/parser/function_test.cc
diff --git a/src/tint/lang/spirv/reader/parser/BUILD.gn b/src/tint/lang/spirv/reader/parser/BUILD.gn
index f6c3fba..618d5d5 100644
--- a/src/tint/lang/spirv/reader/parser/BUILD.gn
+++ b/src/tint/lang/spirv/reader/parser/BUILD.gn
@@ -86,6 +86,7 @@
if (tint_build_spv_reader) {
tint_unittests_source_set("unittests") {
sources = [
+ "binary_test.cc",
"composite_test.cc",
"constant_test.cc",
"function_test.cc",
diff --git a/src/tint/lang/spirv/reader/parser/binary_test.cc b/src/tint/lang/spirv/reader/parser/binary_test.cc
new file mode 100644
index 0000000..bf5d71a
--- /dev/null
+++ b/src/tint/lang/spirv/reader/parser/binary_test.cc
@@ -0,0 +1,161 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/spirv/reader/parser/helper_test.h"
+
+namespace tint::spirv::reader {
+namespace {
+
+struct BinaryCase {
+ std::string spirv_type;
+ std::string spirv_opcode;
+ std::string ir;
+};
+std::string PrintBuiltinCase(testing::TestParamInfo<BinaryCase> bc) {
+ return bc.param.spirv_opcode + "_" + bc.param.spirv_type;
+}
+
+using BinaryTest = SpirvParserTestWithParam<BinaryCase>;
+
+TEST_P(BinaryTest, All) {
+ auto params = GetParam();
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpCapability Float16
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpExecutionMode %main LocalSize 1 1 1
+ %void = OpTypeVoid
+ %i32 = OpTypeInt 32 1
+ %u32 = OpTypeInt 32 0
+ %f16 = OpTypeFloat 16
+ %f32 = OpTypeFloat 32
+ %vec3i = OpTypeVector %i32 3
+ %vec4u = OpTypeVector %u32 4
+ %vec3h = OpTypeVector %f16 3
+ %vec4f = OpTypeVector %f32 4
+ %ep_type = OpTypeFunction %void
+ %fn_type = OpTypeFunction %)" +
+ params.spirv_type + " %" + params.spirv_type + " %" + params.spirv_type + R"(
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+
+ %foo = OpFunction %)" +
+ params.spirv_type + " " + R"( None %fn_type
+ %lhs = OpFunctionParameter %)" +
+ params.spirv_type + " " + R"(
+ %rhs = OpFunctionParameter %)" +
+ params.spirv_type + " " + R"(
+ %foo_start = OpLabel
+ %result = )" +
+ params.spirv_opcode + R"( %)" + params.spirv_type + " " + R"( %lhs %rhs
+ OpReturnValue %result
+ OpFunctionEnd
+)",
+ R"(
+ $B2: {
+ )" + params.ir +
+ R"(
+ ret %5
+ }
+)");
+}
+
+INSTANTIATE_TEST_SUITE_P(SpirvParser,
+ BinaryTest,
+ testing::Values(
+ // OpFAdd
+ BinaryCase{
+ "f16",
+ "OpFAdd",
+ "%5:f16 = add %3, %4",
+ },
+ BinaryCase{
+ "f32",
+ "OpFAdd",
+ "%5:f32 = add %3, %4",
+ },
+ BinaryCase{
+ "vec3h",
+ "OpFAdd",
+ "%5:vec3<f16> = add %3, %4",
+ },
+ BinaryCase{
+ "vec4f",
+ "OpFAdd",
+ "%5:vec4<f32> = add %3, %4",
+ },
+
+ // OpFMul
+ BinaryCase{
+ "f16",
+ "OpFMul",
+ "%5:f16 = mul %3, %4",
+ },
+ BinaryCase{
+ "f32",
+ "OpFMul",
+ "%5:f32 = mul %3, %4",
+ },
+ BinaryCase{
+ "vec3h",
+ "OpFMul",
+ "%5:vec3<f16> = mul %3, %4",
+ },
+ BinaryCase{
+ "vec4f",
+ "OpFMul",
+ "%5:vec4<f32> = mul %3, %4",
+ },
+
+ // OpIAdd
+ BinaryCase{
+ "i32",
+ "OpIAdd",
+ "%5:i32 = add %3, %4",
+ },
+ BinaryCase{
+ "u32",
+ "OpIAdd",
+ "%5:u32 = add %3, %4",
+ },
+ BinaryCase{
+ "vec3i",
+ "OpIAdd",
+ "%5:vec3<i32> = add %3, %4",
+ },
+ BinaryCase{
+ "vec4u",
+ "OpIAdd",
+ "%5:vec4<u32> = add %3, %4",
+ }),
+ PrintBuiltinCase);
+
+} // namespace
+} // namespace tint::spirv::reader
diff --git a/src/tint/lang/spirv/reader/parser/function_test.cc b/src/tint/lang/spirv/reader/parser/function_test.cc
index d268ebb..d344063 100644
--- a/src/tint/lang/spirv/reader/parser/function_test.cc
+++ b/src/tint/lang/spirv/reader/parser/function_test.cc
@@ -96,6 +96,40 @@
)");
}
+TEST_F(SpirvParserTest, FragmentShader_DepthReplacing) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %main "main" %depth
+ OpExecutionMode %main OriginUpperLeft
+ OpExecutionMode %main DepthReplacing
+ OpDecorate %depth BuiltIn FragDepth
+ %void = OpTypeVoid
+ %f32 = OpTypeFloat 32
+ %f32_42 = OpConstant %f32 42.0
+%_ptr_Output_f32 = OpTypePointer Output %f32
+ %depth = OpVariable %_ptr_Output_f32 Output
+ %ep_type = OpTypeFunction %void
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpStore %depth %f32_42
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+$B1: { # root
+ %1:ptr<__out, f32, read_write> = var @builtin(frag_depth)
+}
+
+%main = @fragment func():void {
+ $B2: {
+ store %1, 42.0f
+ ret
+ }
+}
+)");
+}
+
TEST_F(SpirvParserTest, VertexShader) {
EXPECT_IR(R"(
OpCapability Shader
diff --git a/src/tint/lang/spirv/reader/parser/helper_test.h b/src/tint/lang/spirv/reader/parser/helper_test.h
index cf510d3..865aa4c 100644
--- a/src/tint/lang/spirv/reader/parser/helper_test.h
+++ b/src/tint/lang/spirv/reader/parser/helper_test.h
@@ -34,7 +34,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/spirv/reader/common/helper_test.h"
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index 6023194..8fadddf 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -487,7 +487,9 @@
execution_mode.GetSingleWordInOperand(3),
execution_mode.GetSingleWordInOperand(4));
break;
+ case spv::ExecutionMode::DepthReplacing:
case spv::ExecutionMode::OriginUpperLeft:
+ // These are ignored as they are implicitly supported by Tint IR.
break;
default:
TINT_UNIMPLEMENTED() << "unhandled execution mode: " << mode;
@@ -512,9 +514,18 @@
case spv::Op::OpCompositeExtract:
EmitCompositeExtract(inst);
break;
+ case spv::Op::OpFAdd:
+ EmitBinary(inst, core::BinaryOp::kAdd);
+ break;
+ case spv::Op::OpFMul:
+ EmitBinary(inst, core::BinaryOp::kMultiply);
+ break;
case spv::Op::OpFunctionCall:
EmitFunctionCall(inst);
break;
+ case spv::Op::OpIAdd:
+ EmitBinary(inst, core::BinaryOp::kAdd);
+ break;
case spv::Op::OpLoad:
Emit(b_.Load(Value(inst.GetSingleWordOperand(2))), inst.result_id());
break;
@@ -556,6 +567,15 @@
Emit(access, inst.result_id());
}
+ /// @param inst the SPIR-V instruction
+ /// @param op the binary operator to use
+ void EmitBinary(const spvtools::opt::Instruction& inst, core::BinaryOp op) {
+ auto* lhs = Value(inst.GetSingleWordOperand(2));
+ auto* rhs = Value(inst.GetSingleWordOperand(3));
+ auto* binary = b_.Binary(op, Type(inst.type_id()), lhs, rhs);
+ Emit(binary, inst.result_id());
+ }
+
/// @param inst the SPIR-V instruction for OpCompositeExtract
void EmitCompositeExtract(const spvtools::opt::Instruction& inst) {
Vector<core::ir::Value*, 4> indices;
diff --git a/src/tint/lang/spirv/reader/reader_test.cc b/src/tint/lang/spirv/reader/reader_test.cc
index cd0626b..d8ab351 100644
--- a/src/tint/lang/spirv/reader/reader_test.cc
+++ b/src/tint/lang/spirv/reader/reader_test.cc
@@ -31,7 +31,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/spirv/reader/common/helper_test.h"
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
index e76c3c2..48c2a3d 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer_test.cc
@@ -34,7 +34,7 @@
using SpirvASTPrinterTest = TestHelper;
TEST_F(SpirvASTPrinterTest, InvalidProgram) {
- Diagnostics().AddError(diag::System::Writer, Source{}) << "make the program invalid";
+ Diagnostics().AddError(Source{}) << "make the program invalid";
ASSERT_FALSE(IsValid());
auto program = resolver::Resolve(*this);
ASSERT_FALSE(program.IsValid());
diff --git a/src/tint/lang/spirv/writer/common/option_helper.cc b/src/tint/lang/spirv/writer/common/option_helper.cc
index 76a21ed..f209b63 100644
--- a/src/tint/lang/spirv/writer/common/option_helper.cc
+++ b/src/tint/lang/spirv/writer/common/option_helper.cc
@@ -48,8 +48,7 @@
const binding::BindingInfo& dst) -> bool {
if (auto binding = seen_wgsl_bindings.Get(src)) {
if (*binding != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
- << "found duplicate WGSL binding point: " << src;
+ diagnostics.AddError(Source{}) << "found duplicate WGSL binding point: " << src;
return true;
}
}
@@ -61,7 +60,7 @@
const tint::BindingPoint& dst) -> bool {
if (auto binding = seen_spirv_bindings.Get(src)) {
if (*binding != dst) {
- diagnostics.AddError(diag::System::Writer, Source{})
+ diagnostics.AddError(Source{})
<< "found duplicate SPIR-V binding point: [group: " << src.group
<< ", binding: " << src.binding << "]";
return true;
@@ -88,23 +87,23 @@
};
if (!valid(options.bindings.uniform)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing uniform";
+ diagnostics.AddNote(Source{}) << "when processing uniform";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.storage)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage";
+ diagnostics.AddNote(Source{}) << "when processing storage";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing texture";
+ diagnostics.AddNote(Source{}) << "when processing texture";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.storage_texture)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing storage_texture";
+ diagnostics.AddNote(Source{}) << "when processing storage_texture";
return Failure{std::move(diagnostics)};
}
if (!valid(options.bindings.sampler)) {
- diagnostics.AddNote(diag::System::Writer, Source{}) << "when processing sampler";
+ diagnostics.AddNote(Source{}) << "when processing sampler";
return Failure{std::move(diagnostics)};
}
@@ -116,24 +115,20 @@
// Validate with the actual source regardless of what the remapper will do
if (wgsl_seen(src_binding, plane0)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(plane0, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(plane1, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
if (spirv_seen(metadata, src_binding)) {
- diagnostics.AddNote(diag::System::Writer, Source{})
- << "when processing external_texture";
+ diagnostics.AddNote(Source{}) << "when processing external_texture";
return Failure{std::move(diagnostics)};
}
}
diff --git a/src/tint/lang/spirv/writer/raise/merge_return_test.cc b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
index 75998f5..40d44b0 100644
--- a/src/tint/lang/spirv/writer/raise/merge_return_test.cc
+++ b/src/tint/lang/spirv/writer/raise/merge_return_test.cc
@@ -67,7 +67,7 @@
auto* in = b.FunctionParam(ty.i32());
auto* cond = b.FunctionParam(ty.bool_());
auto* func = b.Function("foo", ty.i32());
- func->SetParams({in});
+ func->SetParams({in, cond});
b.Append(func->Block(), [&] {
auto* ifelse = b.If(cond);
@@ -78,9 +78,9 @@
b.Return(func, ifelse->Result(0));
});
auto* src = R"(
-%foo = func(%2:i32):i32 {
+%foo = func(%2:i32, %3:bool):i32 {
$B1: {
- %3:i32 = if %4 [t: $B2, f: $B3] { # if_1
+ %4:i32 = if %3 [t: $B2, f: $B3] { # if_1
$B2: { # true
%5:i32 = add %2, 1i
exit_if %5 # if_1
@@ -90,7 +90,7 @@
exit_if %6 # if_1
}
}
- ret %3
+ ret %4
}
}
)";
@@ -107,7 +107,7 @@
auto* in = b.FunctionParam(ty.i32());
auto* cond = b.FunctionParam(ty.bool_());
auto* func = b.Function("foo", ty.i32());
- func->SetParams({in});
+ func->SetParams({in, cond});
b.Append(func->Block(), [&] {
auto* swtch = b.Switch(in);
@@ -125,7 +125,7 @@
});
auto* src = R"(
-%foo = func(%2:i32):i32 {
+%foo = func(%2:i32, %3:bool):i32 {
$B1: {
switch %2 [c: (default, $B2)] { # switch_1
$B2: { # case
@@ -137,7 +137,7 @@
exit_loop # loop_1
}
}
- %3:i32 = if %4 [t: $B4, f: $B5] { # if_1
+ %4:i32 = if %3 [t: $B4, f: $B5] { # if_1
$B4: { # true
%5:i32 = add %2, 1i
exit_if %5 # if_1
@@ -147,7 +147,7 @@
exit_if %6 # if_1
}
}
- ret %3
+ ret %4
}
}
)";
diff --git a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
index 59b0f27..e1a9da3 100644
--- a/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
+++ b/src/tint/lang/spirv/writer/raise/var_for_dynamic_index_test.cc
@@ -587,11 +587,11 @@
$B2 (%5:array<i32, 4>): { # body
if %2 [t: $B3, f: $B4] { # if_1
$B3: { # true
- %6:i32 = access %5:array<i32, 4>, %3
+ %6:i32 = access %5, %3
ret %6
}
$B4: { # false
- %7:i32 = access %5:array<i32, 4>, %4
+ %7:i32 = access %5, %4
ret %7
}
}
@@ -609,7 +609,7 @@
$B1: {
loop [b: $B2] { # loop_1
$B2 (%5:array<i32, 4>): { # body
- %6:ptr<function, array<i32, 4>, read_write> = var, %5:array<i32, 4>
+ %6:ptr<function, array<i32, 4>, read_write> = var, %5
if %2 [t: $B3, f: $B4] { # if_1
$B3: { # true
%7:ptr<function, i32, read_write> = access %6, %3
@@ -666,11 +666,11 @@
$B2 (%5:array<array<i32, 4>, 4>): { # body
if %2 [t: $B3, f: $B4] { # if_1
$B3: { # true
- %6:i32 = access %5:array<array<i32, 4>, 4>, 0u, %3
+ %6:i32 = access %5, 0u, %3
ret %6
}
$B4: { # false
- %7:i32 = access %5:array<array<i32, 4>, 4>, 0u, %4
+ %7:i32 = access %5, 0u, %4
ret %7
}
}
@@ -688,7 +688,7 @@
$B1: {
loop [b: $B2] { # loop_1
$B2 (%5:array<array<i32, 4>, 4>): { # body
- %6:array<i32, 4> = access %5:array<array<i32, 4>, 4>, 0u
+ %6:array<i32, 4> = access %5, 0u
%7:ptr<function, array<i32, 4>, read_write> = var, %6
if %2 [t: $B3, f: $B4] { # if_1
$B3: { # true
diff --git a/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc b/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
index 636f8f3..40c7fc2 100644
--- a/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
+++ b/src/tint/lang/wgsl/ast/transform/array_length_from_uniform.cc
@@ -97,9 +97,8 @@
/// @returns the new program or SkipTransform if the transform is not required
ApplyResult Run() {
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for "
- << tint::TypeInfo::Of<ArrayLengthFromUniform>().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for "
+ << tint::TypeInfo::Of<ArrayLengthFromUniform>().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/binding_remapper.cc b/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
index 5501dd5..d89d8d8 100644
--- a/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
+++ b/src/tint/lang/wgsl/ast/transform/binding_remapper.cc
@@ -67,8 +67,7 @@
auto* remappings = inputs.Get<Remappings>();
if (!remappings) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
@@ -113,13 +112,13 @@
if (ac_it != remappings->access_controls.end()) {
core::Access access = ac_it->second;
if (access == core::Access::kUndefined) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "invalid access mode (" << static_cast<uint32_t>(access) << ")";
return resolver::Resolve(b);
}
auto* sem = src.Sem().Get(var);
if (sem->AddressSpace() != core::AddressSpace::kStorage) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "cannot apply access control to variable with address space "
<< sem->AddressSpace();
return resolver::Resolve(b);
diff --git a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
index e61f615..206a8d3 100644
--- a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
@@ -979,8 +979,7 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_fuzz.cc b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_fuzz.cc
index d2ef4c8..2854240 100644
--- a/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_fuzz.cc
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_fuzz.cc
@@ -31,7 +31,18 @@
namespace tint::ast::transform {
namespace {
+bool CanRun(const ClampFragDepth::Config& config) {
+ if (config.offsets && config.offsets->min >= config.offsets->max) {
+ return false; // member offset collision / non-ascending
+ }
+ return true;
+}
+
void ClampFragDepthFuzzer(const Program& program, const ClampFragDepth::Config& config) {
+ if (!CanRun(config)) {
+ return;
+ }
+
DataMap inputs;
inputs.Add<ClampFragDepth::Config>(std::move(config));
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
index 3d7450b..51b5f1e 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
@@ -135,7 +135,7 @@
BindingsMap::const_iterator it = new_binding_points->bindings_map.find(bp);
if (it == new_binding_points->bindings_map.end()) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "missing new binding points for texture_external at binding {" << bp.group
<< "," << bp.binding << "}";
continue;
@@ -295,7 +295,13 @@
b.Member("gammaEncodeParams", b.ty("GammaTransferParams")),
b.Member("gamutConversionMatrix", b.ty.mat3x3<f32>()),
b.Member("coordTransformationMatrix", b.ty.mat3x2<f32>()),
- };
+ b.Member("loadTransformationMatrix", b.ty.mat3x2<f32>()),
+ b.Member("samplePlane0RectMin", b.ty.vec2<f32>()),
+ b.Member("samplePlane0RectMax", b.ty.vec2<f32>()),
+ b.Member("samplePlane1RectMin", b.ty.vec2<f32>()),
+ b.Member("samplePlane1RectMax", b.ty.vec2<f32>()),
+ b.Member("displayVisibleRectMax", b.ty.vec2<u32>()),
+ b.Member("plane1CoordFactor", b.ty.vec2<f32>())};
params_struct_sym = b.Symbols().New("ExternalTextureParams");
@@ -344,72 +350,90 @@
/// @returns a statement list that makes of the body of the chosen function
auto buildTextureBuiltinBody(wgsl::BuiltinFn call_type) {
tint::Vector<const Statement*, 16> stmts;
- const CallExpression* single_plane_call = nullptr;
- const CallExpression* plane_0_call = nullptr;
- const CallExpression* plane_1_call = nullptr;
+ const BlockStatement* single_plane_block = nullptr;
+ const BlockStatement* multi_plane_block = nullptr;
switch (call_type) {
case wgsl::BuiltinFn::kTextureSampleBaseClampToEdge:
stmts.Push(b.Decl(b.Let(
"modifiedCoords", b.Mul(b.MemberAccessor("params", "coordTransformationMatrix"),
b.Call<vec3<f32>>("coord", 1_a)))));
- stmts.Push(b.Decl(
- b.Let("plane0_dims",
- b.Call(b.ty.vec2<f32>(), b.Call("textureDimensions", "plane0", 0_a)))));
- stmts.Push(b.Decl(
- b.Let("plane0_half_texel", b.Div(b.Call<vec2<f32>>(0.5_a), "plane0_dims"))));
- stmts.Push(b.Decl(
- b.Let("plane0_clamped", b.Call("clamp", "modifiedCoords", "plane0_half_texel",
- b.Sub(1_a, "plane0_half_texel")))));
- stmts.Push(b.Decl(
- b.Let("plane1_dims",
- b.Call(b.ty.vec2<f32>(), b.Call("textureDimensions", "plane1", 0_a)))));
- stmts.Push(b.Decl(
- b.Let("plane1_half_texel", b.Div(b.Call<vec2<f32>>(0.5_a), "plane1_dims"))));
- stmts.Push(b.Decl(
- b.Let("plane1_clamped", b.Call("clamp", "modifiedCoords", "plane1_half_texel",
- b.Sub(1_a, "plane1_half_texel")))));
+ stmts.Push(b.Decl(b.Let(
+ "plane0_clamped", b.Call("clamp", "modifiedCoords",
+ b.MemberAccessor("params", "samplePlane0RectMin"),
+ b.MemberAccessor("params", "samplePlane0RectMax")))));
- // textureSampleLevel(plane0, smp, plane0_clamped, 0.0);
- single_plane_call =
- b.Call("textureSampleLevel", "plane0", "smp", "plane0_clamped", 0_a);
- // textureSampleLevel(plane0, smp, plane0_clamped, 0.0);
- plane_0_call = b.Call("textureSampleLevel", "plane0", "smp", "plane0_clamped", 0_a);
- // textureSampleLevel(plane1, smp, plane1_clamped, 0.0);
- plane_1_call = b.Call("textureSampleLevel", "plane1", "smp", "plane1_clamped", 0_a);
+ // var color: vec4<f32>;
+ stmts.Push(b.Decl(b.Var("color", b.ty.vec4(b.ty.f32()))));
+
+ single_plane_block = b.Block(
+ b.Assign("color", b.MemberAccessor(b.Call("textureSampleLevel", "plane0", "smp",
+ "plane0_clamped", 0_a),
+ "rgba")));
+
+ multi_plane_block = b.Block(
+ b.Decl(b.Let("plane1_clamped",
+ b.Call("clamp", "modifiedCoords",
+ b.MemberAccessor("params", "samplePlane1RectMin"),
+ b.MemberAccessor("params", "samplePlane1RectMax")))),
+
+ b.Assign("color",
+ b.Call<vec4<f32>>(
+ b.Mul(b.Call<vec4<f32>>(
+ b.MemberAccessor(b.Call("textureSampleLevel", "plane0",
+ "smp", "plane0_clamped", 0_a),
+ "r"),
+ b.MemberAccessor(b.Call("textureSampleLevel", "plane1",
+ "smp", "plane1_clamped", 0_a),
+ "rg"),
+ 1_a),
+ b.MemberAccessor("params", "yuvToRgbConversionMatrix")),
+ 1_a)));
break;
case wgsl::BuiltinFn::kTextureLoad:
- // textureLoad(plane0, coord, 0);
- single_plane_call = b.Call("textureLoad", "plane0", "coord", 0_a);
- // textureLoad(plane0, coord, 0);
- plane_0_call = b.Call("textureLoad", "plane0", "coord", 0_a);
- // let coord1 = coord >> 1;
- stmts.Push(b.Decl(b.Let("coord1", b.Shr("coord", b.Call<vec2<u32>>(1_a)))));
- // textureLoad(plane1, coord1, 0);
- plane_1_call = b.Call("textureLoad", "plane1", "coord1", 0_a);
+ stmts.Push(b.Decl(b.Let(
+ "clampedCoords", b.Call("min", b.Call<vec2<u32>>("coord"),
+ b.MemberAccessor("params", "displayVisibleRectMax")))));
+ stmts.Push(b.Decl(b.Let(
+ "plane0_clamped",
+ b.Call<vec2<u32>>(b.Call(
+ "round",
+ b.Mul(b.MemberAccessor("params", "loadTransformationMatrix"),
+ b.Call<vec3<f32>>(b.Call<vec2<f32>>("clampedCoords"), 1_a)))))));
+
+ // var color: vec4<f32>;
+ stmts.Push(b.Decl(b.Var("color", b.ty.vec4(b.ty.f32()))));
+
+ single_plane_block = b.Block(b.Assign(
+ "color", b.MemberAccessor(
+ b.Call("textureLoad", "plane0", "plane0_clamped", 0_a), "rgba")));
+
+ multi_plane_block = b.Block(
+ b.Decl(b.Let(
+ "plane1_clamped",
+ b.Call<vec2<u32>>(b.Mul(b.Call<vec2<f32>>("plane0_clamped"),
+ b.MemberAccessor("params", "plane1CoordFactor"))))),
+
+ b.Assign("color",
+ b.Call<vec4<f32>>(
+ b.Mul(b.Call<vec4<f32>>(
+ b.MemberAccessor(b.Call("textureLoad", "plane0",
+ "plane0_clamped", 0_a),
+ "r"),
+ b.MemberAccessor(b.Call("textureLoad", "plane1",
+ "plane1_clamped", 0_a),
+ "rg"),
+ 1_a),
+ b.MemberAccessor("params", "yuvToRgbConversionMatrix")),
+ 1_a)));
break;
default:
TINT_ICE() << "unhandled builtin: " << call_type;
}
- // var color: vec4<f32>;
- stmts.Push(b.Decl(b.Var("color", b.ty.vec4(b.ty.f32()))));
-
// if ((params.numPlanes == 1u))
- stmts.Push(b.If(
- b.Equal(b.MemberAccessor("params", "numPlanes"), b.Expr(1_a)),
- b.Block(
- // color = textureLoad(plane0, coord, 0).rgba;
- b.Assign("color", b.MemberAccessor(single_plane_call, "rgba"))),
- b.Else(b.Block(
- // color = vec4<f32>(vec4<f32>(plane_0_call.r, plane_1_call.rg, 1.0) *
- // params.yuvToRgbConversionMatrix));
- b.Assign("color",
- b.Call<vec4<f32>>(
- b.Mul(b.Call<vec4<f32>>(b.MemberAccessor(plane_0_call, "r"),
- b.MemberAccessor(plane_1_call, "rg"), 1_a),
- b.MemberAccessor("params", "yuvToRgbConversionMatrix")),
- 1_a))))));
+ stmts.Push(b.If(b.Equal(b.MemberAccessor("params", "numPlanes"), b.Expr(1_a)),
+ single_plane_block, b.Else(multi_plane_block)));
// if (params.doYuvToRgbConversionOnly == 0u)
stmts.Push(b.If(
@@ -558,7 +582,7 @@
ProgramBuilder b;
program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};
if (!new_binding_points) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "missing new binding point data for " << TypeInfo().name;
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
index f89523c..8f78af9 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
@@ -153,6 +153,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
@@ -206,6 +213,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@internal(disable_validation__binding_point_collision) @group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
@@ -222,12 +236,14 @@
}
fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<u32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -286,6 +302,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
@@ -341,6 +364,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -360,16 +390,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -425,6 +451,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -440,16 +473,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -510,6 +539,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
@@ -526,12 +562,14 @@
}
fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -542,12 +580,14 @@
}
fn textureLoadExternal_1(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<u32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -605,6 +645,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(1) var ext_tex_plane_1 : texture_2d<f32>;
@@ -619,12 +666,14 @@
}
fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -635,12 +684,14 @@
}
fn textureLoadExternal_1(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<u32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -699,6 +750,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -718,16 +776,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -739,12 +793,14 @@
}
fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -799,6 +855,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -814,16 +877,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -835,12 +894,14 @@
}
fn textureLoadExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, coord : vec2<i32>, params : ExternalTextureParams) -> vec4<f32> {
- let coord1 = (coord >> vec2<u32>(1));
+ let clampedCoords = min(vec2<u32>(coord), params.displayVisibleRectMax);
+ let plane0_clamped = vec2<u32>(round((params.loadTransformationMatrix * vec3<f32>(vec2<f32>(clampedCoords), 1))));
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
- color = textureLoad(plane0, coord, 0).rgba;
+ color = textureLoad(plane0, plane0_clamped, 0).rgba;
} else {
- color = vec4<f32>((vec4<f32>(textureLoad(plane0, coord, 0).r, textureLoad(plane1, coord1, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
+ let plane1_clamped = vec2<u32>((vec2<f32>(plane0_clamped) * params.plane1CoordFactor));
+ color = vec4<f32>((vec4<f32>(textureLoad(plane0, plane0_clamped, 0).r, textureLoad(plane1, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
color = vec4<f32>(gammaCorrection(color.rgb, params.gammaDecodeParams), color.a);
@@ -905,6 +966,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(4) var ext_tex_plane_1 : texture_2d<f32>;
@@ -942,16 +1010,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1016,6 +1080,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1031,16 +1102,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1109,6 +1176,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1129,16 +1203,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1202,6 +1272,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1217,16 +1294,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1297,6 +1370,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(3) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1316,16 +1396,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1401,6 +1477,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(3) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1425,16 +1508,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1506,6 +1585,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1521,16 +1607,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1607,6 +1689,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1622,16 +1711,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1696,6 +1781,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
fn f(ext_tex : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams) -> vec2<u32> {
@@ -1748,6 +1840,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1765,16 +1864,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
@@ -1844,6 +1939,13 @@
gammaEncodeParams : GammaTransferParams,
gamutConversionMatrix : mat3x3<f32>,
coordTransformationMatrix : mat3x2<f32>,
+ loadTransformationMatrix : mat3x2<f32>,
+ samplePlane0RectMin : vec2<f32>,
+ samplePlane0RectMax : vec2<f32>,
+ samplePlane1RectMin : vec2<f32>,
+ samplePlane1RectMax : vec2<f32>,
+ displayVisibleRectMax : vec2<u32>,
+ plane1CoordFactor : vec2<f32>,
}
@group(0) @binding(2) var ext_tex_plane_1 : texture_2d<f32>;
@@ -1864,16 +1966,12 @@
fn textureSampleExternal(plane0 : texture_2d<f32>, plane1 : texture_2d<f32>, smp : sampler, coord : vec2<f32>, params : ExternalTextureParams) -> vec4<f32> {
let modifiedCoords = (params.coordTransformationMatrix * vec3<f32>(coord, 1));
- let plane0_dims = vec2<f32>(textureDimensions(plane0, 0));
- let plane0_half_texel = (vec2<f32>(0.5) / plane0_dims);
- let plane0_clamped = clamp(modifiedCoords, plane0_half_texel, (1 - plane0_half_texel));
- let plane1_dims = vec2<f32>(textureDimensions(plane1, 0));
- let plane1_half_texel = (vec2<f32>(0.5) / plane1_dims);
- let plane1_clamped = clamp(modifiedCoords, plane1_half_texel, (1 - plane1_half_texel));
+ let plane0_clamped = clamp(modifiedCoords, params.samplePlane0RectMin, params.samplePlane0RectMax);
var color : vec4<f32>;
if ((params.numPlanes == 1)) {
color = textureSampleLevel(plane0, smp, plane0_clamped, 0).rgba;
} else {
+ let plane1_clamped = clamp(modifiedCoords, params.samplePlane1RectMin, params.samplePlane1RectMax);
color = vec4<f32>((vec4<f32>(textureSampleLevel(plane0, smp, plane0_clamped, 0).r, textureSampleLevel(plane1, smp, plane1_clamped, 0).rg, 1) * params.yuvToRgbConversionMatrix), 1);
}
if ((params.doYuvToRgbConversionOnly == 0)) {
diff --git a/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc b/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
index ba10cf4..6b72964 100644
--- a/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
+++ b/src/tint/lang/wgsl/ast/transform/push_constant_helper.cc
@@ -64,8 +64,7 @@
void PushConstantHelper::InsertMember(const char* name, ast::Type type, uint32_t offset) {
auto& member = member_map[offset];
if (TINT_UNLIKELY(member != nullptr)) {
- ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
- << "struct member offset collision";
+ ctx.dst->Diagnostics().AddError(Source{}) << "struct member offset collision";
}
member = ctx.dst->Member(name, type, Vector{ctx.dst->MemberOffset(core::AInt(offset))});
}
diff --git a/src/tint/lang/wgsl/ast/transform/robustness.cc b/src/tint/lang/wgsl/ast/transform/robustness.cc
index 42273c5..fa00dc9 100644
--- a/src/tint/lang/wgsl/ast/transform/robustness.cc
+++ b/src/tint/lang/wgsl/ast/transform/robustness.cc
@@ -272,8 +272,7 @@
}
// Note: Don't be tempted to use the array override variable as an expression here,
// the name might be shadowed!
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << core::type::Array::kErrExpectedConstantCount;
+ b.Diagnostics().AddError(Source{}) << core::type::Array::kErrExpectedConstantCount;
return nullptr;
}, //
TINT_ICE_ON_NO_MATCH);
diff --git a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
index a0952eb..ed16c78 100644
--- a/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
+++ b/src/tint/lang/wgsl/ast/transform/single_entry_point.cc
@@ -55,8 +55,7 @@
auto* cfg = inputs.Get<Config>();
if (cfg == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "missing transform data for " << TypeInfo().name;
+ b.Diagnostics().AddError(Source{}) << "missing transform data for " << TypeInfo().name;
return resolver::Resolve(b);
}
@@ -72,7 +71,7 @@
}
}
if (entry_point == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "entry point '" << cfg->entry_point_name << "' not found";
return resolver::Resolve(b);
}
diff --git a/src/tint/lang/wgsl/ast/transform/substitute_override.cc b/src/tint/lang/wgsl/ast/transform/substitute_override.cc
index 4711b36..2c5e06a 100644
--- a/src/tint/lang/wgsl/ast/transform/substitute_override.cc
+++ b/src/tint/lang/wgsl/ast/transform/substitute_override.cc
@@ -71,8 +71,7 @@
const auto* data = config.Get<Config>();
if (!data) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "Missing override substitution data";
+ b.Diagnostics().AddError(Source{}) << "Missing override substitution data";
return resolver::Resolve(b);
}
@@ -91,7 +90,7 @@
auto iter = data->map.find(sem->Attributes().override_id.value());
if (iter == data->map.end()) {
if (!w->initializer) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "Initializer not provided for override, and override not overridden.";
return nullptr;
}
@@ -108,8 +107,7 @@
[&](const core::type::F16*) { return b.Expr(f16(value)); });
if (!ctor) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "Failed to create override-expression";
+ b.Diagnostics().AddError(Source{}) << "Failed to create override-expression";
return nullptr;
}
diff --git a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
index 8eae5a6..4c2145d 100644
--- a/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
+++ b/src/tint/lang/wgsl/ast/transform/vertex_pulling.cc
@@ -260,7 +260,7 @@
for (auto* fn : src.AST().Functions()) {
if (fn->PipelineStage() == PipelineStage::kVertex) {
if (func != nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "VertexPulling found more than one vertex entry point";
return resolver::Resolve(b);
}
@@ -268,8 +268,7 @@
}
}
if (func == nullptr) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
- << "Vertex stage entry point not found";
+ b.Diagnostics().AddError(Source{}) << "Vertex stage entry point not found";
return resolver::Resolve(b);
}
@@ -357,7 +356,7 @@
const VertexBufferLayoutDescriptor& buffer_layout = cfg.vertex_state[buffer_idx];
if ((buffer_layout.array_stride & 3) != 0) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "WebGPU requires that vertex stride must be a multiple of 4 bytes, "
"but VertexPulling array stride for buffer "
<< buffer_idx << " was " << buffer_layout.array_stride << " bytes";
@@ -395,7 +394,7 @@
// Base types must match between the vertex stream and the WGSL variable
if (!IsTypeCompatible(var_dt, fmt_dt)) {
- b.Diagnostics().AddError(diag::System::Transform, Source{})
+ b.Diagnostics().AddError(Source{})
<< "VertexAttributeDescriptor for location "
<< attribute_desc.shader_location << " has format " << attribute_desc.format
<< " but shader expects " << var.type->FriendlyName();
diff --git a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
index 7745eb3..8807cb4 100644
--- a/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
+++ b/src/tint/lang/wgsl/ast/transform/zero_init_workgroup_memory.cc
@@ -385,7 +385,7 @@
// `(idx % modulo) / division`
auto count = arr->ConstantCount();
if (!count) {
- ctx.dst->Diagnostics().AddError(diag::System::Transform, Source{})
+ ctx.dst->Diagnostics().AddError(Source{})
<< core::type::Array::kErrExpectedConstantCount;
return Expression{}; // error
}
diff --git a/src/tint/lang/wgsl/diagnostic_severity.cc b/src/tint/lang/wgsl/diagnostic_severity.cc
index d47944d..4fd7c55 100644
--- a/src/tint/lang/wgsl/diagnostic_severity.cc
+++ b/src/tint/lang/wgsl/diagnostic_severity.cc
@@ -49,7 +49,7 @@
case DiagnosticSeverity::kInfo:
return diag::Severity::Note;
default:
- return diag::Severity::InternalCompilerError;
+ return diag::Severity::Error;
}
}
diff --git a/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl b/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
index fdc3a8d..ff0f70e 100644
--- a/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
+++ b/src/tint/lang/wgsl/diagnostic_severity.cc.tmpl
@@ -26,7 +26,7 @@
case DiagnosticSeverity::kInfo:
return diag::Severity::Note;
default:
- return diag::Severity::InternalCompilerError;
+ return diag::Severity::Error;
}
}
diff --git a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
index 5a4372c..647221e 100644
--- a/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
+++ b/src/tint/lang/wgsl/helpers/check_supported_extensions.cc
@@ -48,9 +48,8 @@
for (auto* enable : module.Enables()) {
for (auto* ext : enable->extensions) {
if (!set.Contains(ext->name)) {
- diags.AddError(diag::System::Writer, ext->source)
- << writer_name << " backend does not support extension "
- << style::Code(ext->name);
+ diags.AddError(ext->source) << writer_name << " backend does not support extension "
+ << style::Code(ext->name);
return false;
}
}
diff --git a/src/tint/lang/wgsl/helpers/ir_program_test.h b/src/tint/lang/wgsl/helpers/ir_program_test.h
index 6a71008..5468ebc 100644
--- a/src/tint/lang/wgsl/helpers/ir_program_test.h
+++ b/src/tint/lang/wgsl/helpers/ir_program_test.h
@@ -35,7 +35,7 @@
#include <utility>
#include "gtest/gtest.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/number.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index 1cdbcac..34700c8 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -571,13 +571,12 @@
const ast::Function* Inspector::FindEntryPointByName(const std::string& name) {
auto* func = program_.AST().Functions().Find(program_.Symbols().Get(name));
if (!func) {
- diagnostics_.AddError(diag::System::Inspector, Source{}) << name << " was not found!";
+ diagnostics_.AddError(Source{}) << name << " was not found!";
return nullptr;
}
if (!func->IsEntryPoint()) {
- diagnostics_.AddError(diag::System::Inspector, Source{})
- << name << " is not an entry point!";
+ diagnostics_.AddError(Source{}) << name << " is not an entry point!";
return nullptr;
}
@@ -1029,17 +1028,6 @@
std::unordered_set<BindingPoint> seen = {};
- auto sample_type_for_call_and_type = [](wgsl::BuiltinFn builtin) {
- if (builtin == wgsl::BuiltinFn::kTextureNumLevels ||
- builtin == wgsl::BuiltinFn::kTextureDimensions ||
- builtin == wgsl::BuiltinFn::kTextureLoad) {
- return TextureQueryType::kTextureNumLevels;
- }
-
- TINT_ASSERT(builtin == wgsl::BuiltinFn::kTextureNumSamples);
- return TextureQueryType::kTextureNumSamples;
- };
-
Hashmap<const sem::Function*, Hashmap<const ast::Parameter*, TextureQueryType, 4>, 8>
fn_to_data;
@@ -1090,35 +1078,62 @@
tint::Switch(
call->Target(),
[&](const sem::BuiltinFn* builtin) {
- if (builtin->Fn() != wgsl::BuiltinFn::kTextureNumLevels &&
- builtin->Fn() != wgsl::BuiltinFn::kTextureNumSamples &&
- builtin->Fn() != wgsl::BuiltinFn::kTextureLoad &&
- // When textureDimension takes level as the input,
- // it requires calls to textureNumLevels to clamp mip levels.
- !(builtin->Fn() == wgsl::BuiltinFn::kTextureDimensions &&
- call->Declaration()->args.Length() > 1)) {
- return;
- }
+ auto queryTextureBuiltin = [&](TextureQueryType type,
+ const sem::Call* builtin_call,
+ const sem::Variable* texture_sem = nullptr) {
+ TINT_ASSERT(builtin_call);
+ if (!texture_sem) {
+ auto* texture_expr = builtin_call->Declaration()->args[0];
+ texture_sem = sem.GetVal(texture_expr)->RootIdentifier();
+ }
+ tint::Switch(
+ texture_sem, //
+ [&](const sem::GlobalVariable* global) {
+ save_if_needed(global, type);
+ },
+ [&](const sem::Parameter* param) {
+ record_function_param(fn, param->Declaration(), type);
+ },
+ TINT_ICE_ON_NO_MATCH);
+ };
- auto* texture_expr = call->Declaration()->args[0];
- auto* texture_sem = sem.GetVal(texture_expr)->RootIdentifier();
- TINT_ASSERT(texture_sem);
- if (builtin->Fn() == wgsl::BuiltinFn::kTextureLoad &&
- texture_sem->Type()
- ->UnwrapRef()
- ->IsAnyOf<core::type::MultisampledTexture,
- core::type::DepthMultisampledTexture>()) {
- return;
+ switch (builtin->Fn()) {
+ case wgsl::BuiltinFn::kTextureNumLevels: {
+ queryTextureBuiltin(TextureQueryType::kTextureNumLevels, call);
+ break;
+ }
+ case wgsl::BuiltinFn::kTextureDimensions: {
+ if (call->Declaration()->args.Length() <= 1) {
+ // When textureDimension only takes a texture as the input,
+ // it doesn't require calls to textureNumLevels to clamp mip levels.
+ return;
+ }
+ queryTextureBuiltin(TextureQueryType::kTextureNumLevels, call);
+ break;
+ }
+ case wgsl::BuiltinFn::kTextureLoad: {
+ auto* texture_expr = call->Declaration()->args[0];
+ auto* texture_sem = sem.GetVal(texture_expr)->RootIdentifier();
+ TINT_ASSERT(texture_sem);
+ if (texture_sem->Type()
+ ->UnwrapRef()
+ ->IsAnyOf<core::type::MultisampledTexture,
+ core::type::DepthMultisampledTexture>()) {
+ // When textureLoad takes a multisampled texture as the input,
+ // it doesn't require to query the mip level.
+ return;
+ }
+ queryTextureBuiltin(TextureQueryType::kTextureNumLevels, call,
+ texture_sem);
+ break;
+ }
+ case wgsl::BuiltinFn::kTextureNumSamples: {
+ queryTextureBuiltin(TextureQueryType::kTextureNumSamples, call);
+ break;
+ }
+ default:
+ return;
}
-
- auto type = sample_type_for_call_and_type(builtin->Fn());
- tint::Switch(
- texture_sem, //
- [&](const sem::GlobalVariable* global) { save_if_needed(global, type); },
- [&](const sem::Parameter* param) {
- record_function_param(fn, param->Declaration(), type);
- },
- TINT_ICE_ON_NO_MATCH);
},
[&](const sem::Function* func) {
// A function call, check to see if any params needed to be tracked back to a
diff --git a/src/tint/lang/wgsl/ir_roundtrip_fuzz.cc b/src/tint/lang/wgsl/ir_roundtrip_fuzz.cc
index 0265906..47af44a 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_fuzz.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_fuzz.cc
@@ -30,7 +30,7 @@
#include <iostream>
#include "src/tint/cmd/fuzz/ir/fuzz.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/wgsl/reader/lower/lower.h"
#include "src/tint/lang/wgsl/reader/parser/parser.h"
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index ac07621..39c7ca9 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -29,7 +29,7 @@
#include "gtest/gtest.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.h"
#include "src/tint/lang/wgsl/reader/reader.h"
#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
diff --git a/src/tint/lang/wgsl/ls/diagnostics.cc b/src/tint/lang/wgsl/ls/diagnostics.cc
index 58ed542..98ff03c 100644
--- a/src/tint/lang/wgsl/ls/diagnostics.cc
+++ b/src/tint/lang/wgsl/ls/diagnostics.cc
@@ -49,8 +49,6 @@
d.severity = lsp::DiagnosticSeverity::kWarning;
break;
case diag::Severity::Error:
- case diag::Severity::InternalCompilerError:
- case diag::Severity::Fatal:
d.severity = lsp::DiagnosticSeverity::kError;
break;
}
diff --git a/src/tint/lang/wgsl/program/program.cc b/src/tint/lang/wgsl/program/program.cc
index c649781..c1dfffb 100644
--- a/src/tint/lang/wgsl/program/program.cc
+++ b/src/tint/lang/wgsl/program/program.cc
@@ -81,7 +81,7 @@
// If the builder claims to be invalid, then we really should have an error
// message generated. If we find a situation where the program is not valid
// and there are no errors reported, add one here.
- diagnostics_.AddError(diag::System::Program, Source{}) << "invalid program generated";
+ diagnostics_.AddError(Source{}) << "invalid program generated";
}
}
diff --git a/src/tint/lang/wgsl/program/program_test.cc b/src/tint/lang/wgsl/program/program_test.cc
index 2572ca5..d5f2bb3 100644
--- a/src/tint/lang/wgsl/program/program_test.cc
+++ b/src/tint/lang/wgsl/program/program_test.cc
@@ -93,7 +93,7 @@
}
TEST_F(ProgramTest, DiagnosticsMove) {
- Diagnostics().AddError(diag::System::Program, Source{}) << "an error message";
+ Diagnostics().AddError(Source{}) << "an error message";
Program program_a(std::move(*this));
EXPECT_FALSE(program_a.IsValid());
diff --git a/src/tint/lang/wgsl/reader/parser/parser.cc b/src/tint/lang/wgsl/reader/parser/parser.cc
index e9eee00..3eddee4 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.cc
+++ b/src/tint/lang/wgsl/reader/parser/parser.cc
@@ -244,28 +244,27 @@
Parser::Failure::Errored Parser::AddError(const Source& source, std::string_view err) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddError(diag::System::Reader, source) << err;
+ builder_.Diagnostics().AddError(source) << err;
}
return Failure::kErrored;
}
Parser::Failure::Errored Parser::AddError(const Source& source, StyledText&& err) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddError(diag::System::Reader, source) << std::move(err);
+ builder_.Diagnostics().AddError(source) << std::move(err);
}
return Failure::kErrored;
}
void Parser::AddNote(const Source& source, std::string_view err) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddNote(diag::System::Reader, source) << err;
+ builder_.Diagnostics().AddNote(source) << err;
}
}
void Parser::deprecated(const Source& source, std::string_view msg) {
if (silence_diags_ == 0) {
- builder_.Diagnostics().AddWarning(diag::System::Reader, source)
- << "use of deprecated language feature: " << msg;
+ builder_.Diagnostics().AddWarning(source) << "use of deprecated language feature: " << msg;
}
}
diff --git a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
index 4feffb8..9933ed1 100644
--- a/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
+++ b/src/tint/lang/wgsl/reader/program_to_ir/program_to_ir.cc
@@ -200,9 +200,7 @@
~ControlStackScope() { impl_->control_stack_.Pop(); }
};
- diag::Diagnostic& AddError(const Source& source) {
- return diagnostics_.AddError(tint::diag::System::IR, source);
- }
+ diag::Diagnostic& AddError(const Source& source) { return diagnostics_.AddError(source); }
bool NeedTerminator() { return current_block_ && !current_block_->Terminator(); }
@@ -1353,7 +1351,7 @@
auto r = b.Build();
if (r != Success) {
diag::List err = std::move(r.Failure().reason);
- err.AddNote(diag::System::IR, Source{}) << "AST:\n" + Program::printer(program);
+ err.AddNote(Source{}) << "AST:\n" + Program::printer(program);
return Failure{err};
}
diff --git a/src/tint/lang/wgsl/reader/reader.cc b/src/tint/lang/wgsl/reader/reader.cc
index f2e20be..ed8009a 100644
--- a/src/tint/lang/wgsl/reader/reader.cc
+++ b/src/tint/lang/wgsl/reader/reader.cc
@@ -41,8 +41,7 @@
if (TINT_UNLIKELY(file->content.data.size() >
static_cast<size_t>(std::numeric_limits<uint32_t>::max()))) {
ProgramBuilder b;
- b.Diagnostics().AddError(tint::diag::System::Reader, Source{})
- << "WGSL source must be 0xffffffff bytes or fewer";
+ b.Diagnostics().AddError(tint::Source{}) << "WGSL source must be 0xffffffff bytes or fewer";
return Program(std::move(b));
}
Parser parser(file);
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index 7e2db61..36f97ba 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -133,12 +133,12 @@
/// @returns a new error diagnostic with the given source.
diag::Diagnostic& AddError(diag::List& diagnostics, const Source& source) {
- return diagnostics.AddError(diag::System::Resolver, source);
+ return diagnostics.AddError(source);
}
/// @returns a new note diagnostic with the given source.
diag::Diagnostic& AddNote(diag::List& diagnostics, const Source& source) {
- return diagnostics.AddNote(diag::System::Resolver, source);
+ return diagnostics.AddNote(source);
}
/// DependencyScanner is used to traverse a module to build the list of
diff --git a/src/tint/lang/wgsl/resolver/function_validation_test.cc b/src/tint/lang/wgsl/resolver/function_validation_test.cc
index 764af82..0abe53b 100644
--- a/src/tint/lang/wgsl/resolver/function_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/function_validation_test.cc
@@ -255,12 +255,12 @@
auto* var = Var("a", ty.i32(), Expr(2_i));
Func(Source{{12, 34}}, "func", tint::Empty, ty.i32(),
- Vector{
- Decl(var),
- });
+ Block(Source{Source::Range{{45, 56}, {78, 90}}}, Vector{
+ Decl(var),
+ }));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: missing return at end of function)");
+ EXPECT_EQ(r()->error(), R"(78:89 error: missing return at end of function)");
}
TEST_F(ResolverFunctionValidationTest, VoidFunctionEndWithoutReturnStatementEmptyBody_Pass) {
@@ -274,10 +274,11 @@
TEST_F(ResolverFunctionValidationTest, FunctionEndWithoutReturnStatementEmptyBody_Fail) {
// fn func() -> int {}
- Func(Source{{12, 34}}, "func", tint::Empty, ty.i32(), tint::Empty);
+ Func(Source{{12, 34}}, "func", tint::Empty, ty.i32(),
+ Block(Source{Source::Range{{45, 56}, {78, 90}}}, tint::Empty));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), R"(12:34 error: missing return at end of function)");
+ EXPECT_EQ(r()->error(), R"(78:89 error: missing return at end of function)");
}
TEST_F(ResolverFunctionValidationTest, FunctionTypeMustMatchReturnStatementType_Pass) {
@@ -1022,7 +1023,7 @@
for (int i = 0; i < 256; i++) {
params.Push(Param("param_" + std::to_string(i), ty.i32()));
}
- Func(Source{{12, 34}}, "f", params, ty.void_(), tint::Empty);
+ Func(Ident(Source{{12, 34}}, "f"), params, ty.void_(), tint::Empty);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), R"(12:34 error: function declares 256 parameters, maximum is 255)");
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index b1a1775..fad6159 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -1156,9 +1156,10 @@
}
if (auto* str = return_type->As<core::type::Struct>()) {
- if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, str, decl->source)) {
- AddNote(decl->source) << "while instantiating return type for "
- << decl->name->symbol.NameView();
+ if (!ApplyAddressSpaceUsageToType(core::AddressSpace::kUndefined, str,
+ decl->return_type->source)) {
+ AddNote(decl->return_type->source)
+ << "while instantiating return type for " << decl->name->symbol.NameView();
return nullptr;
}
@@ -5048,22 +5049,21 @@
TINT_ICE() << msg;
}
diag::Diagnostic err{};
- err.severity = diag::Severity::InternalCompilerError;
- err.system = diag::System::Resolver;
+ err.severity = diag::Severity::Error;
err.source = source;
diagnostics_.Add(std::move(err)) << msg;
}
diag::Diagnostic& Resolver::AddError(const Source& source) const {
- return diagnostics_.AddError(diag::System::Resolver, source);
+ return diagnostics_.AddError(source);
}
diag::Diagnostic& Resolver::AddWarning(const Source& source) const {
- return diagnostics_.AddWarning(diag::System::Resolver, source);
+ return diagnostics_.AddWarning(source);
}
diag::Diagnostic& Resolver::AddNote(const Source& source) const {
- return diagnostics_.AddNote(diag::System::Resolver, source);
+ return diagnostics_.AddNote(source);
}
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/sem_helper.cc b/src/tint/lang/wgsl/resolver/sem_helper.cc
index fbd74a9..1fe3934 100644
--- a/src/tint/lang/wgsl/resolver/sem_helper.cc
+++ b/src/tint/lang/wgsl/resolver/sem_helper.cc
@@ -228,14 +228,14 @@
}
diag::Diagnostic& SemHelper::AddError(const Source& source) const {
- return builder_->Diagnostics().AddError(diag::System::Resolver, source);
+ return builder_->Diagnostics().AddError(source);
}
diag::Diagnostic& SemHelper::AddWarning(const Source& source) const {
- return builder_->Diagnostics().AddWarning(diag::System::Resolver, source);
+ return builder_->Diagnostics().AddWarning(source);
}
diag::Diagnostic& SemHelper::AddNote(const Source& source) const {
- return builder_->Diagnostics().AddNote(diag::System::Resolver, source);
+ return builder_->Diagnostics().AddNote(source);
}
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/uniformity.cc b/src/tint/lang/wgsl/resolver/uniformity.cc
index 818e5e1..776d424 100644
--- a/src/tint/lang/wgsl/resolver/uniformity.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity.cc
@@ -130,6 +130,7 @@
kFunctionCallArgumentContents,
kFunctionCallPointerArgumentResult,
kFunctionCallReturnValue,
+ kFunctionPointerParameterContents,
};
/// The type of the node.
@@ -214,13 +215,15 @@
parameters[i].sem = sem;
parameters[i].value = CreateNode({"param_", param_name});
+ parameters[i].value->ast = param;
if (sem->Type()->Is<core::type::Pointer>()) {
// Create extra nodes for a pointer parameter's initial contents and its contents
// when the function returns.
parameters[i].ptr_input_contents =
- CreateNode({"ptrparam_", param_name, "_input_contents"});
+ CreateNode({"ptrparam_", param_name, "_input_contents"}, param);
parameters[i].ptr_output_contents =
CreateNode({"ptrparam_", param_name, "_output_contents"});
+ parameters[i].ptr_input_contents->type = Node::kFunctionPointerParameterContents;
variables.Set(sem, parameters[i].ptr_input_contents);
local_var_decls.Add(sem);
} else {
@@ -1822,14 +1825,17 @@
Traverse(required_to_be_uniform);
// Get the source of the non-uniform value.
- auto* non_uniform_source = may_be_non_uniform->visited_from;
+ auto* non_uniform_source = may_be_non_uniform;
+ if (non_uniform_source == function.may_be_non_uniform) {
+ non_uniform_source = non_uniform_source->visited_from;
+ }
TINT_ASSERT(non_uniform_source);
// Show where the non-uniform value results in non-uniform control flow.
auto* control_flow = TraceBackAlongPathUntil(
non_uniform_source, [](Node* node) { return node->affects_control_flow; });
if (control_flow) {
- diagnostics_.AddNote(diag::System::Resolver, control_flow->ast->source)
+ diagnostics_.AddNote(control_flow->ast->source)
<< "control flow depends on possibly non-uniform value";
// TODO(jrprice): There are cases where the function with uniformity requirements is not
// actually inside this control flow construct, for example:
@@ -1859,11 +1865,10 @@
return "";
}
};
- auto param_type = [&](const sem::Parameter* param) {
- if (ast::HasAttribute<ast::BuiltinAttribute>(param->Declaration()->attributes)) {
+ auto param_type = [&](const ast::Parameter* param) {
+ if (ast::HasAttribute<ast::BuiltinAttribute>(param->attributes)) {
return "builtin ";
- } else if (ast::HasAttribute<ast::LocationAttribute>(
- param->Declaration()->attributes)) {
+ } else if (ast::HasAttribute<ast::LocationAttribute>(param->attributes)) {
return "user-defined input ";
} else {
return "parameter ";
@@ -1877,18 +1882,31 @@
auto* var = sem_.GetVal(ident)->UnwrapLoad()->As<sem::VariableUser>()->Variable();
if (auto* param = var->As<sem::Parameter>()) {
auto* func = param->Owner()->As<sem::Function>();
- diagnostics_.AddNote(diag::System::Resolver, ident->source)
- << param_type(param) << "'" << NameFor(ident) << "' of '" << NameFor(func)
- << "' may be non-uniform";
+ diagnostics_.AddNote(ident->source)
+ << param_type(param->Declaration()) << "'" << NameFor(ident) << "' of '"
+ << NameFor(func) << "' may be non-uniform";
} else {
- diagnostics_.AddNote(diag::System::Resolver, ident->source)
+ diagnostics_.AddNote(ident->source)
<< "reading from " << var_type(var) << "'" << NameFor(ident)
<< "' may result in a non-uniform value";
}
},
+ [&](const ast::Parameter* p) {
+ auto* param = sem_.Get(p);
+ auto* func = param->Owner()->As<sem::Function>();
+ if (non_uniform_source->type == Node::kFunctionPointerParameterContents) {
+ diagnostics_.AddNote(p->source)
+ << "parameter '" << NameFor(p) << "' of '" << NameFor(func)
+ << "' may point to a non-uniform value";
+ } else {
+ diagnostics_.AddNote(p->source)
+ << param_type(p) << "'" << NameFor(p) << "' of '" << NameFor(func)
+ << "' may be non-uniform";
+ }
+ },
[&](const ast::Variable* v) {
auto* var = sem_.Get(v);
- diagnostics_.AddNote(diag::System::Resolver, v->source)
+ diagnostics_.AddNote(v->source)
<< "reading from " << var_type(var) << "'" << NameFor(v)
<< "' may result in a non-uniform value";
},
@@ -1896,14 +1914,14 @@
auto target_name = NameFor(c->target);
switch (non_uniform_source->type) {
case Node::kFunctionCallReturnValue: {
- diagnostics_.AddNote(diag::System::Resolver, c->source)
+ diagnostics_.AddNote(c->source)
<< "return value of '" + target_name + "' may be non-uniform";
break;
}
case Node::kFunctionCallArgumentContents: {
auto* arg = c->args[non_uniform_source->arg_index];
auto* var = sem_.GetVal(arg)->RootIdentifier();
- diagnostics_.AddNote(diag::System::Resolver, var->Declaration()->source)
+ diagnostics_.AddNote(var->Declaration()->source)
<< "reading from " << var_type(var) << "'" << NameFor(var)
<< "' may result in a non-uniform value";
break;
@@ -1911,14 +1929,13 @@
case Node::kFunctionCallArgumentValue: {
auto* arg = c->args[non_uniform_source->arg_index];
// TODO(jrprice): Which output? (return value vs another pointer argument).
- diagnostics_.AddNote(diag::System::Resolver, arg->source)
+ diagnostics_.AddNote(arg->source)
<< "passing non-uniform pointer to '" << target_name
<< "' may produce a non-uniform output";
break;
}
case Node::kFunctionCallPointerArgumentResult: {
- diagnostics_.AddNote(diag::System::Resolver,
- c->args[non_uniform_source->arg_index]->source)
+ diagnostics_.AddNote(c->args[non_uniform_source->arg_index]->source)
<< "contents of pointer may become non-uniform after calling '"
<< target_name << "'";
break;
@@ -1930,8 +1947,7 @@
}
},
[&](const ast::Expression* e) {
- diagnostics_.AddNote(diag::System::Resolver, e->source)
- << "result of expression may be non-uniform";
+ diagnostics_.AddNote(e->source) << "result of expression may be non-uniform";
}, //
TINT_ICE_ON_NO_MATCH);
}
@@ -1945,7 +1961,6 @@
auto report = [&](Source source, std::string msg, bool note) {
diag::Diagnostic error{};
error.severity = note ? diag::Severity::Note : wgsl::ToSeverity(severity);
- error.system = diag::System::Resolver;
error.source = source;
error.message = msg;
diagnostics_.Add(std::move(error));
diff --git a/src/tint/lang/wgsl/resolver/uniformity_test.cc b/src/tint/lang/wgsl/resolver/uniformity_test.cc
index c4a5000..9c15fa6 100644
--- a/src/tint/lang/wgsl/resolver/uniformity_test.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity_test.cc
@@ -433,9 +433,9 @@
if (i == 0) {
^^
-test:5:7 note: parameter 'i' of 'foo' may be non-uniform
- if (i == 0) {
- ^
+test:4:8 note: parameter 'i' of 'foo' may be non-uniform
+fn foo(i : i32) {
+ ^
test:11:7 note: possibly non-uniform value passed here
foo(rw);
@@ -3744,8 +3744,8 @@
if (*p == 0) {
^^
-test:5:8 note: parameter 'p' of 'bar' may be non-uniform
- if (*p == 0) {
+test:4:8 note: parameter 'p' of 'bar' may point to a non-uniform value
+fn bar(p : ptr<function, i32>) {
^
test:12:7 note: possibly non-uniform value passed via pointer here
@@ -3875,8 +3875,8 @@
if (*p == 0) {
^^
-test:5:8 note: parameter 'p' of 'bar' may be non-uniform
- if (*p == 0) {
+test:4:8 note: parameter 'p' of 'bar' may point to a non-uniform value
+fn bar(p : ptr<function, i32>) {
^
test:13:7 note: possibly non-uniform value passed via pointer here
@@ -3916,8 +3916,8 @@
if (*p == 0) {
^^
-test:5:8 note: parameter 'p' of 'bar' may be non-uniform
- if (*p == 0) {
+test:4:8 note: parameter 'p' of 'bar' may point to a non-uniform value
+fn bar(p : ptr<function, i32>) {
^
test:12:7 note: possibly non-uniform value passed via pointer here
@@ -4074,8 +4074,8 @@
if (*p == 0) {
^^
-test:5:8 note: parameter 'p' of 'zoo' may be non-uniform
- if (*p == 0) {
+test:4:8 note: parameter 'p' of 'zoo' may point to a non-uniform value
+fn zoo(p : ptr<function, i32>) {
^
test:11:7 note: possibly non-uniform value passed via pointer here
@@ -4162,8 +4162,8 @@
if (*p == 0) {
^^
-test:6:8 note: parameter 'p' of 'zoo' may be non-uniform
- if (*p == 0) {
+test:5:8 note: parameter 'p' of 'zoo' may point to a non-uniform value
+fn zoo(p : ptr<function, i32>) {
^
test:12:7 note: possibly non-uniform value passed via pointer here
@@ -8032,8 +8032,8 @@
if (*p == 0) {
^^
-test:7:8 note: parameter 'p' of 'bar' may be non-uniform
- if (*p == 0) {
+test:6:8 note: parameter 'p' of 'bar' may point to a non-uniform value
+fn bar(p : ptr<function, i32>) -> i32 {
^
test:15:9 note: possibly non-uniform value passed via pointer here
@@ -8108,8 +8108,8 @@
if (*p == 0) {
^^
-test:7:8 note: parameter 'p' of 'bar' may be non-uniform
- if (*p == 0) {
+test:6:8 note: parameter 'p' of 'bar' may point to a non-uniform value
+fn bar(p : ptr<function, i32>) -> i32 {
^
test:15:9 note: possibly non-uniform value passed via pointer here
@@ -8181,9 +8181,9 @@
if (*p == 0) {
^^
-test:10:8 note: parameter 'p' of 'b' may be non-uniform
- if (*p == 0) {
- ^
+test:9:6 note: parameter 'p' of 'b' may point to a non-uniform value
+fn b(p : ptr<function, i32>) -> i32 {
+ ^
test:19:22 note: possibly non-uniform value passed via pointer here
arr[a(&i)] = arr[b(&i)];
@@ -8222,9 +8222,9 @@
if (cond == 0) {
^^
-test:5:7 note: parameter 'cond' of 'bar' may be non-uniform
- if (cond == 0) {
- ^^^^
+test:4:8 note: parameter 'cond' of 'bar' may be non-uniform
+fn bar(cond : i32) -> i32 {
+ ^^^^
test:13:11 note: possibly non-uniform value passed here
arr[bar(non_uniform)] = 0;
@@ -8263,9 +8263,9 @@
if (cond == 0) {
^^
-test:5:7 note: parameter 'cond' of 'bar' may be non-uniform
- if (cond == 0) {
- ^^^^
+test:4:8 note: parameter 'cond' of 'bar' may be non-uniform
+fn bar(cond : i32) -> i32 {
+ ^^^^
test:13:14 note: possibly non-uniform value passed here
*&(arr[bar(non_uniform)]) = 0;
@@ -8304,9 +8304,9 @@
if (cond == 0) {
^^
-test:5:7 note: parameter 'cond' of 'bar' may be non-uniform
- if (cond == 0) {
- ^^^^
+test:4:8 note: parameter 'cond' of 'bar' may be non-uniform
+fn bar(cond : i32) -> i32 {
+ ^^^^
test:13:14 note: possibly non-uniform value passed here
(&arr)[bar(non_uniform)] = 0;
@@ -8345,9 +8345,9 @@
if (cond == 0) {
^^
-test:5:7 note: parameter 'cond' of 'bar' may be non-uniform
- if (cond == 0) {
- ^^^^
+test:4:8 note: parameter 'cond' of 'bar' may be non-uniform
+fn bar(cond : i32) -> i32 {
+ ^^^^
test:13:14 note: possibly non-uniform value passed here
(&(arr[bar(non_uniform)])).y = 0;
@@ -8418,9 +8418,9 @@
if (*p == 0) {
^^
-test:10:8 note: parameter 'p' of 'b' may be non-uniform
- if (*p == 0) {
- ^
+test:9:6 note: parameter 'p' of 'b' may point to a non-uniform value
+fn b(p : ptr<function, i32>) -> i32 {
+ ^
test:19:23 note: possibly non-uniform value passed via pointer here
arr[a(&i)] += arr[b(&i)];
@@ -9988,9 +9988,9 @@
if (a == 42) {
^^
-test:5:7 note: parameter 'a' of 'zoo' may be non-uniform
- if (a == 42) {
- ^
+test:4:8 note: parameter 'a' of 'zoo' may be non-uniform
+fn zoo(a : i32) {
+ ^
test:11:7 note: possibly non-uniform value passed here
zoo(b);
@@ -10096,5 +10096,52 @@
)");
}
+TEST_F(UniformityAnalysisTest, Error_PointerParameterContentsRequiresUniformity_AfterControlFlow) {
+ // Test that we can find the correct source of uniformity inside a function called with a
+ // pointer parameter, when the pointer contents is used after control flow that introduces extra
+ // nodes for merging the pointer contents.
+ std::string src = R"(
+var<private> non_uniform : i32;
+
+fn foo(p : ptr<function, i32>) {
+ for (var i = 0; i < 3; i++) {
+ continue;
+ }
+ if (*p == 0) {
+ return;
+ }
+ _ = dpdx(1.0);
+}
+
+fn main() {
+ var f = non_uniform;
+ foo(&f);
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(error_,
+ R"(test:11:7 error: 'dpdx' must only be called from uniform control flow
+ _ = dpdx(1.0);
+ ^^^^^^^^^
+
+test:8:3 note: control flow depends on possibly non-uniform value
+ if (*p == 0) {
+ ^^
+
+test:4:8 note: parameter 'p' of 'foo' may point to a non-uniform value
+fn foo(p : ptr<function, i32>) {
+ ^
+
+test:16:7 note: possibly non-uniform value passed via pointer here
+ foo(&f);
+ ^^
+
+test:15:11 note: reading from module-scope private variable 'non_uniform' may result in a non-uniform value
+ var f = non_uniform;
+ ^^^^^^^^^^^
+)");
+}
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 1c110f8..7963482 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -180,15 +180,15 @@
Validator::~Validator() = default;
diag::Diagnostic& Validator::AddError(const Source& source) const {
- return diagnostics_.AddError(diag::System::Resolver, source);
+ return diagnostics_.AddError(source);
}
diag::Diagnostic& Validator::AddWarning(const Source& source) const {
- return diagnostics_.AddWarning(diag::System::Resolver, source);
+ return diagnostics_.AddWarning(source);
}
diag::Diagnostic& Validator::AddNote(const Source& source) const {
- return diagnostics_.AddNote(diag::System::Resolver, source);
+ return diagnostics_.AddNote(source);
}
diag::Diagnostic* Validator::MaybeAddDiagnostic(wgsl::DiagnosticRule rule,
@@ -197,7 +197,6 @@
if (severity != wgsl::DiagnosticSeverity::kOff) {
diag::Diagnostic d{};
d.severity = ToSeverity(severity);
- d.system = diag::System::Resolver;
d.source = source;
return &diagnostics_.Add(std::move(d));
}
@@ -1097,8 +1096,8 @@
}
if (decl->params.Length() > kMaxFunctionParameters) {
- AddError(decl->source) << "function declares " << decl->params.Length()
- << " parameters, maximum is " << kMaxFunctionParameters;
+ AddError(decl->name->source) << "function declares " << decl->params.Length()
+ << " parameters, maximum is " << kMaxFunctionParameters;
return false;
}
@@ -1115,7 +1114,9 @@
behaviors = sem_.Get(last)->Behaviors();
}
if (behaviors.Contains(sem::Behavior::kNext)) {
- AddError(decl->source) << "missing return at end of function";
+ auto end_source = decl->body->source.End();
+ end_source.range.begin.column--;
+ AddError(end_source) << "missing return at end of function";
return false;
}
} else if (TINT_UNLIKELY(IsValidationEnabled(
diff --git a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
index 8ad212a..710c70a 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
@@ -338,7 +338,7 @@
void ASTPrinter::EmitImageFormat(StringStream& out, const core::TexelFormat fmt) {
switch (fmt) {
case core::TexelFormat::kUndefined:
- diagnostics_.AddError(diag::System::Writer, Source{}) << "unknown image format";
+ diagnostics_.AddError(Source{}) << "unknown image format";
break;
default:
out << fmt;
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index 68d4db1..5e601cc 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -32,7 +32,7 @@
#include "src/tint/lang/core/access.h"
#include "src/tint/lang/core/address_space.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/texel_format.h"
#include "src/tint/lang/core/type/storage_texture.h"
#include "src/tint/lang/core/type/texture_dimension.h"
diff --git a/src/tint/lang/wgsl/writer/raise/ptr_to_ref_test.cc b/src/tint/lang/wgsl/writer/raise/ptr_to_ref_test.cc
index 3862749..40f02f4 100644
--- a/src/tint/lang/wgsl/writer/raise/ptr_to_ref_test.cc
+++ b/src/tint/lang/wgsl/writer/raise/ptr_to_ref_test.cc
@@ -32,7 +32,7 @@
#include "gtest/gtest.h"
#include "src/tint/lang/core/ir/builder.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/validator.h"
namespace tint::wgsl::writer::raise {
@@ -65,10 +65,7 @@
}
/// @returns the transformed module as a disassembled string
- std::string str() {
- core::ir::Disassembler dis(mod);
- return "\n" + dis.Disassemble().Plain();
- }
+ std::string str() { return "\n" + core::ir::Disassemble(mod).Plain(); }
protected:
/// The test IR module.
diff --git a/src/tint/lang/wgsl/writer/raise/rename_conflicts_test.cc b/src/tint/lang/wgsl/writer/raise/rename_conflicts_test.cc
index 7be25fc..d5a25db 100644
--- a/src/tint/lang/wgsl/writer/raise/rename_conflicts_test.cc
+++ b/src/tint/lang/wgsl/writer/raise/rename_conflicts_test.cc
@@ -32,7 +32,7 @@
#include "gtest/gtest.h"
#include "src/tint/lang/core/ir/builder.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/core/type/matrix.h"
@@ -65,10 +65,7 @@
}
/// @returns the transformed module as a disassembled string
- std::string str() {
- core::ir::Disassembler dis(mod);
- return "\n" + dis.Disassemble().Plain();
- }
+ std::string str() { return "\n" + core::ir::Disassemble(mod).Plain(); }
protected:
/// The test IR module.
diff --git a/src/tint/lang/wgsl/writer/writer_test.cc b/src/tint/lang/wgsl/writer/writer_test.cc
index ca2f339..d9e573c 100644
--- a/src/tint/lang/wgsl/writer/writer_test.cc
+++ b/src/tint/lang/wgsl/writer/writer_test.cc
@@ -32,7 +32,7 @@
#include <string_view>
#include "gtest/gtest.h"
-#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/disassembly.h"
#include "src/tint/lang/core/ir/ir_helper_test.h"
#include "src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.h"
#include "src/tint/lang/wgsl/writer/ir_to_program/program_options.h"
diff --git a/src/tint/utils/command/command_posix.cc b/src/tint/utils/command/command_posix.cc
index 61bb0b1..f3c30de 100644
--- a/src/tint/utils/command/command_posix.cc
+++ b/src/tint/utils/command/command_posix.cc
@@ -29,6 +29,7 @@
#include "src/tint/utils/command/command.h"
+#include <limits.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -119,7 +120,19 @@
return s.st_mode & S_IXUSR;
}
+std::string GetCWD() {
+ char cwd[PATH_MAX] = "";
+ [[maybe_unused]] auto res = getcwd(cwd, sizeof(cwd));
+ return cwd;
+}
+
std::string FindExecutable(const std::string& name) {
+ if (name.length() >= 1 && name[0] != '/') {
+ auto in_cwd = GetCWD() + "/" + name;
+ if (ExecutableExists(in_cwd)) {
+ return in_cwd;
+ }
+ }
if (ExecutableExists(name)) {
return name;
}
diff --git a/src/tint/utils/command/command_windows.cc b/src/tint/utils/command/command_windows.cc
index 2916d9a..a6a577b 100644
--- a/src/tint/utils/command/command_windows.cc
+++ b/src/tint/utils/command/command_windows.cc
@@ -145,7 +145,20 @@
return false;
}
+std::string GetCWD() {
+ char cwd[MAX_PATH] = "";
+ GetCurrentDirectoryA(sizeof(cwd), cwd);
+ return cwd;
+}
+
std::string FindExecutable(const std::string& name) {
+ auto in_cwd = GetCWD() + "/" + name;
+ if (ExecutableExists(in_cwd)) {
+ return in_cwd;
+ }
+ if (ExecutableExists(in_cwd + ".exe")) {
+ return in_cwd + ".exe";
+ }
if (ExecutableExists(name)) {
return name;
}
diff --git a/src/tint/utils/diagnostic/diagnostic.h b/src/tint/utils/diagnostic/diagnostic.h
index 69f77d2..6471b5a 100644
--- a/src/tint/utils/diagnostic/diagnostic.h
+++ b/src/tint/utils/diagnostic/diagnostic.h
@@ -28,8 +28,8 @@
#ifndef SRC_TINT_UTILS_DIAGNOSTIC_DIAGNOSTIC_H_
#define SRC_TINT_UTILS_DIAGNOSTIC_DIAGNOSTIC_H_
+#include <cstdint>
#include <memory>
-#include <ostream>
#include <string>
#include <utility>
@@ -41,36 +41,13 @@
namespace tint::diag {
/// Severity is an enumerator of diagnostic severities.
-enum class Severity { Note, Warning, Error, InternalCompilerError, Fatal };
+enum class Severity : uint8_t { Note, Warning, Error };
/// @return true iff `a` is more than, or of equal severity to `b`
inline bool operator>=(Severity a, Severity b) {
return static_cast<int>(a) >= static_cast<int>(b);
}
-/// System is an enumerator of Tint systems that can be the originator of a diagnostic message.
-enum class System {
- AST,
- Builtin,
- Clone,
- Constant,
- Inspector,
- Intrinsics,
- IR,
- Program,
- ProgramBuilder,
- Reader,
- Resolver,
- Semantic,
- Symbol,
- Test,
- Transform,
- Type,
- Utils,
- Writer,
- Unknown,
-};
-
/// Diagnostic holds all the information for a single compiler diagnostic
/// message.
class Diagnostic {
@@ -99,8 +76,6 @@
Source source;
/// message is the text associated with the diagnostic.
StyledText message;
- /// system is the Tint system that raised the diagnostic.
- System system;
/// A shared pointer to a Source::File. Only used if the diagnostic Source
/// points to a file that was created specifically for this diagnostic
/// (usually an ICE).
@@ -178,61 +153,38 @@
}
/// Adds the note message with the given Source to the end of this list.
- /// @param system the system raising the note message
/// @param source the source of the note diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddNote(System system, const Source& source) {
+ diag::Diagnostic& AddNote(const Source& source) {
diag::Diagnostic note{};
note.severity = diag::Severity::Note;
- note.system = system;
note.source = source;
return Add(std::move(note));
}
/// Adds the warning message with the given Source to the end of this list.
- /// @param system the system raising the warning message
/// @param source the source of the warning diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddWarning(System system, const Source& source) {
+ diag::Diagnostic& AddWarning(const Source& source) {
diag::Diagnostic warning{};
warning.severity = diag::Severity::Warning;
- warning.system = system;
warning.source = source;
return Add(std::move(warning));
}
/// Adds the error message with the given Source to the end of this list.
- /// @param system the system raising the error message
/// @param source the source of the error diagnostic
/// @returns a reference to the new diagnostic.
/// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddError(System system, const Source& source) {
+ diag::Diagnostic& AddError(const Source& source) {
diag::Diagnostic error{};
error.severity = diag::Severity::Error;
- error.system = system;
error.source = source;
return Add(std::move(error));
}
- /// Adds an internal compiler error message to the end of this list.
- /// @param system the system raising the error message
- /// @param source the source of the internal compiler error
- /// @param file the Source::File owned by this diagnostic
- /// @returns a reference to the new diagnostic.
- /// @note The returned reference must not be used after the list is mutated again.
- diag::Diagnostic& AddIce(System system,
- const Source& source,
- std::shared_ptr<Source::File> file) {
- diag::Diagnostic ice{};
- ice.severity = diag::Severity::InternalCompilerError;
- ice.system = system;
- ice.source = source;
- ice.owned_file = std::move(file);
- return Add(std::move(ice));
- }
-
/// @returns true iff the diagnostic list contains errors diagnostics (or of
/// higher severity).
bool ContainsErrors() const { return error_count_ > 0; }
diff --git a/src/tint/utils/diagnostic/diagnostic_test.cc b/src/tint/utils/diagnostic/diagnostic_test.cc
index 3d76f1e..9a00566 100644
--- a/src/tint/utils/diagnostic/diagnostic_test.cc
+++ b/src/tint/utils/diagnostic/diagnostic_test.cc
@@ -36,7 +36,7 @@
TEST(DiagListTest, CtorInitializerList) {
Diagnostic err_a, err_b;
err_a.severity = Severity::Error;
- err_b.severity = Severity::Fatal;
+ err_b.severity = Severity::Warning;
List list{err_a, err_b};
EXPECT_EQ(list.Count(), 2u);
}
@@ -44,7 +44,7 @@
TEST(DiagListTest, CtorVectorRef) {
Diagnostic err_a, err_b;
err_a.severity = Severity::Error;
- err_b.severity = Severity::Fatal;
+ err_b.severity = Severity::Warning;
List list{Vector{err_a, err_b}};
EXPECT_EQ(list.Count(), 2u);
}
diff --git a/src/tint/utils/diagnostic/formatter.cc b/src/tint/utils/diagnostic/formatter.cc
index 9fd279b..5b5c574 100644
--- a/src/tint/utils/diagnostic/formatter.cc
+++ b/src/tint/utils/diagnostic/formatter.cc
@@ -50,10 +50,6 @@
return "warning";
case Severity::Error:
return "error";
- case Severity::InternalCompilerError:
- return "internal compiler error";
- case Severity::Fatal:
- return "fatal";
}
return "";
}
@@ -127,10 +123,6 @@
case Severity::Error:
style = style::Error + style::Bold;
break;
- case Severity::Fatal:
- case Severity::InternalCompilerError:
- style = style::Fatal + style::Bold;
- break;
}
prefix.Push(TextAndStyle{ToString(diag.severity), style});
}
diff --git a/src/tint/utils/diagnostic/formatter_test.cc b/src/tint/utils/diagnostic/formatter_test.cc
index 6d77367..9fee7c9 100644
--- a/src/tint/utils/diagnostic/formatter_test.cc
+++ b/src/tint/utils/diagnostic/formatter_test.cc
@@ -36,12 +36,11 @@
namespace tint::diag {
namespace {
-Diagnostic Diag(Severity severity, Source source, std::string message, System system) {
+Diagnostic Diag(Severity severity, Source source, std::string message) {
Diagnostic d;
d.severity = severity;
d.source = source;
d.message = std::move(message);
- d.system = system;
return d;
}
@@ -62,47 +61,19 @@
public:
Source::File ascii_file{"file.name", ascii_content};
Source::File utf8_file{"file.name", utf8_content};
- Diagnostic ascii_diag_note = Diag(Severity::Note,
- Source{Source::Range{Source::Location{1, 14}}, &ascii_file},
- "purr",
- System::Test);
- Diagnostic ascii_diag_warn = Diag(Severity::Warning,
- Source{Source::Range{{2, 14}, {2, 18}}, &ascii_file},
- "grrr",
- System::Test);
- Diagnostic ascii_diag_err = Diag(Severity::Error,
- Source{Source::Range{{3, 16}, {3, 21}}, &ascii_file},
- "hiss",
- System::Test);
- Diagnostic ascii_diag_ice = Diag(Severity::InternalCompilerError,
- Source{Source::Range{{4, 16}, {4, 19}}, &ascii_file},
- "unreachable",
- System::Test);
- Diagnostic ascii_diag_fatal = Diag(Severity::Fatal,
- Source{Source::Range{{4, 16}, {4, 19}}, &ascii_file},
- "nothing",
- System::Test);
+ Diagnostic ascii_diag_note =
+ Diag(Severity::Note, Source{Source::Range{Source::Location{1, 14}}, &ascii_file}, "purr");
+ Diagnostic ascii_diag_warn =
+ Diag(Severity::Warning, Source{Source::Range{{2, 14}, {2, 18}}, &ascii_file}, "grrr");
+ Diagnostic ascii_diag_err =
+ Diag(Severity::Error, Source{Source::Range{{3, 16}, {3, 21}}, &ascii_file}, "hiss");
- Diagnostic utf8_diag_note = Diag(Severity::Note,
- Source{Source::Range{Source::Location{1, 15}}, &utf8_file},
- "purr",
- System::Test);
- Diagnostic utf8_diag_warn = Diag(Severity::Warning,
- Source{Source::Range{{2, 15}, {2, 19}}, &utf8_file},
- "grrr",
- System::Test);
- Diagnostic utf8_diag_err = Diag(Severity::Error,
- Source{Source::Range{{3, 15}, {3, 20}}, &utf8_file},
- "hiss",
- System::Test);
- Diagnostic utf8_diag_ice = Diag(Severity::InternalCompilerError,
- Source{Source::Range{{4, 15}, {4, 18}}, &utf8_file},
- "unreachable",
- System::Test);
- Diagnostic utf8_diag_fatal = Diag(Severity::Fatal,
- Source{Source::Range{{4, 15}, {4, 18}}, &utf8_file},
- "nothing",
- System::Test);
+ Diagnostic utf8_diag_note =
+ Diag(Severity::Note, Source{Source::Range{Source::Location{1, 15}}, &utf8_file}, "purr");
+ Diagnostic utf8_diag_warn =
+ Diag(Severity::Warning, Source{Source::Range{{2, 15}, {2, 19}}, &utf8_file}, "grrr");
+ Diagnostic utf8_diag_err =
+ Diag(Severity::Error, Source{Source::Range{{3, 15}, {3, 20}}, &utf8_file}, "hiss");
};
TEST_F(DiagFormatterTest, Simple) {
@@ -126,7 +97,7 @@
TEST_F(DiagFormatterTest, SimpleNoSource) {
Formatter fmt{{false, false, false, false}};
- auto diag = Diag(Severity::Note, Source{}, "no source!", System::Test);
+ auto diag = Diag(Severity::Note, Source{}, "no source!");
auto got = fmt.Format(List{diag}).Plain();
auto* expect = "no source!";
ASSERT_EQ(expect, got);
@@ -202,8 +173,8 @@
}
TEST_F(DiagFormatterTest, BasicWithMultiLine) {
- auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
- "multiline", System::Test);
+ auto multiline =
+ Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file}, "multiline");
Formatter fmt{{false, false, true, false}};
auto got = fmt.Format(List{multiline}).Plain();
auto* expect = R"(2:9: multiline
@@ -218,8 +189,8 @@
}
TEST_F(DiagFormatterTest, UnicodeWithMultiLine) {
- auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &utf8_file},
- "multiline", System::Test);
+ auto multiline =
+ Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &utf8_file}, "multiline");
Formatter fmt{{false, false, true, false}};
auto got = fmt.Format(List{multiline}).Plain();
auto* expect =
@@ -249,8 +220,8 @@
}
TEST_F(DiagFormatterTest, BasicWithMultiLineTab4) {
- auto multiline = Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file},
- "multiline", System::Test);
+ auto multiline =
+ Diag(Severity::Warning, Source{Source::Range{{2, 9}, {4, 15}}, &ascii_file}, "multiline");
Formatter fmt{{false, false, true, false, 4u}};
auto got = fmt.Format(List{multiline}).Plain();
auto* expect = R"(2:9: multiline
@@ -264,32 +235,10 @@
ASSERT_EQ(expect, got);
}
-TEST_F(DiagFormatterTest, ICE) {
- Formatter fmt{{}};
- auto got = fmt.Format(List{ascii_diag_ice}).Plain();
- auto* expect = R"(file.name:4:16 internal compiler error: unreachable
-the snail says ???
- ^^^
-
-)";
- ASSERT_EQ(expect, got);
-}
-
-TEST_F(DiagFormatterTest, Fatal) {
- Formatter fmt{{}};
- auto got = fmt.Format(List{ascii_diag_fatal}).Plain();
- auto* expect = R"(file.name:4:16 fatal: nothing
-the snail says ???
- ^^^
-
-)";
- ASSERT_EQ(expect, got);
-}
-
TEST_F(DiagFormatterTest, RangeOOB) {
Formatter fmt{{true, true, true, true}};
diag::List list;
- list.AddError(System::Test, Source{{{10, 20}, {30, 20}}, &ascii_file}) << "oob";
+ list.AddError(Source{{{10, 20}, {30, 20}}, &ascii_file}) << "oob";
auto got = fmt.Format(list).Plain();
auto* expect = R"(file.name:10:20 error: oob
diff --git a/src/tint/utils/macros/compiler.h b/src/tint/utils/macros/compiler.h
index a3de76f..a62a59e 100644
--- a/src/tint/utils/macros/compiler.h
+++ b/src/tint/utils/macros/compiler.h
@@ -54,6 +54,10 @@
#define TINT_DISABLE_WARNING_ZERO_AS_NULLPTR /* currently no-op */
#define TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE /* currently no-op */
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() __pragma(warning(push, 0)) TINT_REQUIRE_SEMICOLON
+
+#define TINT_END_DISABLE_ALL_WARNINGS() __pragma(warning(pop)) TINT_REQUIRE_SEMICOLON
+
// clang-format off
#define TINT_BEGIN_DISABLE_WARNING(name) \
__pragma(warning(push)) \
@@ -71,6 +75,10 @@
#define TINT_UNLIKELY(x) x /* currently no-op */
#define TINT_LIKELY(x) x /* currently no-op */
+#if defined(__SANITIZE_ADDRESS__)
+#define TINT_ASAN_ENABLED
+#endif
+
#elif defined(__clang__)
////////////////////////////////////////////////////////////////////////////////
// Clang
@@ -123,6 +131,15 @@
_Pragma("clang diagnostic pop") \
TINT_REQUIRE_SEMICOLON
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \
+ _Pragma("clang diagnostic push") \
+ _Pragma("clang diagnostic ignored \"-Weverything\"") \
+ TINT_REQUIRE_SEMICOLON
+
+#define TINT_END_DISABLE_ALL_WARNINGS() \
+ _Pragma("clang diagnostic pop") \
+ TINT_REQUIRE_SEMICOLON
+
#define TINT_BEGIN_DISABLE_WARNING(name) \
_Pragma("clang diagnostic push") \
TINT_CONCAT(TINT_DISABLE_WARNING_, name) \
@@ -135,6 +152,11 @@
#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false)
#define TINT_LIKELY(x) __builtin_expect(!!(x), true)
+
+#if __has_feature(address_sanitizer)
+#define TINT_ASAN_ENABLED
+#endif
+
#elif defined(__GNUC__)
////////////////////////////////////////////////////////////////////////////////
// GCC
@@ -164,6 +186,31 @@
#define TINT_END_DISABLE_PROTOBUF_WARNINGS() _Pragma("GCC diagnostic pop") TINT_REQUIRE_SEMICOLON
// clang-format off
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() \
+ _Pragma("GCC diagnostic push") \
+ TINT_DISABLE_WARNING_CONSTANT_OVERFLOW \
+ TINT_DISABLE_WARNING_MAYBE_UNINITIALIZED \
+ TINT_DISABLE_WARNING_NEWLINE_EOF \
+ TINT_DISABLE_WARNING_OLD_STYLE_CAST \
+ TINT_DISABLE_WARNING_SIGN_CONVERSION \
+ TINT_DISABLE_WARNING_UNREACHABLE_CODE \
+ TINT_DISABLE_WARNING_WEAK_VTABLES \
+ TINT_DISABLE_WARNING_FLOAT_EQUAL \
+ TINT_DISABLE_WARNING_DEPRECATED \
+ TINT_DISABLE_WARNING_RESERVED_IDENTIFIER \
+ TINT_DISABLE_WARNING_RESERVED_MACRO_IDENTIFIER \
+ TINT_DISABLE_WARNING_UNUSED_VALUE \
+ TINT_DISABLE_WARNING_UNUSED_PARAMETER \
+ TINT_DISABLE_WARNING_SHADOW_FIELD_IN_CONSTRUCTOR \
+ TINT_DISABLE_WARNING_EXTRA_SEMICOLON \
+ TINT_DISABLE_WARNING_ZERO_AS_NULLPTR \
+ TINT_DISABLE_WARNING_MISSING_DESTRUCTOR_OVERRIDE \
+ TINT_REQUIRE_SEMICOLON
+// clang-format on
+
+#define TINT_END_DISABLE_ALL_WARNINGS() _Pragma("GCC diagnostic pop") TINT_REQUIRE_SEMICOLON
+
+// clang-format off
#define TINT_BEGIN_DISABLE_WARNING(name) \
_Pragma("GCC diagnostic push") \
TINT_CONCAT(TINT_DISABLE_WARNING_, name) \
@@ -175,10 +222,17 @@
#define TINT_UNLIKELY(x) __builtin_expect(!!(x), false)
#define TINT_LIKELY(x) __builtin_expect(!!(x), true)
+
+#if defined(__SANITIZE_ADDRESS__)
+#define TINT_ASAN_ENABLED
+#endif
+
#else
////////////////////////////////////////////////////////////////////////////////
// Other
////////////////////////////////////////////////////////////////////////////////
+#define TINT_BEGIN_DISABLE_ALL_WARNINGS() TINT_REQUIRE_SEMICOLON
+#define TINT_END_DISABLE_ALL_WARNINGS TINT_REQUIRE_SEMICOLON
#define TINT_BEGIN_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
#define TINT_END_DISABLE_WARNING(name) TINT_REQUIRE_SEMICOLON
#define TINT_BEGIN_DISABLE_PROTOBUF_WARNINGS() TINT_REQUIRE_SEMICOLON
diff --git a/src/tint/utils/result/result.cc b/src/tint/utils/result/result.cc
index a3ecfc3..0a8c6c8 100644
--- a/src/tint/utils/result/result.cc
+++ b/src/tint/utils/result/result.cc
@@ -32,7 +32,7 @@
Failure::Failure() = default;
Failure::Failure(std::string_view err) {
- reason.AddError(diag::System::Unknown, Source{}) << err;
+ reason.AddError(Source{}) << err;
}
Failure::Failure(diag::Diagnostic diagnostic) : reason(diag::List{std::move(diagnostic)}) {}