Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions naga-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ impl SpirvOutParameters {
Some(self.capabilities.clone())
},
bounds_check_policies,
fake_missing_bindings: true,
binding_map: self.binding_map.clone(),
zero_initialize_workgroup_memory: spv::ZeroInitializeWorkgroupMemoryMode::Polyfill,
force_loop_bounding: true,
Expand Down
12 changes: 11 additions & 1 deletion naga/src/back/spv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ pub enum Error {
Override,
#[error(transparent)]
ResolveArraySizeError(#[from] crate::proc::ResolveArraySizeError),
#[error("mapping of {0:?} is missing")]
MissingBinding(crate::ResourceBinding),
}

#[derive(Default)]
Expand Down Expand Up @@ -760,6 +762,7 @@ pub struct Writer {
constant_ids: HandleVec<crate::Expression, Word>,
cached_constants: crate::FastHashMap<CachedConstant, Word>,
global_variables: HandleVec<crate::GlobalVariable, GlobalVariable>,
fake_missing_bindings: bool,
binding_map: BindingMap,

// Cached expressions are only meaningful within a BlockContext, but we
Expand Down Expand Up @@ -811,10 +814,12 @@ bitflags::bitflags! {
}
}

#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct BindingInfo {
pub descriptor_set: u32,
pub binding: u32,
/// If the binding is an unsized binding array, this overrides the size.
pub binding_array_size: Option<u32>,
}
Expand All @@ -839,6 +844,10 @@ pub struct Options<'a> {
/// Configuration flags for the writer.
pub flags: WriterFlags,

/// Don't panic on missing bindings. Instead use fake values for `Binding`
/// and `DescriptorSet` decorations. This may result in invalid SPIR-V.
pub fake_missing_bindings: bool,

/// Map of resources to information about the binding.
pub binding_map: BindingMap,

Expand Down Expand Up @@ -877,6 +886,7 @@ impl Default for Options<'_> {
Options {
lang_version: (1, 0),
flags,
fake_missing_bindings: true,
binding_map: BindingMap::default(),
capabilities: None,
bounds_check_policies: BoundsCheckPolicies::default(),
Expand Down
32 changes: 26 additions & 6 deletions naga/src/back/spv/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ impl Writer {
constant_ids: HandleVec::new(),
cached_constants: crate::FastHashMap::default(),
global_variables: HandleVec::new(),
fake_missing_bindings: options.fake_missing_bindings,
binding_map: options.binding_map.clone(),
saved_cached: CachedExpressions::default(),
gl450_ext_inst_id,
Expand Down Expand Up @@ -149,6 +150,7 @@ impl Writer {
force_loop_bounding: self.force_loop_bounding,
use_storage_input_output_16: self.use_storage_input_output_16,
capabilities_available: take(&mut self.capabilities_available),
fake_missing_bindings: self.fake_missing_bindings,
binding_map: take(&mut self.binding_map),

// Initialized afresh:
Expand Down Expand Up @@ -469,6 +471,26 @@ impl Writer {
})
}

/// Resolve the [`BindingInfo`] for a [`crate::ResourceBinding`] from the
/// provided [`Writer::binding_map`].
///
/// If the specified resource is not present in the binding map this will
/// return an error, unless [`Writer::fake_missing_bindings`] is set.
fn resolve_resource_binding(
&self,
res_binding: &crate::ResourceBinding,
) -> Result<BindingInfo, Error> {
match self.binding_map.get(res_binding) {
Some(target) => Ok(*target),
None if self.fake_missing_bindings => Ok(BindingInfo {
descriptor_set: res_binding.group,
binding: res_binding.binding,
binding_array_size: None,
}),
None => Err(Error::MissingBinding(*res_binding)),
}
}

/// Emits code for any wrapper functions required by the expressions in ir_function.
/// The IDs of any emitted functions will be stored in [`Self::wrapped_functions`].
fn write_wrapped_functions(
Expand Down Expand Up @@ -2241,13 +2263,11 @@ impl Writer {
// and it is failing on 0.
let mut substitute_inner_type_lookup = None;
if let Some(ref res_binding) = global_variable.binding {
self.decorate(id, Decoration::DescriptorSet, &[res_binding.group]);
self.decorate(id, Decoration::Binding, &[res_binding.binding]);
let bind_target = self.resolve_resource_binding(res_binding)?;
self.decorate(id, Decoration::DescriptorSet, &[bind_target.descriptor_set]);
self.decorate(id, Decoration::Binding, &[bind_target.binding]);

if let Some(&BindingInfo {
binding_array_size: Some(remapped_binding_array_size),
}) = self.binding_map.get(res_binding)
{
if let Some(remapped_binding_array_size) = bind_target.binding_array_size {
if let crate::TypeInner::BindingArray { base, .. } =
ir_module.types[global_variable.ty].inner
{
Expand Down
2 changes: 1 addition & 1 deletion naga/tests/in/wgsl/binding-arrays.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,5 @@ resource_binding = { group = 0, binding = 8 }
version = [1, 1]

[[spv.binding_map]]
bind_target = { binding_array_size = 10 }
bind_target = { descriptor_set = 0, binding = 0, binding_array_size = 10 }
resource_binding = { group = 0, binding = 0 }
2 changes: 1 addition & 1 deletion naga/tests/in/wgsl/binding-buffer-arrays.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ image = "ReadZeroSkipWrite"
version = [1, 1]

[[spv.binding_map]]
bind_target = { binding_array_size = 10 }
bind_target = { descriptor_set = 0, binding = 0, binding_array_size = 10 }
resource_binding = { group = 0, binding = 0 }
1 change: 1 addition & 0 deletions wgpu-hal/src/vulkan/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2166,6 +2166,7 @@ impl super::Adapter {
force_loop_bounding: true,
use_storage_input_output_16: features.contains(wgt::Features::SHADER_F16)
&& self.phd_features.supports_storage_input_output_16(),
fake_missing_bindings: false,
// We need to build this separately for each invocation, so just default it out here
binding_map: BTreeMap::default(),
debug_info: None,
Expand Down
Loading
Loading