Using binding information for SPIR-V/Tint interface
This CL removes the explicit external texture and multiplanar options
from the SPIR-V writer and instead uses `binding` information which is
populated by Dawn.
On the Tint side the needed transform data is created from the requested
result from Dawn.
Bug: tint:1501
Change-Id: I36ce6272b3b4e8e4b47a0bcaf59bec193acb7038
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/152864
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/dawn/native/StreamImplTint.cpp b/src/dawn/native/StreamImplTint.cpp
index 1b7db58..3cc052c 100644
--- a/src/dawn/native/StreamImplTint.cpp
+++ b/src/dawn/native/StreamImplTint.cpp
@@ -57,6 +57,32 @@
return {};
}
+#if TINT_BUILD_SPV_WRITER
+// static
+template <>
+void stream::Stream<tint::spirv::writer::Bindings>::Write(
+ stream::Sink* sink,
+ const tint::spirv::writer::Bindings& bindings) {
+ StreamInTintObject(bindings, sink);
+}
+
+// static
+template <>
+void stream::Stream<tint::spirv::writer::binding::ExternalTexture>::Write(
+ stream::Sink* sink,
+ const tint::spirv::writer::binding::ExternalTexture& et) {
+ StreamInTintObject(et, sink);
+}
+
+// static
+template <>
+void stream::Stream<tint::spirv::writer::binding::BindingInfo>::Write(
+ stream::Sink* sink,
+ const tint::spirv::writer::binding::BindingInfo& point) {
+ StreamInTintObject(point, sink);
+}
+#endif // TINT_BUILD_SPV_WRITER
+
// static
template <>
void stream::Stream<tint::ExternalTextureOptions::BindingPoints>::Write(
diff --git a/src/dawn/native/vulkan/ShaderModuleVk.cpp b/src/dawn/native/vulkan/ShaderModuleVk.cpp
index 79df5a8..a1ac4c3 100644
--- a/src/dawn/native/vulkan/ShaderModuleVk.cpp
+++ b/src/dawn/native/vulkan/ShaderModuleVk.cpp
@@ -165,11 +165,12 @@
ShaderModule::~ShaderModule() = default;
+#if TINT_BUILD_SPV_WRITER
+
#define SPIRV_COMPILATION_REQUEST_MEMBERS(X) \
X(SingleShaderStage, stage) \
X(const tint::Program*, inputProgram) \
- X(tint::BindingRemapperOptions, bindingRemapper) \
- X(tint::ExternalTextureOptions, externalTextureOptions) \
+ X(tint::spirv::writer::Bindings, bindings) \
X(std::optional<tint::ast::transform::SubstituteOverride::Config>, substituteOverrideConfig) \
X(LimitsForCompilationRequest, limits) \
X(std::string_view, entryPointName) \
@@ -187,6 +188,8 @@
DAWN_MAKE_CACHE_REQUEST(SpirvCompilationRequest, SPIRV_COMPILATION_REQUEST_MEMBERS);
#undef SPIRV_COMPILATION_REQUEST_MEMBERS
+#endif // TINT_BUILD_SPV_WRITER
+
ResultOrError<ShaderModule::ModuleAndSpirv> ShaderModule::GetHandleAndSpirv(
SingleShaderStage stage,
const ProgrammableStage& programmableStage,
@@ -207,60 +210,95 @@
return std::move(*handleAndSpirv);
}
+#if TINT_BUILD_SPV_WRITER
// Creation of module and spirv is deferred to this point when using tint generator
- // Remap BindingNumber to BindingIndex in WGSL shader
- using BindingPoint = tint::BindingPoint;
-
- tint::BindingRemapperOptions bindingRemapper;
+ tint::spirv::writer::Bindings bindings;
const BindingInfoArray& moduleBindingInfo =
GetEntryPoint(programmableStage.entryPoint.c_str()).bindings;
for (BindGroupIndex group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
const BindGroupLayout* bgl = ToBackend(layout->GetBindGroupLayout(group));
- const auto& groupBindingInfo = moduleBindingInfo[group];
- for (const auto& [binding, _] : groupBindingInfo) {
- BindingIndex bindingIndex = bgl->GetBindingIndex(binding);
- BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
- static_cast<uint32_t>(binding)};
- BindingPoint dstBindingPoint{static_cast<uint32_t>(group),
- static_cast<uint32_t>(bindingIndex)};
- if (srcBindingPoint != dstBindingPoint) {
- bindingRemapper.binding_points.emplace(srcBindingPoint, dstBindingPoint);
+ for (const auto& [binding, bindingInfo] : moduleBindingInfo[group]) {
+ tint::BindingPoint srcBindingPoint{static_cast<uint32_t>(group),
+ static_cast<uint32_t>(binding)};
+
+ tint::BindingPoint dstBindingPoint{
+ static_cast<uint32_t>(group), static_cast<uint32_t>(bgl->GetBindingIndex(binding))};
+
+ switch (bindingInfo.bindingType) {
+ case BindingInfoType::Buffer:
+ switch (bindingInfo.buffer.type) {
+ case wgpu::BufferBindingType::Uniform:
+ bindings.uniform.emplace(
+ srcBindingPoint,
+ tint::spirv::writer::binding::Uniform{dstBindingPoint.group,
+ dstBindingPoint.binding});
+ break;
+ case kInternalStorageBufferBinding:
+ case wgpu::BufferBindingType::Storage:
+ case wgpu::BufferBindingType::ReadOnlyStorage:
+ bindings.storage.emplace(
+ srcBindingPoint,
+ tint::spirv::writer::binding::Storage{dstBindingPoint.group,
+ dstBindingPoint.binding});
+ break;
+ case wgpu::BufferBindingType::Undefined:
+ DAWN_UNREACHABLE();
+ break;
+ }
+ break;
+ case BindingInfoType::Sampler:
+ bindings.sampler.emplace(srcBindingPoint,
+ tint::spirv::writer::binding::Sampler{
+ dstBindingPoint.group, dstBindingPoint.binding});
+ break;
+ case BindingInfoType::Texture:
+ bindings.texture.emplace(srcBindingPoint,
+ tint::spirv::writer::binding::Texture{
+ dstBindingPoint.group, dstBindingPoint.binding});
+ break;
+ case BindingInfoType::StorageTexture:
+ bindings.storage_texture.emplace(
+ srcBindingPoint, tint::spirv::writer::binding::StorageTexture{
+ dstBindingPoint.group, dstBindingPoint.binding});
+ break;
+ case BindingInfoType::ExternalTexture: {
+ const auto& bindingMap = bgl->GetExternalTextureBindingExpansionMap();
+ const auto& expansion = bindingMap.find(binding);
+ DAWN_ASSERT(expansion != bindingMap.end());
+
+ const auto& bindingExpansion = expansion->second;
+ tint::spirv::writer::binding::BindingInfo plane0{
+ static_cast<uint32_t>(group),
+ static_cast<uint32_t>(bgl->GetBindingIndex(bindingExpansion.plane0))};
+ tint::spirv::writer::binding::BindingInfo plane1{
+ static_cast<uint32_t>(group),
+ static_cast<uint32_t>(bgl->GetBindingIndex(bindingExpansion.plane1))};
+ tint::spirv::writer::binding::BindingInfo metadata{
+ static_cast<uint32_t>(group),
+ static_cast<uint32_t>(bgl->GetBindingIndex(bindingExpansion.params))};
+
+ bindings.external_texture.emplace(
+ srcBindingPoint,
+ tint::spirv::writer::binding::ExternalTexture{metadata, plane0, plane1});
+ break;
+ }
}
}
}
- // Transform external textures into the binding locations specified in the bgl
- // TODO(dawn:1082): Replace this block with BuildExternalTextureTransformBindings.
- tint::ExternalTextureOptions externalTextureOptions;
- for (BindGroupIndex i : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
- const BindGroupLayoutInternalBase* bgl = layout->GetBindGroupLayout(i);
-
- for (const auto& [_, expansion] : bgl->GetExternalTextureBindingExpansionMap()) {
- externalTextureOptions
- .bindings_map[{static_cast<uint32_t>(i),
- static_cast<uint32_t>(bgl->GetBindingIndex(expansion.plane0))}] = {
- {static_cast<uint32_t>(i),
- static_cast<uint32_t>(bgl->GetBindingIndex(expansion.plane1))},
- {static_cast<uint32_t>(i),
- static_cast<uint32_t>(bgl->GetBindingIndex(expansion.params))}};
- }
- }
-
std::optional<tint::ast::transform::SubstituteOverride::Config> substituteOverrideConfig;
if (!programmableStage.metadata->overrides.empty()) {
substituteOverrideConfig = BuildSubstituteOverridesTransformConfig(programmableStage);
}
-#if TINT_BUILD_SPV_WRITER
SpirvCompilationRequest req = {};
req.stage = stage;
req.inputProgram = GetTintProgram();
- req.bindingRemapper = std::move(bindingRemapper);
- req.externalTextureOptions = std::move(externalTextureOptions);
+ req.bindings = std::move(bindings);
req.entryPointName = programmableStage.entryPoint;
req.isRobustnessEnabled = GetDevice()->IsRobustnessEnabled();
req.disableWorkgroupInit = GetDevice()->IsToggleEnabled(Toggle::DisableWorkgroupInit);
@@ -348,8 +386,7 @@
options.disable_workgroup_init = r.disableWorkgroupInit;
options.use_zero_initialize_workgroup_memory_extension =
r.useZeroInitializeWorkgroupMemoryExtension;
- options.binding_remapper_options = r.bindingRemapper;
- options.external_texture_options = r.externalTextureOptions;
+ options.bindings = r.bindings;
options.disable_image_robustness = r.disableImageRobustness;
options.disable_runtime_sized_array_index_clamping =
r.disableRuntimeSizedArrayIndexClamping;
diff --git a/src/tint/cmd/loopy/BUILD.bazel b/src/tint/cmd/loopy/BUILD.bazel
index 194e728..4f75977 100644
--- a/src/tint/cmd/loopy/BUILD.bazel
+++ b/src/tint/cmd/loopy/BUILD.bazel
@@ -39,6 +39,7 @@
"//src/tint/lang/core/type",
"//src/tint/lang/hlsl/writer/common",
"//src/tint/lang/spirv/reader/common",
+ "//src/tint/lang/spirv/writer/helpers",
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/helpers",
diff --git a/src/tint/cmd/loopy/BUILD.cmake b/src/tint/cmd/loopy/BUILD.cmake
index 86eee38..0370b97 100644
--- a/src/tint/cmd/loopy/BUILD.cmake
+++ b/src/tint/cmd/loopy/BUILD.cmake
@@ -40,6 +40,7 @@
tint_lang_core_type
tint_lang_hlsl_writer_common
tint_lang_spirv_reader_common
+ tint_lang_spirv_writer_helpers
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_helpers
diff --git a/src/tint/cmd/loopy/BUILD.gn b/src/tint/cmd/loopy/BUILD.gn
index 4c54f72..4ca63ad 100644
--- a/src/tint/cmd/loopy/BUILD.gn
+++ b/src/tint/cmd/loopy/BUILD.gn
@@ -39,6 +39,7 @@
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/hlsl/writer/common",
"${tint_src_dir}/lang/spirv/reader/common",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/helpers",
diff --git a/src/tint/cmd/loopy/main.cc b/src/tint/cmd/loopy/main.cc
index e488fad..a12fbc6 100644
--- a/src/tint/cmd/loopy/main.cc
+++ b/src/tint/cmd/loopy/main.cc
@@ -37,6 +37,7 @@
#endif // TINT_BUILD_SPV_READER
#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
#include "src/tint/lang/spirv/writer/writer.h"
#endif // TINT_BUILD_SPV_WRITER
@@ -192,8 +193,7 @@
bool GenerateSpirv(const tint::Program& program) {
#if TINT_BUILD_SPV_WRITER
tint::spirv::writer::Options gen_options;
- gen_options.external_texture_options.bindings_map =
- tint::cmd::GenerateExternalTextureBindings(program);
+ gen_options.bindings = tint::spirv::writer::GenerateBindings(program);
auto result = tint::spirv::writer::Generate(program, gen_options);
if (!result) {
tint::cmd::PrintWGSL(std::cerr, program);
diff --git a/src/tint/cmd/tint/BUILD.bazel b/src/tint/cmd/tint/BUILD.bazel
index 321c15e..ad986d1 100644
--- a/src/tint/cmd/tint/BUILD.bazel
+++ b/src/tint/cmd/tint/BUILD.bazel
@@ -39,6 +39,7 @@
"//src/tint/lang/core/type",
"//src/tint/lang/hlsl/writer/common",
"//src/tint/lang/spirv/reader/common",
+ "//src/tint/lang/spirv/writer/helpers",
"//src/tint/lang/wgsl",
"//src/tint/lang/wgsl/ast",
"//src/tint/lang/wgsl/ast/transform",
diff --git a/src/tint/cmd/tint/BUILD.cmake b/src/tint/cmd/tint/BUILD.cmake
index 1d500ac..1f0dc3b 100644
--- a/src/tint/cmd/tint/BUILD.cmake
+++ b/src/tint/cmd/tint/BUILD.cmake
@@ -40,6 +40,7 @@
tint_lang_core_type
tint_lang_hlsl_writer_common
tint_lang_spirv_reader_common
+ tint_lang_spirv_writer_helpers
tint_lang_wgsl
tint_lang_wgsl_ast
tint_lang_wgsl_ast_transform
diff --git a/src/tint/cmd/tint/BUILD.gn b/src/tint/cmd/tint/BUILD.gn
index e6c897c..40b456b 100644
--- a/src/tint/cmd/tint/BUILD.gn
+++ b/src/tint/cmd/tint/BUILD.gn
@@ -39,6 +39,7 @@
"${tint_src_dir}/lang/core/type",
"${tint_src_dir}/lang/hlsl/writer/common",
"${tint_src_dir}/lang/spirv/reader/common",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
"${tint_src_dir}/lang/wgsl",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 73eae30..1506bce 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -65,6 +65,7 @@
#endif // TINT_BUILD_WGSL_READER
#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
#include "src/tint/lang/spirv/writer/writer.h"
#endif // TINT_BUILD_SPV_WRITER
@@ -579,8 +580,7 @@
tint::spirv::writer::Options gen_options;
gen_options.disable_robustness = !options.enable_robustness;
gen_options.disable_workgroup_init = options.disable_workgroup_init;
- gen_options.external_texture_options.bindings_map =
- tint::cmd::GenerateExternalTextureBindings(program);
+ gen_options.bindings = tint::spirv::writer::GenerateBindings(program);
gen_options.use_tint_ir = options.use_ir;
auto result = tint::spirv::writer::Generate(program, gen_options);
diff --git a/src/tint/fuzzers/BUILD.gn b/src/tint/fuzzers/BUILD.gn
index a482492..1f576ad 100644
--- a/src/tint/fuzzers/BUILD.gn
+++ b/src/tint/fuzzers/BUILD.gn
@@ -74,6 +74,7 @@
"${tint_src_dir}/lang/hlsl/writer",
"${tint_src_dir}/lang/msl/writer",
"${tint_src_dir}/lang/spirv/writer",
+ "${tint_src_dir}/lang/spirv/writer/helpers",
"${tint_src_dir}/lang/wgsl/ast",
"${tint_src_dir}/lang/wgsl/ast/transform",
"${tint_src_dir}/lang/wgsl/helpers",
diff --git a/src/tint/fuzzers/CMakeLists.txt b/src/tint/fuzzers/CMakeLists.txt
index f9c8747..97674f2 100644
--- a/src/tint/fuzzers/CMakeLists.txt
+++ b/src/tint/fuzzers/CMakeLists.txt
@@ -38,6 +38,7 @@
tint_spvheaders_compile_options(${NAME})
tint_spvtools_compile_options(${NAME})
endif()
+ target_link_libraries(${NAME} PRIVATE tint_lang_spirv_writer_helpers)
target_compile_options(${NAME} PRIVATE -Wno-missing-prototypes)
endfunction()
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
index f822030..85881e4 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_ast_fuzzer/CMakeLists.txt
@@ -14,7 +14,7 @@
function(add_tint_ast_fuzzer NAME)
add_executable(${NAME} ${NAME}.cc ${AST_FUZZER_SOURCES})
- target_link_libraries(${NAME} PRIVATE libtint_ast_fuzzer)
+ target_link_libraries(${NAME} PRIVATE libtint_ast_fuzzer tint_lang_spirv_writer_helpers)
tint_fuzzer_compile_options(${NAME})
if(TINT_BUILD_SPV_READER OR TINT_BUILD_SPV_WRITER)
tint_spvheaders_compile_options(${NAME})
diff --git a/src/tint/fuzzers/tint_common_fuzzer.cc b/src/tint/fuzzers/tint_common_fuzzer.cc
index 1b6bd5a..582b259 100644
--- a/src/tint/fuzzers/tint_common_fuzzer.cc
+++ b/src/tint/fuzzers/tint_common_fuzzer.cc
@@ -41,6 +41,10 @@
#include "src/tint/utils/diagnostic/printer.h"
#include "src/tint/utils/math/hash.h"
+#if TINT_BUILD_SPV_WRITER
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
+#endif // TINT_BUILD_SPV_WRITER
+
namespace tint::fuzzers {
namespace {
@@ -244,10 +248,23 @@
}
}
+ switch (output_) {
+ case OutputFormat::kMSL:
+ break;
+ case OutputFormat::kHLSL:
+ break;
+ case OutputFormat::kSpv:
+#if TINT_BUILD_SPV_WRITER
+ options_spirv_.bindings = tint::spirv::writer::GenerateBindings(program);
+#endif // TINT_BUILD_SPV_WRITER
+ break;
+ case OutputFormat::kWGSL:
+ break;
+ }
+
// For the generates which use MultiPlanar, make sure the configuration options are provided so
// that the transformer will execute.
- if (output_ == OutputFormat::kMSL || output_ == OutputFormat::kHLSL ||
- output_ == OutputFormat::kSpv) {
+ if (output_ == OutputFormat::kMSL || output_ == OutputFormat::kHLSL) {
// Gather external texture binding information
// Collect next valid binding number per group
std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number;
@@ -284,7 +301,6 @@
break;
}
case OutputFormat::kSpv: {
- options_spirv_.external_texture_options.bindings_map = new_bindings_map;
break;
}
default:
diff --git a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
index f062d97..90e7e21 100644
--- a/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
+++ b/src/tint/fuzzers/tint_regex_fuzzer/CMakeLists.txt
@@ -14,7 +14,7 @@
function(add_tint_regex_fuzzer NAME)
add_executable(${NAME} ${NAME}.cc ${REGEX_FUZZER_SOURCES})
- target_link_libraries(${NAME} PRIVATE libtint_regex_fuzzer)
+ target_link_libraries(${NAME} PRIVATE libtint_regex_fuzzer tint_lang_spirv_writer_helpers)
tint_fuzzer_compile_options(${NAME})
tint_spvtools_compile_options(${NAME})
target_compile_definitions(${NAME} PRIVATE CUSTOM_MUTATOR)
diff --git a/src/tint/lang/spirv/writer/BUILD.bazel b/src/tint/lang/spirv/writer/BUILD.bazel
index 7c2a7b7..7220323 100644
--- a/src/tint/lang/spirv/writer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/BUILD.bazel
@@ -106,7 +106,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
@@ -155,7 +154,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/cmd/bench:bench",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
diff --git a/src/tint/lang/spirv/writer/BUILD.cmake b/src/tint/lang/spirv/writer/BUILD.cmake
index 953b266..c0169e9 100644
--- a/src/tint/lang/spirv/writer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/BUILD.cmake
@@ -24,6 +24,7 @@
include(lang/spirv/writer/ast_printer/BUILD.cmake)
include(lang/spirv/writer/ast_raise/BUILD.cmake)
include(lang/spirv/writer/common/BUILD.cmake)
+include(lang/spirv/writer/helpers/BUILD.cmake)
include(lang/spirv/writer/printer/BUILD.cmake)
include(lang/spirv/writer/raise/BUILD.cmake)
@@ -118,7 +119,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
@@ -175,7 +175,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_bench bench
tint_api_common
- tint_api_options
tint_cmd_bench_bench
tint_lang_core
tint_lang_core_constant
diff --git a/src/tint/lang/spirv/writer/BUILD.gn b/src/tint/lang/spirv/writer/BUILD.gn
index a816952..31d0875 100644
--- a/src/tint/lang/spirv/writer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/BUILD.gn
@@ -109,7 +109,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
@@ -159,7 +158,6 @@
deps = [
"${tint_src_dir}:google_benchmark",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/cmd/bench:bench",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel b/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
index 99c7cd5..22c6d85 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.bazel
@@ -109,7 +109,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake b/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
index 46151c0..81b45cd 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.cmake
@@ -115,7 +115,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_ast_printer_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
diff --git a/src/tint/lang/spirv/writer/ast_printer/BUILD.gn b/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
index c517b43..b855543 100644
--- a/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_printer/BUILD.gn
@@ -112,7 +112,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/type",
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
index fa7d322..e8d1c45 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
@@ -24,6 +24,7 @@
#include "src/tint/lang/spirv/writer/ast_raise/var_for_dynamic_index.h"
#include "src/tint/lang/spirv/writer/ast_raise/vectorize_matrix_conversions.h"
#include "src/tint/lang/spirv/writer/ast_raise/while_to_loop.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/wgsl/ast/transform/add_block_attribute.h"
#include "src/tint/lang/wgsl/ast/transform/add_empty_entry_point.h"
#include "src/tint/lang/wgsl/ast/transform/binding_remapper.h"
@@ -93,16 +94,21 @@
data.Add<ast::transform::Robustness::Config>(config);
}
+ ExternalTextureOptions external_texture_options{};
+ RemapperData remapper_data{};
+ PopulateRemapperAndMultiplanarOptions(options, remapper_data, external_texture_options);
+
// BindingRemapper must come before MultiplanarExternalTexture. Note, this is flipped to the
// other generators which run Multiplanar first and then binding remapper.
manager.Add<ast::transform::BindingRemapper>();
+
data.Add<ast::transform::BindingRemapper::Remappings>(
- options.binding_remapper_options.binding_points,
- std::unordered_map<BindingPoint, core::Access>{}, /* allow_collisions */ false);
+ remapper_data, std::unordered_map<BindingPoint, core::Access>{},
+ /* allow_collisions */ false);
// Note: it is more efficient for MultiplanarExternalTexture to come after Robustness
data.Add<ast::transform::MultiplanarExternalTexture::NewBindingPoints>(
- options.external_texture_options.bindings_map);
+ external_texture_options.bindings_map);
manager.Add<ast::transform::MultiplanarExternalTexture>();
{ // Builtin polyfills
diff --git a/src/tint/lang/spirv/writer/common/BUILD.bazel b/src/tint/lang/spirv/writer/common/BUILD.bazel
index bf196f2..ecd94ab 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/common/BUILD.bazel
@@ -31,6 +31,7 @@
"instruction.cc",
"module.cc",
"operand.cc",
+ "option_builder.cc",
],
hdrs = [
"binary_writer.h",
@@ -38,13 +39,14 @@
"instruction.h",
"module.h",
"operand.h",
+ "option_builder.h",
"options.h",
],
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/lang/core",
"//src/tint/utils/containers",
+ "//src/tint/utils/diagnostic",
"//src/tint/utils/ice",
"//src/tint/utils/macros",
"//src/tint/utils/math",
@@ -76,7 +78,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/common/BUILD.cmake b/src/tint/lang/spirv/writer/common/BUILD.cmake
index 086cac1..dcb2f58 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/common/BUILD.cmake
@@ -38,14 +38,16 @@
lang/spirv/writer/common/module.h
lang/spirv/writer/common/operand.cc
lang/spirv/writer/common/operand.h
+ lang/spirv/writer/common/option_builder.cc
+ lang/spirv/writer/common/option_builder.h
lang/spirv/writer/common/options.h
)
tint_target_add_dependencies(tint_lang_spirv_writer_common lib
tint_api_common
tint_api_options
- tint_lang_core
tint_utils_containers
+ tint_utils_diagnostic
tint_utils_ice
tint_utils_macros
tint_utils_math
@@ -81,7 +83,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_common_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
diff --git a/src/tint/lang/spirv/writer/common/BUILD.gn b/src/tint/lang/spirv/writer/common/BUILD.gn
index dc4970f..becae92 100644
--- a/src/tint/lang/spirv/writer/common/BUILD.gn
+++ b/src/tint/lang/spirv/writer/common/BUILD.gn
@@ -41,13 +41,15 @@
"module.h",
"operand.cc",
"operand.h",
+ "option_builder.cc",
+ "option_builder.h",
"options.h",
]
deps = [
"${tint_src_dir}/api/common",
"${tint_src_dir}/api/options",
- "${tint_src_dir}/lang/core",
"${tint_src_dir}/utils/containers",
+ "${tint_src_dir}/utils/diagnostic",
"${tint_src_dir}/utils/ice",
"${tint_src_dir}/utils/macros",
"${tint_src_dir}/utils/math",
@@ -78,7 +80,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/common/option_builder.cc b/src/tint/lang/spirv/writer/common/option_builder.cc
new file mode 100644
index 0000000..1bec1e9
--- /dev/null
+++ b/src/tint/lang/spirv/writer/common/option_builder.cc
@@ -0,0 +1,224 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
+
+#include "src/tint/utils/containers/hashset.h"
+
+namespace tint::spirv::writer {
+
+bool ValidateBindingOptions(const Options& options, diag::List& diagnostics) {
+ tint::Hashset<tint::BindingPoint, 8> seen_wgsl_bindings{};
+ tint::Hashset<binding::BindingInfo, 8> seen_spirv_bindings{};
+
+ auto wgsl_seen = [&diagnostics, &seen_wgsl_bindings](const tint::BindingPoint& info) -> bool {
+ if (seen_wgsl_bindings.Contains(info)) {
+ std::stringstream str;
+ str << "Found duplicate WGSL binding point: " << info;
+
+ diagnostics.add_error(diag::System::Writer, str.str());
+ return true;
+ }
+ seen_wgsl_bindings.Add(info);
+ return false;
+ };
+
+ auto spirv_seen = [&diagnostics,
+ &seen_spirv_bindings](const binding::BindingInfo& info) -> bool {
+ if (seen_spirv_bindings.Contains(info)) {
+ std::stringstream str;
+ str << "Found duplicate SPIR-V binding point: [group: " << info.group
+ << ", binding: " << info.binding << "]";
+ diagnostics.add_error(diag::System::Writer, str.str());
+ return true;
+ }
+ seen_spirv_bindings.Add(info);
+ return false;
+ };
+
+ auto valid = [&wgsl_seen, &spirv_seen](const auto& hsh) -> bool {
+ for (const auto it : hsh) {
+ const auto& src_binding = it.first;
+ const auto& dst_binding = it.second;
+
+ if (wgsl_seen(src_binding)) {
+ return false;
+ }
+
+ if (spirv_seen(dst_binding)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ if (!valid(options.bindings.uniform)) {
+ diagnostics.add_note(diag::System::Writer, "When processing uniform", {});
+ return false;
+ }
+ if (!valid(options.bindings.storage)) {
+ diagnostics.add_note(diag::System::Writer, "When processing storage", {});
+ return false;
+ }
+ if (!valid(options.bindings.texture)) {
+ diagnostics.add_note(diag::System::Writer, "When processing texture", {});
+ return false;
+ }
+ if (!valid(options.bindings.storage_texture)) {
+ diagnostics.add_note(diag::System::Writer, "When processing storage_texture", {});
+ return false;
+ }
+ if (!valid(options.bindings.sampler)) {
+ diagnostics.add_note(diag::System::Writer, "When processing sampler", {});
+ return false;
+ }
+
+ for (const auto it : options.bindings.external_texture) {
+ const auto& src_binding = it.first;
+ const auto& plane0 = it.second.plane0;
+ const auto& plane1 = it.second.plane1;
+ const auto& metadata = it.second.metadata;
+
+ // Validate with the actual source regardless of what the remapper will do
+ if (wgsl_seen(src_binding)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+
+ if (spirv_seen(plane0)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ if (spirv_seen(plane1)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ if (spirv_seen(metadata)) {
+ diagnostics.add_note(diag::System::Writer, "When processing external_texture", {});
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// The remapped binding data and external texture data need to coordinate in order to put things in
+// the correct place when we're done.
+//
+// When the data comes in we have a list of all WGSL origin (group,binding) pairs to SPIR-V
+// (group,binding) pairs in the `uniform`, `storage`, `texture`, and `sampler` arrays.
+//
+// The `external_texture` array stores a WGSL origin (group,binding) pair for the external textures
+// which provide `plane0`, `plane1`, and `metadata` SPIR-V (group,binding) pairs.
+//
+// If the remapper is run first, then the `external_texture` will end up being moved from the WGSL
+// point, or the SPIR-V point (or the `plane0` value). There will also, possibly, have been bindings
+// moved aside in order to place the `external_texture` bindings.
+//
+// If multiplanar runs first, care needs to be taken that when the texture is split and we create
+// `plane1` and `metadata` that they do not collide with existing bindings. If they would collide
+// then we need to place them elsewhere and have the remapper place them in the correct locations.
+//
+// # Example
+// WGSL:
+// @group(0) @binding(0) var<uniform> u: Uniforms;
+// @group(0) @binding(1) var s: sampler;
+// @group(0) @binding(2) var t: texture_external;
+//
+// Given that program, Dawn may decide to do the remappings such that:
+// * WGSL u (0, 0) -> SPIR-V (0, 1)
+// * WGSL s (0, 1) -> SPIR-V (0, 2)
+// * WGSL t (0, 2):
+// * plane0 -> SPIR-V (0, 3)
+// * plane1 -> SPIR-V (0, 4)
+// * metadata -> SPIR-V (0, 0)
+//
+// In this case, if we run binding remapper first, then tell multiplanar to look for the texture at
+// (0, 3) instead of the original (0, 2).
+//
+// If multiplanar runs first, then metadata (0, 0) needs to be placed elsewhere and then remapped
+// back to (0, 0) by the remapper. (Otherwise, we'll have two `@group(0) @binding(0)` items in the
+// program.)
+//
+// # Status
+// The below method assumes we run binding remapper first. So it will setup the binding data and
+// switch the value used by the multiplanar.
+void PopulateRemapperAndMultiplanarOptions(const Options& options,
+ RemapperData& remapper_data,
+ ExternalTextureOptions& external_texture) {
+ auto create_remappings = [&remapper_data](const auto& hsh) {
+ for (const auto it : hsh) {
+ const BindingPoint& src_binding_point = it.first;
+ const binding::Uniform& dst_binding_point = it.second;
+
+ // Bindings which go to the same slot in SPIR-V do not need to be re-bound.
+ if (src_binding_point.group == dst_binding_point.group &&
+ src_binding_point.binding == dst_binding_point.binding) {
+ continue;
+ }
+
+ remapper_data.emplace(src_binding_point,
+ BindingPoint{dst_binding_point.group, dst_binding_point.binding});
+ }
+ };
+
+ create_remappings(options.bindings.uniform);
+ create_remappings(options.bindings.storage);
+ create_remappings(options.bindings.texture);
+ create_remappings(options.bindings.storage_texture);
+ create_remappings(options.bindings.sampler);
+
+ // External textures are re-bound to their plane0 location
+ for (const auto it : options.bindings.external_texture) {
+ const BindingPoint& src_binding_point = it.first;
+ const binding::BindingInfo& plane0 = it.second.plane0;
+ const binding::BindingInfo& plane1 = it.second.plane1;
+ const binding::BindingInfo& metadata = it.second.metadata;
+
+ BindingPoint plane0_binding_point{plane0.group, plane0.binding};
+ BindingPoint plane1_binding_point{plane1.group, plane1.binding};
+ BindingPoint metadata_binding_point{metadata.group, metadata.binding};
+
+ // Use the re-bound spir-v plane0 value for the lookup key.
+ external_texture.bindings_map.emplace(
+ plane0_binding_point,
+ ExternalTextureOptions::BindingPoints{plane1_binding_point, metadata_binding_point});
+
+ // Bindings which go to the same slot in SPIR-V do not need to be re-bound.
+ if (src_binding_point.group == plane0.group &&
+ src_binding_point.binding == plane0.binding) {
+ continue;
+ }
+
+ remapper_data.emplace(src_binding_point, BindingPoint{plane0.group, plane0.binding});
+ }
+}
+
+} // namespace tint::spirv::writer
+
+namespace std {
+
+/// Custom std::hash specialization for tint::spirv::writer::binding::BindingInfo so
+/// they can be used as keys for std::unordered_map and std::unordered_set.
+template <>
+class hash<tint::spirv::writer::binding::BindingInfo> {
+ public:
+ /// @param info the binding to create a hash for
+ /// @return the hash value
+ inline std::size_t operator()(const tint::spirv::writer::binding::BindingInfo& info) const {
+ return tint::Hash(info.group, info.binding);
+ }
+};
+
+} // namespace std
diff --git a/src/tint/lang/spirv/writer/common/option_builder.h b/src/tint/lang/spirv/writer/common/option_builder.h
new file mode 100644
index 0000000..0187b48
--- /dev/null
+++ b/src/tint/lang/spirv/writer/common/option_builder.h
@@ -0,0 +1,44 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
+#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
+
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
+#include "src/tint/api/options/external_texture.h"
+#include "src/tint/lang/spirv/writer/common/options.h"
+#include "src/tint/utils/diagnostic/diagnostic.h"
+
+namespace tint::spirv::writer {
+
+using RemapperData = std::unordered_map<BindingPoint, BindingPoint>;
+
+/// @param options the options
+/// @returns true if the binding points are valid
+bool ValidateBindingOptions(const Options& options, diag::List& diagnostics);
+
+/// Populates data from the writer options for the remapper and external texture.
+/// @param options the writer options
+/// @param remapper_data where to put the remapper data
+/// @param external_texture where to store the external texture options
+/// Note, these are populated together because there are dependencies between the two types of data.
+void PopulateRemapperAndMultiplanarOptions(const Options& options,
+ RemapperData& remapper_data,
+ ExternalTextureOptions& external_texture);
+
+} // namespace tint::spirv::writer
+
+#endif // SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTION_BUILDER_H_
diff --git a/src/tint/lang/spirv/writer/common/options.h b/src/tint/lang/spirv/writer/common/options.h
index 57e81e8..4fe9652 100644
--- a/src/tint/lang/spirv/writer/common/options.h
+++ b/src/tint/lang/spirv/writer/common/options.h
@@ -15,11 +15,83 @@
#ifndef SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_
#define SRC_TINT_LANG_SPIRV_WRITER_COMMON_OPTIONS_H_
-#include "src/tint/api/options/binding_remapper.h"
-#include "src/tint/api/options/external_texture.h"
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
#include "src/tint/utils/reflection/reflection.h"
namespace tint::spirv::writer {
+namespace binding {
+
+/// Generic binding point
+struct BindingInfo {
+ /// The group
+ uint32_t group = 0;
+ /// The binding
+ uint32_t binding = 0;
+
+ /// Equality operator
+ /// @param rhs the BindingInfo to compare against
+ /// @returns true if this BindingInfo is equal to `rhs`
+ inline bool operator==(const BindingInfo& rhs) const {
+ return group == rhs.group && binding == rhs.binding;
+ }
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(group, binding);
+};
+using Uniform = BindingInfo;
+using Storage = BindingInfo;
+using Texture = BindingInfo;
+using StorageTexture = BindingInfo;
+using Sampler = BindingInfo;
+
+/// An external texture
+struct ExternalTexture {
+ /// Metadata
+ BindingInfo metadata{};
+ /// Plane0 binding data
+ BindingInfo plane0{};
+ /// Plane1 binding data
+ BindingInfo plane1{};
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(metadata, plane0, plane1);
+};
+
+} // namespace binding
+
+// Maps the WGSL binding point to the SPIR-V group,binding for uniforms
+using UniformBindings = std::unordered_map<BindingPoint, binding::Uniform>;
+// Maps the WGSL binding point to the SPIR-V group,binding for storage
+using StorageBindings = std::unordered_map<BindingPoint, binding::Storage>;
+// Maps the WGSL binding point to the SPIR-V group,binding for textures
+using TextureBindings = std::unordered_map<BindingPoint, binding::Texture>;
+// Maps the WGSL binding point to the SPIR-V group,binding for storage textures
+using StorageTextureBindings = std::unordered_map<BindingPoint, binding::StorageTexture>;
+// Maps the WGSL binding point to the SPIR-V group,binding for samplers
+using SamplerBindings = std::unordered_map<BindingPoint, binding::Sampler>;
+// Maps the WGSL binding point to the plane0, plane1, and metadata information for external textures
+using ExternalTextureBindings = std::unordered_map<BindingPoint, binding::ExternalTexture>;
+
+/// Binding information
+struct Bindings {
+ /// Uniform bindings
+ UniformBindings uniform{};
+ /// Storage bindings
+ StorageBindings storage{};
+ /// Texture bindings
+ TextureBindings texture{};
+ /// Storage texture bindings
+ StorageTextureBindings storage_texture{};
+ /// Sampler bindings
+ SamplerBindings sampler{};
+ /// External bindings
+ ExternalTextureBindings external_texture{};
+
+ /// Reflect the fields of this class so that it can be used by tint::ForeachField()
+ TINT_REFLECT(uniform, storage, texture, sampler, external_texture);
+};
/// Configuration options used for generating SPIR-V.
struct Options {
@@ -49,17 +121,14 @@
/// Set to `true` to generate SPIR-V via the Tint IR instead of from the AST.
bool use_tint_ir = false;
- /// Options used in the binding mappings for external textures
- ExternalTextureOptions external_texture_options = {};
-
- /// Options used in the bindings remapper
- BindingRemapperOptions binding_remapper_options = {};
-
/// Set to `true` to require `SPV_KHR_subgroup_uniform_control_flow` extension and
/// `SubgroupUniformControlFlowKHR` execution mode for compute stage entry points in generated
/// SPIRV module. Issue: dawn:464
bool experimental_require_subgroup_uniform_control_flow = false;
+ /// The bindings
+ Bindings bindings;
+
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
TINT_REFLECT(disable_robustness,
disable_image_robustness,
@@ -69,9 +138,8 @@
emit_vertex_point_size,
clamp_frag_depth,
use_tint_ir,
- external_texture_options,
- binding_remapper_options,
- experimental_require_subgroup_uniform_control_flow);
+ experimental_require_subgroup_uniform_control_flow,
+ bindings);
};
} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.bazel b/src/tint/lang/spirv/writer/helpers/BUILD.bazel
new file mode 100644
index 0000000..190110b
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.bazel
@@ -0,0 +1,70 @@
+# Copyright 2023 The Tint Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################################################################################
+# 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 = "helpers",
+ srcs = [
+ "generate_bindings.cc",
+ ],
+ hdrs = [
+ "generate_bindings.h",
+ ],
+ deps = [
+ "//src/tint/api/common",
+ "//src/tint/lang/core",
+ "//src/tint/lang/core/constant",
+ "//src/tint/lang/core/type",
+ "//src/tint/lang/wgsl",
+ "//src/tint/lang/wgsl/ast",
+ "//src/tint/lang/wgsl/program",
+ "//src/tint/lang/wgsl/sem",
+ "//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",
+ ] + select({
+ ":tint_build_spv_writer": [
+ "//src/tint/lang/spirv/writer/common",
+ ],
+ "//conditions:default": [],
+ }),
+ copts = COPTS,
+ visibility = ["//visibility:public"],
+)
+
+alias(
+ name = "tint_build_spv_writer",
+ actual = "//src/tint:tint_build_spv_writer_true",
+)
+
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.cmake b/src/tint/lang/spirv/writer/helpers/BUILD.cmake
new file mode 100644
index 0000000..31063c4
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.cmake
@@ -0,0 +1,61 @@
+# Copyright 2023 The Tint Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################################################################################
+# 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_spirv_writer_helpers
+# Kind: lib
+################################################################################
+tint_add_target(tint_lang_spirv_writer_helpers lib
+ lang/spirv/writer/helpers/generate_bindings.cc
+ lang/spirv/writer/helpers/generate_bindings.h
+)
+
+tint_target_add_dependencies(tint_lang_spirv_writer_helpers lib
+ tint_api_common
+ tint_lang_core
+ tint_lang_core_constant
+ tint_lang_core_type
+ tint_lang_wgsl
+ tint_lang_wgsl_ast
+ tint_lang_wgsl_program
+ tint_lang_wgsl_sem
+ 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
+)
+
+if(TINT_BUILD_SPV_WRITER)
+ tint_target_add_dependencies(tint_lang_spirv_writer_helpers lib
+ tint_lang_spirv_writer_common
+ )
+endif(TINT_BUILD_SPV_WRITER)
diff --git a/src/tint/lang/spirv/writer/helpers/BUILD.gn b/src/tint/lang/spirv/writer/helpers/BUILD.gn
new file mode 100644
index 0000000..b062d79
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/BUILD.gn
@@ -0,0 +1,60 @@
+# Copyright 2023 The Tint Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+################################################################################
+# 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/tint_overrides_with_defaults.gni")
+
+import("${tint_src_dir}/tint.gni")
+
+libtint_source_set("helpers") {
+ sources = [
+ "generate_bindings.cc",
+ "generate_bindings.h",
+ ]
+ deps = [
+ "${tint_src_dir}/api/common",
+ "${tint_src_dir}/lang/core",
+ "${tint_src_dir}/lang/core/constant",
+ "${tint_src_dir}/lang/core/type",
+ "${tint_src_dir}/lang/wgsl",
+ "${tint_src_dir}/lang/wgsl/ast",
+ "${tint_src_dir}/lang/wgsl/program",
+ "${tint_src_dir}/lang/wgsl/sem",
+ "${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_spv_writer) {
+ deps += [ "${tint_src_dir}/lang/spirv/writer/common" ]
+ }
+}
diff --git a/src/tint/lang/spirv/writer/helpers/generate_bindings.cc b/src/tint/lang/spirv/writer/helpers/generate_bindings.cc
new file mode 100644
index 0000000..0285b0b
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/generate_bindings.cc
@@ -0,0 +1,119 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/tint/lang/spirv/writer/helpers/generate_bindings.h"
+
+#include <algorithm>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "src/tint/api/common/binding_point.h"
+#include "src/tint/lang/core/type/external_texture.h"
+#include "src/tint/lang/core/type/storage_texture.h"
+#include "src/tint/lang/wgsl/ast/module.h"
+#include "src/tint/lang/wgsl/program/program.h"
+#include "src/tint/lang/wgsl/sem/variable.h"
+#include "src/tint/utils/rtti/switch.h"
+
+namespace tint::spirv::writer {
+
+Bindings GenerateBindings(const Program& program) {
+ // TODO(tint:1491): Use Inspector once we can get binding info for all
+ // variables, not just those referenced by entry points.
+
+ Bindings bindings{};
+
+ std::unordered_set<tint::BindingPoint> seen_binding_points;
+
+ // Collect next valid binding number per group
+ std::unordered_map<uint32_t, uint32_t> group_to_next_binding_number;
+ std::vector<tint::BindingPoint> ext_tex_bps;
+ for (auto* var : program.AST().GlobalVariables()) {
+ if (auto* sem_var = program.Sem().Get(var)->As<sem::GlobalVariable>()) {
+ if (auto bp = sem_var->BindingPoint()) {
+ // This is a bit of a hack. The binding points must be unique over all the `binding`
+ // entries. But, this is looking at _all_ entry points where bindings can overlap.
+ // In the case where both entry points used the same type (uniform, sampler, etc)
+ // then it woudl be fine as it just overwrites with itself. But, if one entry point
+ // has a uniform and the other a sampler at the same (group,binding) pair then we'll
+ // get a validation error due to duplicate WGSL bindings.
+ //
+ // For generate bindings we don't really care as we always map to itself, so if it
+ // exists anywhere, we just pretend that's the only one.
+ if (seen_binding_points.find(*bp) != seen_binding_points.end()) {
+ continue;
+ }
+ seen_binding_points.emplace(*bp);
+
+ auto& n = group_to_next_binding_number[bp->group];
+ n = std::max(n, bp->binding + 1);
+
+ // Store up the external textures, we'll add them in the next step
+ if (sem_var->Type()->UnwrapRef()->Is<core::type::ExternalTexture>()) {
+ ext_tex_bps.emplace_back(*bp);
+ continue;
+ }
+
+ binding::BindingInfo info{bp->group, bp->binding};
+ switch (sem_var->AddressSpace()) {
+ case core::AddressSpace::kHandle:
+ Switch(
+ sem_var->Type()->UnwrapRef(), //
+ [&](const core::type::Sampler*) {
+ bindings.sampler.emplace(*bp, info);
+ },
+ [&](const core::type::StorageTexture*) {
+ bindings.storage_texture.emplace(*bp, info);
+ },
+ [&](const core::type::Texture*) {
+ bindings.texture.emplace(*bp, info);
+ });
+ break;
+ case core::AddressSpace::kStorage:
+ bindings.storage.emplace(*bp, info);
+ break;
+ case core::AddressSpace::kUniform:
+ bindings.uniform.emplace(*bp, info);
+ break;
+
+ case core::AddressSpace::kUndefined:
+ case core::AddressSpace::kPixelLocal:
+ case core::AddressSpace::kPrivate:
+ case core::AddressSpace::kPushConstant:
+ case core::AddressSpace::kIn:
+ case core::AddressSpace::kOut:
+ case core::AddressSpace::kFunction:
+ case core::AddressSpace::kWorkgroup:
+ break;
+ }
+ }
+ }
+ }
+
+ for (auto bp : ext_tex_bps) {
+ uint32_t g = bp.group;
+ uint32_t& next_num = group_to_next_binding_number[g];
+
+ binding::BindingInfo plane0{bp.group, bp.binding};
+ binding::BindingInfo plane1{g, next_num++};
+ binding::BindingInfo metadata{g, next_num++};
+
+ bindings.external_texture.emplace(bp, binding::ExternalTexture{metadata, plane0, plane1});
+ }
+
+ return bindings;
+}
+
+} // namespace tint::spirv::writer
diff --git a/src/tint/lang/spirv/writer/helpers/generate_bindings.h b/src/tint/lang/spirv/writer/helpers/generate_bindings.h
new file mode 100644
index 0000000..d97120f
--- /dev/null
+++ b/src/tint/lang/spirv/writer/helpers/generate_bindings.h
@@ -0,0 +1,31 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
+#define SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
+
+#include "src/tint/lang/spirv/writer/common/options.h"
+
+// Forward declarations
+namespace tint {
+class Program;
+}
+
+namespace tint::spirv::writer {
+
+Bindings GenerateBindings(const Program& program);
+
+} // namespace tint::spirv::writer
+
+#endif // SRC_TINT_LANG_SPIRV_WRITER_HELPERS_GENERATE_BINDINGS_H_
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.bazel b/src/tint/lang/spirv/writer/printer/BUILD.bazel
index f595547..21bb414 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/printer/BUILD.bazel
@@ -33,7 +33,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.cmake b/src/tint/lang/spirv/writer/printer/BUILD.cmake
index 81c1626..cdadaec 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/printer/BUILD.cmake
@@ -34,7 +34,6 @@
tint_target_add_dependencies(tint_lang_spirv_writer_printer lib
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_intrinsic
diff --git a/src/tint/lang/spirv/writer/printer/BUILD.gn b/src/tint/lang/spirv/writer/printer/BUILD.gn
index 476271a..e57f56c 100644
--- a/src/tint/lang/spirv/writer/printer/BUILD.gn
+++ b/src/tint/lang/spirv/writer/printer/BUILD.gn
@@ -32,7 +32,6 @@
]
deps = [
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/intrinsic",
diff --git a/src/tint/lang/spirv/writer/raise/raise.cc b/src/tint/lang/spirv/writer/raise/raise.cc
index c2fc514..7add4af 100644
--- a/src/tint/lang/spirv/writer/raise/raise.cc
+++ b/src/tint/lang/spirv/writer/raise/raise.cc
@@ -31,6 +31,7 @@
#include "src/tint/lang/core/ir/transform/robustness.h"
#include "src/tint/lang/core/ir/transform/std140.h"
#include "src/tint/lang/core/ir/transform/zero_init_workgroup_memory.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/spirv/writer/raise/builtin_polyfill.h"
#include "src/tint/lang/spirv/writer/raise/expand_implicit_splats.h"
#include "src/tint/lang/spirv/writer/raise/handle_matrix_arithmetic.h"
@@ -49,8 +50,11 @@
} \
} while (false)
- RUN_TRANSFORM(core::ir::transform::BindingRemapper, module,
- options.binding_remapper_options.binding_points);
+ ExternalTextureOptions external_texture_options{};
+ RemapperData remapper_data{};
+ PopulateRemapperAndMultiplanarOptions(options, remapper_data, external_texture_options);
+
+ RUN_TRANSFORM(core::ir::transform::BindingRemapper, module, remapper_data);
core::ir::transform::BinaryPolyfillConfig binary_polyfills;
binary_polyfills.bitshift_modulo = true;
@@ -84,7 +88,7 @@
}
RUN_TRANSFORM(core::ir::transform::MultiplanarExternalTexture, module,
- options.external_texture_options);
+ external_texture_options);
if (!options.disable_workgroup_init &&
!options.use_zero_initialize_workgroup_memory_extension) {
diff --git a/src/tint/lang/spirv/writer/writer.cc b/src/tint/lang/spirv/writer/writer.cc
index 1a47183..94484f4 100644
--- a/src/tint/lang/spirv/writer/writer.cc
+++ b/src/tint/lang/spirv/writer/writer.cc
@@ -18,6 +18,7 @@
#include <utility>
#include "src/tint/lang/spirv/writer/ast_printer/ast_printer.h"
+#include "src/tint/lang/spirv/writer/common/option_builder.h"
#include "src/tint/lang/spirv/writer/printer/printer.h"
#include "src/tint/lang/spirv/writer/raise/raise.h"
#include "src/tint/lang/wgsl/reader/lower/lower.h"
@@ -40,6 +41,13 @@
bool zero_initialize_workgroup_memory =
!options.disable_workgroup_init && options.use_zero_initialize_workgroup_memory_extension;
+ {
+ diag::List validation_diagnostics;
+ if (!ValidateBindingOptions(options, validation_diagnostics)) {
+ return Failure{validation_diagnostics};
+ }
+ }
+
Output output;
if (options.use_tint_ir) {