[tint][ir][val] Check vertex output builtin rules
- Moves ReferenceModuleVars to core/ir/ and modifies it to support
const and non-const operations
- Some rewrites of existing tests whose shaders were not following
the vertex rules.
- Disables some tests where it is known getting them working will
require additional work.
Fixes: 367764845
Change-Id: I6decc0253b349de0e544b428c4180a5a1863540d
WIP: Initial constification
Change-Id: I69b33b28f6b9da3b0d281f78f9a3066bd3a54110
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/207374
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/cmd/test/BUILD.bazel b/src/tint/cmd/test/BUILD.bazel
index 3d8f21d..7720586 100644
--- a/src/tint/cmd/test/BUILD.bazel
+++ b/src/tint/cmd/test/BUILD.bazel
@@ -46,7 +46,6 @@
"//src/tint/api/common:test",
"//src/tint/lang/core/constant:test",
"//src/tint/lang/core/intrinsic:test",
- "//src/tint/lang/core/ir/transform/common:test",
"//src/tint/lang/core/ir/transform:test",
"//src/tint/lang/core/ir:test",
"//src/tint/lang/core/type:test",
diff --git a/src/tint/cmd/test/BUILD.cmake b/src/tint/cmd/test/BUILD.cmake
index 36633be..a039469 100644
--- a/src/tint/cmd/test/BUILD.cmake
+++ b/src/tint/cmd/test/BUILD.cmake
@@ -47,7 +47,6 @@
tint_api_common_test
tint_lang_core_constant_test
tint_lang_core_intrinsic_test
- tint_lang_core_ir_transform_common_test
tint_lang_core_ir_transform_test
tint_lang_core_ir_test
tint_lang_core_type_test
diff --git a/src/tint/cmd/test/BUILD.gn b/src/tint/cmd/test/BUILD.gn
index c346355..6152cfc 100644
--- a/src/tint/cmd/test/BUILD.gn
+++ b/src/tint/cmd/test/BUILD.gn
@@ -56,7 +56,6 @@
"${tint_src_dir}/lang/core/intrinsic:unittests",
"${tint_src_dir}/lang/core/ir:unittests",
"${tint_src_dir}/lang/core/ir/transform:unittests",
- "${tint_src_dir}/lang/core/ir/transform/common:unittests",
"${tint_src_dir}/lang/core/type:unittests",
"${tint_src_dir}/lang/glsl/ir:unittests",
"${tint_src_dir}/lang/hlsl/ir:unittests",
diff --git a/src/tint/lang/core/ir/BUILD.bazel b/src/tint/lang/core/ir/BUILD.bazel
index b525147..e924736 100644
--- a/src/tint/lang/core/ir/BUILD.bazel
+++ b/src/tint/lang/core/ir/BUILD.bazel
@@ -132,6 +132,7 @@
"multi_in_block.h",
"next_iteration.h",
"operand_instruction.h",
+ "referenced_module_vars.h",
"return.h",
"store.h",
"store_vector_element.h",
@@ -207,6 +208,7 @@
"multi_in_block_test.cc",
"next_iteration_test.cc",
"operand_instruction_test.cc",
+ "referenced_module_vars_test.cc",
"return_test.cc",
"store_test.cc",
"store_vector_element_test.cc",
diff --git a/src/tint/lang/core/ir/BUILD.cmake b/src/tint/lang/core/ir/BUILD.cmake
index b4d6e1d..7eb4265 100644
--- a/src/tint/lang/core/ir/BUILD.cmake
+++ b/src/tint/lang/core/ir/BUILD.cmake
@@ -119,6 +119,7 @@
lang/core/ir/next_iteration.h
lang/core/ir/operand_instruction.cc
lang/core/ir/operand_instruction.h
+ lang/core/ir/referenced_module_vars.h
lang/core/ir/return.cc
lang/core/ir/return.h
lang/core/ir/store.cc
@@ -211,6 +212,7 @@
lang/core/ir/multi_in_block_test.cc
lang/core/ir/next_iteration_test.cc
lang/core/ir/operand_instruction_test.cc
+ lang/core/ir/referenced_module_vars_test.cc
lang/core/ir/return_test.cc
lang/core/ir/store_test.cc
lang/core/ir/store_vector_element_test.cc
diff --git a/src/tint/lang/core/ir/BUILD.gn b/src/tint/lang/core/ir/BUILD.gn
index 86ec6bd..26f700b 100644
--- a/src/tint/lang/core/ir/BUILD.gn
+++ b/src/tint/lang/core/ir/BUILD.gn
@@ -122,6 +122,7 @@
"next_iteration.h",
"operand_instruction.cc",
"operand_instruction.h",
+ "referenced_module_vars.h",
"return.cc",
"return.h",
"store.cc",
@@ -208,6 +209,7 @@
"multi_in_block_test.cc",
"next_iteration_test.cc",
"operand_instruction_test.cc",
+ "referenced_module_vars_test.cc",
"return_test.cc",
"store_test.cc",
"store_vector_element_test.cc",
diff --git a/src/tint/lang/core/ir/referenced_module_vars.h b/src/tint/lang/core/ir/referenced_module_vars.h
new file mode 100644
index 0000000..34401c1
--- /dev/null
+++ b/src/tint/lang/core/ir/referenced_module_vars.h
@@ -0,0 +1,159 @@
+// 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.
+
+#ifndef SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_
+#define SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_
+
+#include <functional>
+
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/user_call.h"
+#include "src/tint/lang/core/ir/var.h"
+#include "src/tint/utils/containers/hashmap.h"
+#include "src/tint/utils/containers/unique_vector.h"
+#include "src/tint/utils/rtti/switch.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Block;
+class Function;
+} // namespace tint::core::ir
+
+/// Utility that helps guarantee makes sure the same const-ness is applied to both type
+template <class Src, class Dst>
+using TranscribeConst = std::conditional_t<std::is_const<Src>{}, std::add_const_t<Dst>, Dst>;
+
+namespace tint::core::ir {
+
+/// ReferencedModuleVars is a helper to determine the set of module-scope variables that are
+/// transitively referenced by functions in a module.
+/// References are determined lazily and cached for future requests.
+///
+/// Note:
+/// The template param M is used to ensure that inputs and outputs of this class have the same
+/// const-ness. If 'Module' is supplied then the internal operations and output will not be
+/// const, which is needed for transforms. Whereas if the param is 'const Module' the internals
+/// and outputs will be const, which is needed for the IR validator.
+/// Note:
+/// Changes to the module can invalidate the cached data. This is intended to be created by
+/// operations that need this information, and discarded when they complete. Tracking this
+/// information inside the IR module would add overhead any time an instruction is added or
+/// removed from the module. Since only a few operations need this information, it is expected
+/// to be more efficient to generate it on demand.
+template <typename M>
+class ReferencedModuleVars {
+ // Replace this with concepts when C++20 is available
+ static_assert(std::is_same<std::remove_cv_t<M>, Module>());
+
+ public:
+ /// Short form aliases for types that have the same constant-ness as M.
+ /// (The single use types are not aliased)
+ using BlockT = TranscribeConst<M, Block>;
+ using VarT = TranscribeConst<M, Var>;
+ using FunctionT = TranscribeConst<M, Function>;
+
+ /// A set of a variables referenced by a function (in declaration order).
+ using VarSet = UniqueVector<VarT*, 16>;
+
+ /// Constructor.
+ /// @param ir the module
+ /// @param pred an predicate function for filtering variables
+ /// Note: @p pred is not stored by the class, so can be a lambda that captures by reference.
+ template <typename Predicate>
+ ReferencedModuleVars(M& ir, Predicate&& pred) {
+ // Loop over module-scope variables, recording the blocks that they are referenced from.
+ BlockT* root_block = ir.root_block;
+ for (auto* inst : *root_block) {
+ if (auto* var = inst->template As<VarT>()) {
+ if (pred(var)) {
+ if (!var->Result(0)) {
+ continue;
+ }
+ var->Result(0)->ForEachUseUnsorted([&](const Usage& use) {
+ block_to_direct_vars_.GetOrAddZero(use.instruction->Block()).Add(var);
+ });
+ }
+ }
+ }
+ }
+
+ /// Constructor.
+ /// Provided default predicate that accepts all variables.
+ explicit ReferencedModuleVars(M& ir) : ReferencedModuleVars(ir, [](VarT*) { return true; }) {}
+
+ /// Get the set of transitively referenced module-scope variables for a function, filtered by
+ /// the predicate function if provided.
+ /// @param func the function
+ /// @returns the set of (possibly filtered) transitively reference module-scope variables
+ VarSet& TransitiveReferences(FunctionT* func) {
+ return transitive_references_.GetOrAdd(func, [&] {
+ VarSet vars;
+ GetTransitiveReferences(func->Block(), vars);
+ return vars;
+ });
+ }
+
+ private:
+ /// A map from blocks to their directly referenced variables.
+ Hashmap<BlockT*, VarSet, 64> block_to_direct_vars_{};
+
+ /// A map from functions to their transitively referenced variables.
+ Hashmap<FunctionT*, VarSet, 8> transitive_references_;
+
+ /// Get the set of transitively referenced module-scope variables for a block.
+ /// @param block the block
+ /// @param vars the set of transitively reference module-scope variables to populate
+ void GetTransitiveReferences(BlockT* block, VarSet& vars) {
+ // Add directly referenced vars.
+ if (auto itr = block_to_direct_vars_.Get(block)) {
+ for (auto& var : *itr) {
+ vars.Add(var);
+ }
+ }
+
+ // Loop over instructions in the block to find indirectly referenced vars.
+ for (auto* inst : *block) {
+ tint::Switch(
+ inst,
+ [&](TranscribeConst<M, UserCall>* call) {
+ // Get variables referenced by a function called from this block.
+ const auto& callee_vars = TransitiveReferences(call->Target());
+ for (auto* var : callee_vars) {
+ vars.Add(var);
+ }
+ },
+ [&](TranscribeConst<M, ControlInstruction>* ctrl) {
+ // Recurse into control instructions and gather their referenced vars.
+ ctrl->ForeachBlock([&](BlockT* blk) { GetTransitiveReferences(blk, vars); });
+ });
+ }
+ }
+};
+
+} // namespace tint::core::ir
+
+#endif // SRC_TINT_LANG_CORE_IR_REFERENCED_MODULE_VARS_H_
diff --git a/src/tint/lang/core/ir/transform/common/referenced_module_vars_test.cc b/src/tint/lang/core/ir/referenced_module_vars_test.cc
similarity index 96%
rename from src/tint/lang/core/ir/transform/common/referenced_module_vars_test.cc
rename to src/tint/lang/core/ir/referenced_module_vars_test.cc
index a8ee411..dce9c18 100644
--- a/src/tint/lang/core/ir/transform/common/referenced_module_vars_test.cc
+++ b/src/tint/lang/core/ir/referenced_module_vars_test.cc
@@ -25,7 +25,7 @@
// 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/transform/common/referenced_module_vars.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include <string>
@@ -62,7 +62,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
auto& foo_vars = vars.TransitiveReferences(foo);
EXPECT_TRUE(foo_vars.IsEmpty());
}
@@ -98,7 +98,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a, var_b));
}
@@ -141,7 +141,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a, var_b, var_c, var_d, var_e));
}
@@ -198,7 +198,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a, var_b));
EXPECT_THAT(vars.TransitiveReferences(bar), ElementsAre(var_a, var_c));
EXPECT_TRUE(vars.TransitiveReferences(zoo).IsEmpty());
@@ -275,7 +275,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a, var_b, var_c, var_d));
}
@@ -335,7 +335,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(bar), ElementsAre(var_b));
EXPECT_THAT(vars.TransitiveReferences(zoo), ElementsAre(var_b));
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a, var_b));
@@ -368,7 +368,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod);
+ ReferencedModuleVars<Module> vars(mod);
EXPECT_THAT(vars.TransitiveReferences(foo), ElementsAre(var_a));
}
@@ -411,7 +411,7 @@
)";
EXPECT_EQ(src, Disassemble());
- ReferencedModuleVars vars(mod, [](const Var* var) {
+ ReferencedModuleVars<Module> vars(mod, [](const Var* var) {
auto* view = var->Result(0)->Type()->As<type::MemoryView>();
return view->AddressSpace() == AddressSpace::kPrivate;
});
diff --git a/src/tint/lang/core/ir/transform/BUILD.bazel b/src/tint/lang/core/ir/transform/BUILD.bazel
index b90c54f..7dcf606 100644
--- a/src/tint/lang/core/ir/transform/BUILD.bazel
+++ b/src/tint/lang/core/ir/transform/BUILD.bazel
@@ -93,7 +93,6 @@
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
"//src/tint/lang/core/ir",
- "//src/tint/lang/core/ir/transform/common",
"//src/tint/lang/core/type",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
diff --git a/src/tint/lang/core/ir/transform/BUILD.cmake b/src/tint/lang/core/ir/transform/BUILD.cmake
index 1687918..fe36cb8 100644
--- a/src/tint/lang/core/ir/transform/BUILD.cmake
+++ b/src/tint/lang/core/ir/transform/BUILD.cmake
@@ -34,8 +34,6 @@
# Do not modify this file directly
################################################################################
-include(lang/core/ir/transform/common/BUILD.cmake)
-
################################################################################
# Target: tint_lang_core_ir_transform
# Kind: lib
@@ -94,7 +92,6 @@
tint_lang_core_constant
tint_lang_core_intrinsic
tint_lang_core_ir
- tint_lang_core_ir_transform_common
tint_lang_core_type
tint_utils_containers
tint_utils_diagnostic
diff --git a/src/tint/lang/core/ir/transform/BUILD.gn b/src/tint/lang/core/ir/transform/BUILD.gn
index 9387529..d4e8158 100644
--- a/src/tint/lang/core/ir/transform/BUILD.gn
+++ b/src/tint/lang/core/ir/transform/BUILD.gn
@@ -98,7 +98,6 @@
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
"${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/ir/transform/common",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
diff --git a/src/tint/lang/core/ir/transform/common/BUILD.bazel b/src/tint/lang/core/ir/transform/common/BUILD.bazel
deleted file mode 100644
index c02990e..0000000
--- a/src/tint/lang/core/ir/transform/common/BUILD.bazel
+++ /dev/null
@@ -1,105 +0,0 @@
-# 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.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.bazel.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-load("//src/tint:flags.bzl", "COPTS")
-load("@bazel_skylib//lib:selects.bzl", "selects")
-cc_library(
- name = "common",
- srcs = [
- "referenced_module_vars.cc",
- ],
- hdrs = [
- "referenced_module_vars.h",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/ir",
- "//src/tint/lang/core/type",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/id",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/reflection",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "//src/tint/utils/traits",
- "//src/utils",
- ],
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-cc_library(
- name = "test",
- alwayslink = True,
- srcs = [
- "referenced_module_vars_test.cc",
- ],
- deps = [
- "//src/tint/api/common",
- "//src/tint/lang/core",
- "//src/tint/lang/core/constant",
- "//src/tint/lang/core/intrinsic",
- "//src/tint/lang/core/ir",
- "//src/tint/lang/core/ir/transform/common",
- "//src/tint/lang/core/ir:test",
- "//src/tint/lang/core/type",
- "//src/tint/utils/containers",
- "//src/tint/utils/diagnostic",
- "//src/tint/utils/ice",
- "//src/tint/utils/id",
- "//src/tint/utils/macros",
- "//src/tint/utils/math",
- "//src/tint/utils/memory",
- "//src/tint/utils/reflection",
- "//src/tint/utils/result",
- "//src/tint/utils/rtti",
- "//src/tint/utils/symbol",
- "//src/tint/utils/text",
- "//src/tint/utils/traits",
- "@gtest",
- "//src/utils",
- ],
- copts = COPTS,
- visibility = ["//visibility:public"],
-)
-
diff --git a/src/tint/lang/core/ir/transform/common/BUILD.cmake b/src/tint/lang/core/ir/transform/common/BUILD.cmake
deleted file mode 100644
index 35a95e0..0000000
--- a/src/tint/lang/core/ir/transform/common/BUILD.cmake
+++ /dev/null
@@ -1,106 +0,0 @@
-# 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.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.cmake.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-################################################################################
-# Target: tint_lang_core_ir_transform_common
-# Kind: lib
-################################################################################
-tint_add_target(tint_lang_core_ir_transform_common lib
- lang/core/ir/transform/common/referenced_module_vars.cc
- lang/core/ir/transform/common/referenced_module_vars.h
-)
-
-tint_target_add_dependencies(tint_lang_core_ir_transform_common lib
- tint_api_common
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_ir
- tint_lang_core_type
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_id
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_reflection
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
- tint_utils_traits
-)
-
-tint_target_add_external_dependencies(tint_lang_core_ir_transform_common lib
- "src_utils"
-)
-
-################################################################################
-# Target: tint_lang_core_ir_transform_common_test
-# Kind: test
-################################################################################
-tint_add_target(tint_lang_core_ir_transform_common_test test
- lang/core/ir/transform/common/referenced_module_vars_test.cc
-)
-
-tint_target_add_dependencies(tint_lang_core_ir_transform_common_test test
- tint_api_common
- tint_lang_core
- tint_lang_core_constant
- tint_lang_core_intrinsic
- tint_lang_core_ir
- tint_lang_core_ir_transform_common
- tint_lang_core_ir_test
- tint_lang_core_type
- tint_utils_containers
- tint_utils_diagnostic
- tint_utils_ice
- tint_utils_id
- tint_utils_macros
- tint_utils_math
- tint_utils_memory
- tint_utils_reflection
- tint_utils_result
- tint_utils_rtti
- tint_utils_symbol
- tint_utils_text
- tint_utils_traits
-)
-
-tint_target_add_external_dependencies(tint_lang_core_ir_transform_common_test test
- "gtest"
- "src_utils"
-)
diff --git a/src/tint/lang/core/ir/transform/common/BUILD.gn b/src/tint/lang/core/ir/transform/common/BUILD.gn
deleted file mode 100644
index 0dff5dae..0000000
--- a/src/tint/lang/core/ir/transform/common/BUILD.gn
+++ /dev/null
@@ -1,102 +0,0 @@
-# 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.
-
-################################################################################
-# File generated by 'tools/src/cmd/gen' using the template:
-# tools/src/cmd/gen/build/BUILD.gn.tmpl
-#
-# To regenerate run: './tools/run gen'
-#
-# Do not modify this file directly
-################################################################################
-
-import("../../../../../../../scripts/dawn_overrides_with_defaults.gni")
-import("../../../../../../../scripts/tint_overrides_with_defaults.gni")
-
-import("${tint_src_dir}/tint.gni")
-
-if (tint_build_unittests || tint_build_benchmarks) {
- import("//testing/test.gni")
-}
-
-libtint_source_set("common") {
- sources = [
- "referenced_module_vars.cc",
- "referenced_module_vars.h",
- ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
-}
-if (tint_build_unittests) {
- tint_unittests_source_set("unittests") {
- sources = [ "referenced_module_vars_test.cc" ]
- deps = [
- "${dawn_root}/src/utils:utils",
- "${tint_src_dir}:gmock_and_gtest",
- "${tint_src_dir}/api/common",
- "${tint_src_dir}/lang/core",
- "${tint_src_dir}/lang/core/constant",
- "${tint_src_dir}/lang/core/intrinsic",
- "${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/ir:unittests",
- "${tint_src_dir}/lang/core/ir/transform/common",
- "${tint_src_dir}/lang/core/type",
- "${tint_src_dir}/utils/containers",
- "${tint_src_dir}/utils/diagnostic",
- "${tint_src_dir}/utils/ice",
- "${tint_src_dir}/utils/id",
- "${tint_src_dir}/utils/macros",
- "${tint_src_dir}/utils/math",
- "${tint_src_dir}/utils/memory",
- "${tint_src_dir}/utils/reflection",
- "${tint_src_dir}/utils/result",
- "${tint_src_dir}/utils/rtti",
- "${tint_src_dir}/utils/symbol",
- "${tint_src_dir}/utils/text",
- "${tint_src_dir}/utils/traits",
- ]
- }
-}
diff --git a/src/tint/lang/core/ir/transform/common/referenced_module_vars.cc b/src/tint/lang/core/ir/transform/common/referenced_module_vars.cc
deleted file mode 100644
index b97b9dd..0000000
--- a/src/tint/lang/core/ir/transform/common/referenced_module_vars.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-// 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/core/ir/transform/common/referenced_module_vars.h"
-
-#include "src/tint/lang/core/ir/control_instruction.h"
-#include "src/tint/lang/core/ir/module.h"
-#include "src/tint/lang/core/ir/user_call.h"
-#include "src/tint/lang/core/ir/var.h"
-#include "src/tint/utils/rtti/switch.h"
-
-namespace tint::core::ir {
-
-const ReferencedModuleVars::VarSet& ReferencedModuleVars::TransitiveReferences(Function* func) {
- return transitive_references_.GetOrAdd(func, [&] {
- VarSet vars;
- GetTransitiveReferences(func->Block(), vars);
- return vars;
- });
-}
-
-/// Get the set of variables transitively referenced by @p block.
-/// @param block the block
-/// @param vars the set of transitively referenced variables to populate
-void ReferencedModuleVars::GetTransitiveReferences(Block* block, VarSet& vars) {
- // Add directly referenced vars.
- if (auto itr = block_to_direct_vars_.Get(block)) {
- for (auto& var : *itr) {
- vars.Add(var);
- }
- }
-
- // Loop over instructions in the block to find indirectly referenced vars.
- for (auto* inst : *block) {
- tint::Switch(
- inst,
- [&](UserCall* call) {
- // Get variables referenced by a function called from this block.
- const auto& callee_vars = TransitiveReferences(call->Target());
- for (auto* var : callee_vars) {
- vars.Add(var);
- }
- },
- [&](ControlInstruction* ctrl) {
- // Recurse into control instructions and gather their referenced vars.
- ctrl->ForeachBlock([&](Block* blk) { GetTransitiveReferences(blk, vars); });
- });
- }
-}
-
-} // namespace tint::core::ir
diff --git a/src/tint/lang/core/ir/transform/common/referenced_module_vars.h b/src/tint/lang/core/ir/transform/common/referenced_module_vars.h
deleted file mode 100644
index 41e2dd9..0000000
--- a/src/tint/lang/core/ir/transform/common/referenced_module_vars.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// 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.
-
-#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_COMMON_REFERENCED_MODULE_VARS_H_
-#define SRC_TINT_LANG_CORE_IR_TRANSFORM_COMMON_REFERENCED_MODULE_VARS_H_
-
-#include <functional>
-
-#include "src/tint/lang/core/ir/module.h"
-#include "src/tint/lang/core/ir/var.h"
-#include "src/tint/utils/containers/hashmap.h"
-#include "src/tint/utils/containers/unique_vector.h"
-
-// Forward declarations.
-namespace tint::core::ir {
-class Block;
-class Function;
-} // namespace tint::core::ir
-
-namespace tint::core::ir {
-
-/// ReferencedModuleVars is a helper to determine the set of module-scope variables that are
-/// transitively referenced by functions in a module.
-/// References are determined lazily and cached for future requests.
-///
-/// Note: changes to the module can invalidate the cached data. This is intended to be created by
-/// a transform that need this information, and discarded when that transform completes. Tracking
-/// this information inside the IR module would add overhead any time an instruction is added or
-/// removed from the module. Since only a few transforms need this information, we expect it to be
-/// more efficient to generate it as and when needed instead.
-class ReferencedModuleVars {
- public:
- /// The signature of a predicate used to filter variables.
- /// A predicate function should return `true` when the variable should be added to the set.
- using Predicate = std::function<bool(const Var*)>;
-
- /// A set of a variables referenced by a function (in declaration order).
- using VarSet = UniqueVector<Var*, 16>;
-
- /// Constructor.
- /// @param ir the module
- /// @param pred an optional predicate function for filtering variables
- /// Note: @p pred is not stored by the class, so can be a lambda that captures by reference.
- explicit ReferencedModuleVars(Module& ir, Predicate&& pred = {}) : ir_(ir) {
- // Loop over module-scope variables, recording the blocks that they are referenced from.
- for (auto inst : *ir_.root_block) {
- if (auto* var = inst->As<Var>()) {
- if (!pred || pred(var)) {
- var->Result(0)->ForEachUseUnsorted([&](const Usage& use) {
- block_to_direct_vars_.GetOrAddZero(use.instruction->Block()).Add(var);
- });
- }
- }
- }
- }
-
- /// Get the set of transitively referenced module-scope variables for a function, filtered by
- /// the predicate function if provided.
- /// @param func the function
- /// @returns the set of (possibly filtered) transitively reference module-scope variables
- const VarSet& TransitiveReferences(Function* func);
-
- private:
- /// The module.
- Module& ir_;
-
- /// A map from blocks to their directly referenced variables.
- Hashmap<Block*, VarSet, 64> block_to_direct_vars_{};
-
- /// A map from functions to their transitively referenced variables.
- Hashmap<Function*, VarSet, 8> transitive_references_;
-
- /// Get the set of transitively referenced module-scope variables for a block.
- /// @param block the block
- /// @param vars the set of transitively reference module-scope variables to populate
- void GetTransitiveReferences(Block* block, VarSet& vars);
-};
-
-} // namespace tint::core::ir
-
-#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_COMMON_REFERENCED_MODULE_VARS_H_
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 28511b9..9566183 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
@@ -32,7 +32,7 @@
#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/module.h"
-#include "src/tint/lang/core/ir/transform/common/referenced_module_vars.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/utils/containers/reverse.h"
@@ -63,7 +63,7 @@
core::type::Manager& ty{ir.Types()};
/// The mapping from functions to their transitively referenced workgroup variables.
- ReferencedModuleVars referenced_module_vars_{
+ ReferencedModuleVars<Module> referenced_module_vars_{
ir, [](const Var* var) {
auto* view = var->Result(0)->Type()->As<type::MemoryView>();
return view && view->AddressSpace() == AddressSpace::kWorkgroup;
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 12a2759..e1d81b0 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -63,6 +63,7 @@
#include "src/tint/lang/core/ir/member_builtin_call.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
#include "src/tint/lang/core/ir/store_vector_element.h"
@@ -75,6 +76,7 @@
#include "src/tint/lang/core/ir/user_call.h"
#include "src/tint/lang/core/ir/var.h"
#include "src/tint/lang/core/type/bool.h"
+#include "src/tint/lang/core/type/f32.h"
#include "src/tint/lang/core/type/i8.h"
#include "src/tint/lang/core/type/memory_view.h"
#include "src/tint/lang/core/type/pointer.h"
@@ -363,9 +365,23 @@
void CheckRootBlock(const Block* blk);
/// Validates the given function
- /// @param func the function validate
+ /// @param func the function to validate
void CheckFunction(const Function* func);
+ /// Validates the specific function as a vertex entry point
+ /// @param ep the function to validate
+ void CheckVertexEntryPoint(const Function* ep);
+
+ /// Validates that the type annotated with @builtin(position) is correct
+ /// @param ep the entry point to associate errors with
+ /// @param type the type to validate
+ void CheckBuiltinPosition(const Function* ep, const core::type::Type* type);
+
+ /// Validates that the type annotated with @builtin(clip_distances) is correct
+ /// @param ep the entry point to associate errors with
+ /// @param type the type to validate
+ void CheckBuiltinClipDistances(const Function* ep, const core::type::Type* type);
+
/// Validates the given instruction
/// @param inst the instruction to validate
void CheckInstruction(const Instruction* inst);
@@ -612,10 +628,11 @@
Hashmap<const ir::Block*, const ir::Function*, 64> block_to_function_{};
Hashmap<const ir::Function*, Hashset<const ir::UserCall*, 4>, 4> user_func_calls_;
Hashset<const ir::Discard*, 4> discards_;
+ core::ir::ReferencedModuleVars<const Module> referenced_module_vars_;
};
Validator::Validator(const Module& mod, Capabilities capabilities)
- : mod_(mod), capabilities_(capabilities) {}
+ : mod_(mod), capabilities_(capabilities), referenced_module_vars_(mod) {}
Validator::~Validator() = default;
@@ -1176,10 +1193,98 @@
}
}
+ if (func->Stage() == Function::PipelineStage::kVertex) {
+ CheckVertexEntryPoint(func);
+ }
+
QueueBlock(func->Block());
ProcessTasks();
}
+void Validator::CheckVertexEntryPoint(const Function* ep) {
+ const auto* ret_struct = ep->ReturnType()->As<core::type::Struct>();
+ bool contains_position = false;
+ if (ret_struct) {
+ for (auto* mem : ret_struct->Members()) {
+ if (!mem->Attributes().builtin.has_value()) {
+ continue;
+ }
+ switch (mem->Attributes().builtin.value()) {
+ case BuiltinValue::kPosition:
+ contains_position = true;
+ CheckBuiltinPosition(ep, mem->Type());
+ break;
+ case BuiltinValue::kClipDistances:
+ CheckBuiltinClipDistances(ep, mem->Type());
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ if (ep->ReturnBuiltin() && ep->ReturnBuiltin() == BuiltinValue::kPosition) {
+ contains_position = true;
+ CheckBuiltinPosition(ep, ep->ReturnType());
+ }
+ }
+
+ for (auto var : referenced_module_vars_.TransitiveReferences(ep)) {
+ const auto* res_type = var->Result(0)->Type()->UnwrapPtrOrRef();
+ const auto* res_struct = res_type->As<core::type::Struct>();
+ if (res_struct) {
+ for (auto* mem : res_struct->Members()) {
+ if (!mem->Attributes().builtin.has_value()) {
+ continue;
+ }
+ switch (mem->Attributes().builtin.value()) {
+ case BuiltinValue::kPosition:
+ contains_position = true;
+ CheckBuiltinPosition(ep, mem->Type()->UnwrapPtrOrRef());
+ break;
+ case BuiltinValue::kClipDistances:
+ CheckBuiltinClipDistances(ep, mem->Type()->UnwrapPtrOrRef());
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ if (!var->Attributes().builtin.has_value()) {
+ continue;
+ }
+ switch (var->Attributes().builtin.value()) {
+ case BuiltinValue::kPosition: {
+ contains_position = true;
+ CheckBuiltinPosition(ep, res_type);
+ } break;
+ case BuiltinValue::kClipDistances:
+ CheckBuiltinClipDistances(ep, var->Result(0)->Type()->UnwrapPtrOrRef());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (DAWN_UNLIKELY(!contains_position)) {
+ AddError(ep) << "position must be declared for vertex entry point output";
+ }
+}
+
+void Validator::CheckBuiltinPosition(const Function* ep, const core::type::Type* type) {
+ auto elems = type->Elements();
+ if (!type->IsFloatVector() || !elems.type->Is<core::type::F32>() || elems.count != 4) {
+ AddError(ep) << "position must be a vec4<f32>";
+ }
+}
+
+void Validator::CheckBuiltinClipDistances(const Function* ep, const core::type::Type* type) {
+ const auto elems = type->Elements();
+ if (!elems.type || !elems.type->Is<core::type::F32>() || elems.count > 8) {
+ AddError(ep) << "clip_distances must be an array<f32, N>, where N <= 8";
+ }
+}
+
void Validator::ProcessTasks() {
while (!tasks_.IsEmpty()) {
tasks_.Pop()();
@@ -1789,7 +1894,8 @@
// Ensure that values used in the loop continuing are not from the loop body, after a
// continue instruction.
if (auto* first_continue = first_continues_.GetOr(loop, nullptr)) {
- // Find the instruction in the body block that is or holds the first continue instruction.
+ // Find the instruction in the body block that is or holds the first continue
+ // instruction.
const Instruction* holds_continue = first_continue;
while (holds_continue && holds_continue->Block() &&
holds_continue->Block() != loop->Body()) {
@@ -1803,7 +1909,8 @@
if (TransitivelyHolds(loop->Continuing(), use.instruction)) {
AddError(use.instruction, use.operand_index)
<< NameOf(result)
- << " cannot be used in continuing block as it is declared after the "
+ << " cannot be used in continuing block as it is declared after "
+ "the "
"first "
<< style::Instruction("continue") << " in the loop's body";
AddDeclarationNote(result);
@@ -1986,8 +2093,8 @@
auto* func = ret->Func();
if (func == nullptr) {
- // Func() returning nullptr after CheckResultsAndOperandRange is due to the first operand
- // being not a function
+ // Func() returning nullptr after CheckResultsAndOperandRange is due to the first
+ // operand being not a function
AddError(ret) << "expected function for first operand";
return;
}
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index 5c7235f..7b90404 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -451,6 +451,133 @@
)");
}
+TEST_F(IR_ValidatorTest, Function_VertexBasicPosition) {
+ auto* f = b.Function("my_func", ty.vec4<f32>());
+ f->SetStage(Function::PipelineStage::kVertex);
+ f->SetReturnBuiltin(BuiltinValue::kPosition);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_EQ(res, Success);
+}
+
+TEST_F(IR_ValidatorTest, Function_VertexStructPosition) {
+ auto pos_ty = ty.vec4<f32>();
+ auto pos_attr = IOAttributes();
+ pos_attr.builtin = BuiltinValue::kPosition;
+
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("pos"), pos_ty, pos_attr},
+ });
+
+ auto* f = b.Function("my_func", str_ty);
+ f->SetStage(Function::PipelineStage::kVertex);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_EQ(res, Success);
+}
+
+TEST_F(IR_ValidatorTest, Function_VertexStructPositionAndClipDistances) {
+ auto pos_ty = ty.vec4<f32>();
+ auto pos_attr = IOAttributes();
+ pos_attr.builtin = BuiltinValue::kPosition;
+
+ auto clip_ty = ty.array<f32, 4>();
+ auto clip_attr = IOAttributes();
+ clip_attr.builtin = BuiltinValue::kClipDistances;
+
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("pos"), pos_ty, pos_attr},
+ {mod.symbols.New("clip"), clip_ty, clip_attr},
+ });
+
+ auto* f = b.Function("my_func", str_ty);
+ f->SetStage(Function::PipelineStage::kVertex);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_EQ(res, Success);
+}
+
+TEST_F(IR_ValidatorTest, Function_VertexStructOnlyClipDistances) {
+ auto clip_ty = ty.array<f32, 4>();
+ auto clip_attr = IOAttributes();
+ clip_attr.builtin = BuiltinValue::kClipDistances;
+
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("clip"), clip_ty, clip_attr},
+ });
+
+ auto* f = b.Function("my_func", str_ty);
+ f->SetStage(Function::PipelineStage::kVertex);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:5:1 error: position must be declared for vertex entry point output
+%my_func = @vertex func():MyStruct {
+^^^^^^^^
+
+note: # Disassembly
+MyStruct = struct @align(4) {
+ clip:array<f32, 4> @offset(0), @builtin(clip_distances)
+}
+
+%my_func = @vertex func():MyStruct {
+ $B1: {
+ unreachable
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Function_VertexMissingPosition) {
+ auto* f = b.Function("my_func", ty.vec4<f32>());
+ f->SetStage(Function::PipelineStage::kVertex);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:1:1 error: position must be declared for vertex entry point output
+%my_func = @vertex func():vec4<f32> {
+^^^^^^^^
+
+note: # Disassembly
+%my_func = @vertex func():vec4<f32> {
+ $B1: {
+ unreachable
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Function_VertexPositionWrongType) {
+ auto* f = b.Function("my_func", ty.void_());
+ f->SetStage(Function::PipelineStage::kVertex);
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:1:1 error: position must be declared for vertex entry point output
+%my_func = @vertex func():void {
+^^^^^^^^
+
+note: # Disassembly
+%my_func = @vertex func():void {
+ $B1: {
+ unreachable
+ }
+}
+)");
+}
+
TEST_F(IR_ValidatorTest, CallToFunctionOutsideModule) {
auto* f = b.Function("f", ty.void_());
auto* g = b.Function("g", ty.void_());
@@ -1547,7 +1674,8 @@
});
auto* ep = b.Function("ep", ty.void_());
- ep->SetStage(Function::PipelineStage::kVertex);
+ ep->SetStage(Function::PipelineStage::kCompute);
+ ep->SetWorkgroupSize(0, 0, 0);
b.Append(ep->Block(), [&] {
b.Call(func);
b.Return(ep);
@@ -1567,7 +1695,7 @@
ret
}
}
-%ep = @vertex func():void {
+%ep = @compute @workgroup_size(0, 0, 0) func():void {
$B2: {
%3:void = call %foo
ret
diff --git a/src/tint/lang/msl/writer/raise/BUILD.bazel b/src/tint/lang/msl/writer/raise/BUILD.bazel
index e820aac..e1f73fc 100644
--- a/src/tint/lang/msl/writer/raise/BUILD.bazel
+++ b/src/tint/lang/msl/writer/raise/BUILD.bazel
@@ -66,7 +66,6 @@
"//src/tint/lang/core/intrinsic",
"//src/tint/lang/core/ir",
"//src/tint/lang/core/ir/transform",
- "//src/tint/lang/core/ir/transform/common",
"//src/tint/lang/core/type",
"//src/tint/lang/msl",
"//src/tint/lang/msl/intrinsic",
diff --git a/src/tint/lang/msl/writer/raise/BUILD.cmake b/src/tint/lang/msl/writer/raise/BUILD.cmake
index d872922..9f786f3 100644
--- a/src/tint/lang/msl/writer/raise/BUILD.cmake
+++ b/src/tint/lang/msl/writer/raise/BUILD.cmake
@@ -67,7 +67,6 @@
tint_lang_core_intrinsic
tint_lang_core_ir
tint_lang_core_ir_transform
- tint_lang_core_ir_transform_common
tint_lang_core_type
tint_lang_msl
tint_lang_msl_intrinsic
diff --git a/src/tint/lang/msl/writer/raise/BUILD.gn b/src/tint/lang/msl/writer/raise/BUILD.gn
index 33e9d8f..614d731 100644
--- a/src/tint/lang/msl/writer/raise/BUILD.gn
+++ b/src/tint/lang/msl/writer/raise/BUILD.gn
@@ -71,7 +71,6 @@
"${tint_src_dir}/lang/core/intrinsic",
"${tint_src_dir}/lang/core/ir",
"${tint_src_dir}/lang/core/ir/transform",
- "${tint_src_dir}/lang/core/ir/transform/common",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/msl",
"${tint_src_dir}/lang/msl/intrinsic",
diff --git a/src/tint/lang/msl/writer/raise/module_scope_vars.cc b/src/tint/lang/msl/writer/raise/module_scope_vars.cc
index efbde47..8727e39 100644
--- a/src/tint/lang/msl/writer/raise/module_scope_vars.cc
+++ b/src/tint/lang/msl/writer/raise/module_scope_vars.cc
@@ -30,7 +30,7 @@
#include <utility>
#include "src/tint/lang/core/ir/builder.h"
-#include "src/tint/lang/core/ir/transform/common/referenced_module_vars.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/ir/validator.h"
namespace tint::msl::writer::raise {
@@ -62,7 +62,7 @@
Hashmap<core::ir::Block*, core::ir::Function*, 64> block_to_function{};
/// The mapping from functions to their transitively referenced workgroup variables.
- core::ir::ReferencedModuleVars referenced_module_vars{ir};
+ core::ir::ReferencedModuleVars<core::ir::Module> referenced_module_vars{ir};
// The name of the module-scope variables structure.
static constexpr const char* kModuleVarsName = "tint_module_vars";
@@ -172,7 +172,7 @@
/// @returns the structure that holds the module-scope variables
core::ir::Value* AddModuleVarsToEntryPoint(
core::ir::Function* func,
- const core::ir::ReferencedModuleVars::VarSet& referenced_vars) {
+ const core::ir::ReferencedModuleVars<core::ir::Module>::VarSet& referenced_vars) {
core::ir::Value* module_var_struct = nullptr;
core::ir::FunctionParam* workgroup_allocation_param = nullptr;
Vector<core::type::Manager::StructMemberDesc, 4> workgroup_struct_members;
diff --git a/src/tint/lang/msl/writer/raise/simd_ballot.cc b/src/tint/lang/msl/writer/raise/simd_ballot.cc
index 565d85d..1b4c84c 100644
--- a/src/tint/lang/msl/writer/raise/simd_ballot.cc
+++ b/src/tint/lang/msl/writer/raise/simd_ballot.cc
@@ -30,7 +30,7 @@
#include <utility>
#include "src/tint/lang/core/ir/builder.h"
-#include "src/tint/lang/core/ir/transform/common/referenced_module_vars.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/ir/validator.h"
#include "src/tint/lang/msl/ir/builtin_call.h"
@@ -68,9 +68,10 @@
}
// Set the subgroup size mask value from all entry points that use it.
- core::ir::ReferencedModuleVars refs(ir, [&](const core::ir::Var* var) { //
- return var == subgroup_size_mask;
- });
+ core::ir::ReferencedModuleVars<core::ir::Module> refs(ir,
+ [&](const core::ir::Var* var) { //
+ return var == subgroup_size_mask;
+ });
for (auto func : ir.functions) {
if (func->Stage() != core::ir::Function::PipelineStage::kUndefined) {
if (refs.TransitiveReferences(func).Contains(subgroup_size_mask)) {
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.bazel b/src/tint/lang/spirv/reader/lower/BUILD.bazel
index 5d99ad6..06eec9c 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.bazel
+++ b/src/tint/lang/spirv/reader/lower/BUILD.bazel
@@ -54,7 +54,6 @@
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
"//src/tint/lang/core/ir",
- "//src/tint/lang/core/ir/transform/common",
"//src/tint/lang/core/type",
"//src/tint/utils/containers",
"//src/tint/utils/diagnostic",
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.cmake b/src/tint/lang/spirv/reader/lower/BUILD.cmake
index 9758df7..3bd17b4 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.cmake
+++ b/src/tint/lang/spirv/reader/lower/BUILD.cmake
@@ -53,7 +53,6 @@
tint_lang_core_constant
tint_lang_core_intrinsic
tint_lang_core_ir
- tint_lang_core_ir_transform_common
tint_lang_core_type
tint_utils_containers
tint_utils_diagnostic
diff --git a/src/tint/lang/spirv/reader/lower/BUILD.gn b/src/tint/lang/spirv/reader/lower/BUILD.gn
index b9adbf6..07df190 100644
--- a/src/tint/lang/spirv/reader/lower/BUILD.gn
+++ b/src/tint/lang/spirv/reader/lower/BUILD.gn
@@ -59,7 +59,6 @@
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
"${tint_src_dir}/lang/core/ir",
- "${tint_src_dir}/lang/core/ir/transform/common",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/utils/containers",
"${tint_src_dir}/utils/diagnostic",
diff --git a/src/tint/lang/spirv/reader/lower/shader_io.cc b/src/tint/lang/spirv/reader/lower/shader_io.cc
index 7f402d6..7fc8d18 100644
--- a/src/tint/lang/spirv/reader/lower/shader_io.cc
+++ b/src/tint/lang/spirv/reader/lower/shader_io.cc
@@ -31,7 +31,7 @@
#include "src/tint/lang/core/ir/builder.h"
#include "src/tint/lang/core/ir/module.h"
-#include "src/tint/lang/core/ir/transform/common/referenced_module_vars.h"
+#include "src/tint/lang/core/ir/referenced_module_vars.h"
#include "src/tint/lang/core/ir/validator.h"
namespace tint::spirv::reader::lower {
@@ -62,7 +62,7 @@
Hashset<core::ir::Var*, 4> output_variables{};
/// The mapping from functions to their transitively referenced output variables.
- core::ir::ReferencedModuleVars referenced_output_vars{
+ core::ir::ReferencedModuleVars<core::ir::Module> referenced_output_vars{
ir, [](const core::ir::Var* var) {
auto* view = var->Result(0)->Type()->As<core::type::MemoryView>();
return view && view->AddressSpace() == core::AddressSpace::kOut;
diff --git a/src/tint/lang/spirv/reader/parser/function_test.cc b/src/tint/lang/spirv/reader/parser/function_test.cc
index d344063..1790734 100644
--- a/src/tint/lang/spirv/reader/parser/function_test.cc
+++ b/src/tint/lang/spirv/reader/parser/function_test.cc
@@ -130,7 +130,7 @@
)");
}
-TEST_F(SpirvParserTest, VertexShader) {
+TEST_F(SpirvParserTest, DISABLED_VertexShader) {
EXPECT_IR(R"(
OpCapability Shader
OpMemoryModel Logical GLSL450
diff --git a/src/tint/lang/spirv/writer/function_test.cc b/src/tint/lang/spirv/writer/function_test.cc
index f566d7e..9058a18 100644
--- a/src/tint/lang/spirv/writer/function_test.cc
+++ b/src/tint/lang/spirv/writer/function_test.cc
@@ -143,25 +143,51 @@
}
TEST_F(SpirvWriterTest, Function_EntryPoint_Vertex) {
- auto* func = b.Function("main", ty.void_(), core::ir::Function::PipelineStage::kVertex);
+ auto* func = b.Function("main", ty.vec4<f32>(), core::ir::Function::PipelineStage::kVertex);
+ func->SetReturnBuiltin(core::BuiltinValue::kPosition);
b.Append(func->Block(), [&] { //
- b.Return(func);
+ b.Return(func, b.Zero<vec4<f32>>());
});
ASSERT_TRUE(Generate()) << Error() << output_;
EXPECT_INST(R"(
- OpEntryPoint Vertex %main "main"
+ OpEntryPoint Vertex %main "main" %main_position_Output %main___point_size_Output
; Debug Information
- OpName %main "main" ; id %1
+ OpName %main_position_Output "main_position_Output" ; id %1
+ OpName %main___point_size_Output "main___point_size_Output" ; id %5
+ OpName %main_inner "main_inner" ; id %7
+ OpName %main "main" ; id %11
+
+ ; Annotations
+ OpDecorate %main_position_Output BuiltIn Position
+ OpDecorate %main___point_size_Output BuiltIn PointSize
; Types, variables and constants
+ %float = OpTypeFloat 32
+ %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output ; BuiltIn Position
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output ; BuiltIn PointSize
+ %8 = OpTypeFunction %v4float
+ %10 = OpConstantNull %v4float
%void = OpTypeVoid
- %3 = OpTypeFunction %void
+ %13 = OpTypeFunction %void
+ %float_1 = OpConstant %float 1
+
+ ; Function main_inner
+ %main_inner = OpFunction %v4float None %8
+ %9 = OpLabel
+ OpReturnValue %10
+ OpFunctionEnd
; Function main
- %main = OpFunction %void None %3
- %4 = OpLabel
+ %main = OpFunction %void None %13
+ %14 = OpLabel
+ %15 = OpFunctionCall %v4float %main_inner
+ OpStore %main_position_Output %15 None
+ OpStore %main___point_size_Output %float_1 None
OpReturn
OpFunctionEnd
)");