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)}) {}