[spirv-fuzz] Generate resource bindings configuration.
The fuzzer passes in randomized options to the SPIR-V writer. The
resource bindings are required to match up to the module itself, so
replace the random resource_binding options with generated options.
Fixed: 442161264
Change-Id: Ife9cc326f61a8af52e7930b0ce17728a0e9f8673
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/260734
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 9d1953b..a6208a9 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -41,12 +41,12 @@
#include "spirv-tools/libspirv.hpp"
#endif // TINT_BUILD_SPV_READER || TINT_BUILD_SPV_WRITER
-#include "src/tint/api/common/resource_binding_config.h"
#include "src/tint/api/tint.h"
#include "src/tint/cmd/common/helper.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/load.h"
+#include "src/tint/lang/core/ir/transform/resource_binding_helper.h"
#include "src/tint/lang/core/ir/transform/single_entry_point.h"
#include "src/tint/lang/core/ir/transform/substitute_overrides.h"
#include "src/tint/lang/core/ir/var.h"
@@ -775,74 +775,6 @@
}
TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE);
-[[maybe_unused]] std::optional<tint::ResourceBindingConfig> GenerateResourceBindingConfig(
- tint::core::ir::Module& mod) {
- tint::ResourceBindingConfig cfg;
-
- uint32_t max_group = 0;
- std::vector<tint::core::ir::Var*> resource_bindings;
-
- for (auto* inst : *mod.root_block) {
- auto* var = inst->As<tint::core::ir::Var>();
- if (!var) {
- continue;
- }
- if (!var->BindingPoint().has_value()) {
- continue;
- }
-
- auto* ty = var->Result()->Type()->UnwrapPtr()->As<tint::core::type::ResourceBinding>();
- if (!ty) {
- continue;
- }
- resource_bindings.push_back(var);
-
- max_group = std::max(max_group, var->BindingPoint()->group);
- }
- if (resource_bindings.empty()) {
- return std::nullopt;
- }
-
- max_group += 1;
- uint32_t binding = 0;
- for (auto* var : resource_bindings) {
- tint::ResourceBindingInfo info{
- .storage_buffer_binding = tint::BindingPoint{.group = max_group, .binding = binding++},
- .default_binding_type_order = {},
- };
-
- std::vector<tint::core::ir::Value*> to_check = {var->Result()};
- while (!to_check.empty()) {
- auto* next = to_check.back();
- to_check.pop_back();
-
- for (auto& usage : next->UsagesUnsorted()) {
- tint::Switch(
- usage->instruction,
- [&](tint::core::ir::Load* l) { to_check.push_back(l->Result()); },
- [&](tint::core::ir::CoreBuiltinCall* call) {
- if (call->Func() != tint::core::BuiltinFn::kHasBinding &&
- call->Func() != tint::core::BuiltinFn::kGetBinding) {
- return;
- }
-
- auto exp = call->ExplicitTemplateParams();
- TINT_ASSERT(exp.Length() == 1);
- info.default_binding_type_order.push_back(
- tint::core::type::TypeToResourceType(exp[0]));
- },
- TINT_ICE_ON_NO_MATCH);
- }
- }
- // Sort so we get stable generated results
- std::sort(info.default_binding_type_order.begin(), info.default_binding_type_order.end());
-
- cfg.bindings.insert({var->BindingPoint().value(), std::move(info)});
- }
-
- return cfg;
-}
-
[[maybe_unused]] tint::diag::Result<tint::core::ir::transform::SubstituteOverridesConfig>
CreateOverrideMap(const Options& options, tint::inspector::Inspector& inspector) {
auto override_names = inspector.GetNamedOverrideIds();
@@ -945,7 +877,7 @@
}
gen_options.bindings = tint::spirv::writer::GenerateBindings(ir);
- gen_options.resource_binding = GenerateResourceBindingConfig(ir);
+ gen_options.resource_binding = tint::core::ir::transform::GenerateResourceBindingConfig(ir);
// Enable the Vulkan Memory Model if needed.
for (auto* ty : ir.Types()) {
diff --git a/src/tint/lang/core/ir/transform/BUILD.bazel b/src/tint/lang/core/ir/transform/BUILD.bazel
index 64ff860..3bf2b3e 100644
--- a/src/tint/lang/core/ir/transform/BUILD.bazel
+++ b/src/tint/lang/core/ir/transform/BUILD.bazel
@@ -62,6 +62,7 @@
"remove_terminator_args.cc",
"rename_conflicts.cc",
"resource_binding.cc",
+ "resource_binding_helper.cc",
"robustness.cc",
"shader_io.cc",
"signed_integer_polyfill.cc",
@@ -98,6 +99,7 @@
"remove_terminator_args.h",
"rename_conflicts.h",
"resource_binding.h",
+ "resource_binding_helper.h",
"robustness.h",
"shader_io.h",
"signed_integer_polyfill.h",
diff --git a/src/tint/lang/core/ir/transform/BUILD.cmake b/src/tint/lang/core/ir/transform/BUILD.cmake
index 5ea8d42..d980be2 100644
--- a/src/tint/lang/core/ir/transform/BUILD.cmake
+++ b/src/tint/lang/core/ir/transform/BUILD.cmake
@@ -86,6 +86,8 @@
lang/core/ir/transform/rename_conflicts.h
lang/core/ir/transform/resource_binding.cc
lang/core/ir/transform/resource_binding.h
+ lang/core/ir/transform/resource_binding_helper.cc
+ lang/core/ir/transform/resource_binding_helper.h
lang/core/ir/transform/robustness.cc
lang/core/ir/transform/robustness.h
lang/core/ir/transform/shader_io.cc
diff --git a/src/tint/lang/core/ir/transform/BUILD.gn b/src/tint/lang/core/ir/transform/BUILD.gn
index 689cef3..249e3ed 100644
--- a/src/tint/lang/core/ir/transform/BUILD.gn
+++ b/src/tint/lang/core/ir/transform/BUILD.gn
@@ -92,6 +92,8 @@
"rename_conflicts.h",
"resource_binding.cc",
"resource_binding.h",
+ "resource_binding_helper.cc",
+ "resource_binding_helper.h",
"robustness.cc",
"robustness.h",
"shader_io.cc",
diff --git a/src/tint/lang/core/ir/transform/resource_binding_helper.cc b/src/tint/lang/core/ir/transform/resource_binding_helper.cc
new file mode 100644
index 0000000..fa962ef
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/resource_binding_helper.cc
@@ -0,0 +1,107 @@
+// Copyright 2025 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/resource_binding_helper.h"
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "src/tint/lang/core/ir/core_builtin_call.h"
+#include "src/tint/lang/core/ir/load.h"
+#include "src/tint/lang/core/ir/var.h"
+#include "src/tint/lang/core/type/resource_type.h"
+#include "src/tint/utils/rtti/switch.h"
+
+namespace tint::core::ir::transform {
+
+std::optional<ResourceBindingConfig> GenerateResourceBindingConfig(Module& mod) {
+ ResourceBindingConfig cfg;
+
+ uint32_t max_group = 0;
+ std::vector<Var*> resource_bindings;
+
+ for (auto* inst : *mod.root_block) {
+ auto* var = inst->As<Var>();
+ if (!var) {
+ continue;
+ }
+ if (!var->BindingPoint().has_value()) {
+ continue;
+ }
+
+ auto* ty = var->Result()->Type()->UnwrapPtr()->As<type::ResourceBinding>();
+ if (!ty) {
+ continue;
+ }
+ resource_bindings.push_back(var);
+
+ max_group = std::max(max_group, var->BindingPoint()->group);
+ }
+ if (resource_bindings.empty()) {
+ return std::nullopt;
+ }
+
+ max_group += 1;
+ uint32_t binding = 0;
+ for (auto* var : resource_bindings) {
+ ResourceBindingInfo info{
+ .storage_buffer_binding = BindingPoint{.group = max_group, .binding = binding++},
+ .default_binding_type_order = {},
+ };
+
+ std::vector<Value*> to_check = {var->Result()};
+ while (!to_check.empty()) {
+ auto* next = to_check.back();
+ to_check.pop_back();
+
+ for (auto& usage : next->UsagesUnsorted()) {
+ Switch(
+ usage->instruction, [&](Load* l) { to_check.push_back(l->Result()); },
+ [&](CoreBuiltinCall* call) {
+ if (call->Func() != BuiltinFn::kHasBinding &&
+ call->Func() != BuiltinFn::kGetBinding) {
+ return;
+ }
+
+ auto exp = call->ExplicitTemplateParams();
+ TINT_ASSERT(exp.Length() == 1);
+ info.default_binding_type_order.push_back(type::TypeToResourceType(exp[0]));
+ },
+ TINT_ICE_ON_NO_MATCH);
+ }
+ }
+ // Sort so we get stable generated results
+ std::sort(info.default_binding_type_order.begin(), info.default_binding_type_order.end());
+
+ cfg.bindings.insert({var->BindingPoint().value(), std::move(info)});
+ }
+
+ return cfg;
+}
+
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/resource_binding_helper.h b/src/tint/lang/core/ir/transform/resource_binding_helper.h
new file mode 100644
index 0000000..ee087a9
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/resource_binding_helper.h
@@ -0,0 +1,43 @@
+// Copyright 2025 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_RESOURCE_BINDING_HELPER_H_
+#define SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_BINDING_HELPER_H_
+
+#include <optional>
+
+#include "src/tint/api/common/resource_binding_config.h"
+#include "src/tint/lang/core/ir/module.h"
+
+namespace tint::core::ir::transform {
+
+std::optional<tint::ResourceBindingConfig> GenerateResourceBindingConfig(
+ tint::core::ir::Module& mod);
+
+}
+
+#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_RESOURCE_BINDING_HELPER_H_
diff --git a/src/tint/lang/spirv/writer/BUILD.cmake b/src/tint/lang/spirv/writer/BUILD.cmake
index 36ffd03..e2fe748 100644
--- a/src/tint/lang/spirv/writer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/BUILD.cmake
@@ -174,6 +174,7 @@
tint_lang_core
tint_lang_core_constant
tint_lang_core_ir
+ tint_lang_core_ir_transform
tint_lang_core_type
tint_utils
tint_utils_bytes
diff --git a/src/tint/lang/spirv/writer/BUILD.gn b/src/tint/lang/spirv/writer/BUILD.gn
index 8121453..c01e8b7 100644
--- a/src/tint/lang/spirv/writer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/BUILD.gn
@@ -156,6 +156,7 @@
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/ir",
+ "${tint_src_dir}/lang/core/ir/transform",
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/utils",
"${tint_src_dir}/utils/bytes",
diff --git a/src/tint/lang/spirv/writer/writer_fuzz.cc b/src/tint/lang/spirv/writer/writer_fuzz.cc
index bce4dc8..f74299d 100644
--- a/src/tint/lang/spirv/writer/writer_fuzz.cc
+++ b/src/tint/lang/spirv/writer/writer_fuzz.cc
@@ -29,6 +29,7 @@
#include "src/tint/cmd/fuzz/ir/fuzz.h"
#include "src/tint/lang/core/ir/disassembler.h"
+#include "src/tint/lang/core/ir/transform/resource_binding_helper.h"
#include "src/tint/lang/spirv/validate/validate.h"
#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
#include "src/tint/lang/spirv/writer/printer/printer.h"
@@ -43,6 +44,8 @@
}
options.bindings = GenerateBindings(module);
+ options.resource_binding = tint::core::ir::transform::GenerateResourceBindingConfig(module);
+
auto output = Generate(module, options);
if (output != Success) {
TINT_ICE() << "Generate() failed after CanGenerate() succeeded: "