Pad out binding arrays to their full length if partially bound binding arrays aren't supported. (#18126)
I mistakenly thought that with the wgpu upgrade we'd have `PARTIALLY_BOUND_BINDING_ARRAY` everywhere. Unfortunately this is not the case. This PR adds a workaround back in. Closes #18098.
This commit is contained in:
parent
195a74afad
commit
528e68f5bb
@ -4,7 +4,7 @@
|
||||
//! allocator manages each bind group, assigning slots to materials as
|
||||
//! appropriate.
|
||||
|
||||
use core::{marker::PhantomData, mem};
|
||||
use core::{iter, marker::PhantomData, mem};
|
||||
|
||||
use bevy_derive::{Deref, DerefMut};
|
||||
use bevy_ecs::{
|
||||
@ -23,6 +23,7 @@ use bevy_render::{
|
||||
UnpreparedBindGroup, WgpuSampler, WgpuTextureView,
|
||||
},
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
settings::WgpuFeatures,
|
||||
texture::FallbackImage,
|
||||
};
|
||||
use bevy_utils::default;
|
||||
@ -812,6 +813,7 @@ where
|
||||
&self.fallback_buffers,
|
||||
fallback_image,
|
||||
&self.bindless_descriptor,
|
||||
self.slab_capacity,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1171,6 +1173,7 @@ where
|
||||
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
||||
fallback_image: &FallbackImage,
|
||||
bindless_descriptor: &BindlessDescriptor,
|
||||
slab_capacity: u32,
|
||||
) {
|
||||
// Create the bindless index table buffer if needed.
|
||||
self.bindless_index_table.buffer.prepare(render_device);
|
||||
@ -1188,6 +1191,7 @@ where
|
||||
fallback_buffers,
|
||||
fallback_image,
|
||||
bindless_descriptor,
|
||||
slab_capacity,
|
||||
);
|
||||
}
|
||||
|
||||
@ -1201,17 +1205,30 @@ where
|
||||
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
||||
fallback_image: &FallbackImage,
|
||||
bindless_descriptor: &BindlessDescriptor,
|
||||
slab_capacity: u32,
|
||||
) {
|
||||
// If the bind group is clean, then do nothing.
|
||||
if self.bind_group.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine whether we need to pad out our binding arrays with dummy
|
||||
// resources.
|
||||
let required_binding_array_size = if render_device
|
||||
.features()
|
||||
.contains(WgpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(slab_capacity)
|
||||
};
|
||||
|
||||
let binding_resource_arrays = self.create_binding_resource_arrays(
|
||||
fallback_bindless_resources,
|
||||
fallback_buffers,
|
||||
fallback_image,
|
||||
bindless_descriptor,
|
||||
required_binding_array_size,
|
||||
);
|
||||
|
||||
let mut bind_group_entries = vec![BindGroupEntry {
|
||||
@ -1282,6 +1299,7 @@ where
|
||||
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
bindless_descriptor: &'a BindlessDescriptor,
|
||||
required_binding_array_size: Option<u32>,
|
||||
) -> Vec<(&'a u32, BindingResourceArray<'a>)> {
|
||||
let mut binding_resource_arrays = vec![];
|
||||
|
||||
@ -1289,16 +1307,22 @@ where
|
||||
self.create_sampler_binding_resource_arrays(
|
||||
&mut binding_resource_arrays,
|
||||
fallback_bindless_resources,
|
||||
required_binding_array_size,
|
||||
);
|
||||
|
||||
// Build texture bindings.
|
||||
self.create_texture_binding_resource_arrays(&mut binding_resource_arrays, fallback_image);
|
||||
self.create_texture_binding_resource_arrays(
|
||||
&mut binding_resource_arrays,
|
||||
fallback_image,
|
||||
required_binding_array_size,
|
||||
);
|
||||
|
||||
// Build buffer bindings.
|
||||
self.create_buffer_binding_resource_arrays(
|
||||
&mut binding_resource_arrays,
|
||||
fallback_buffers,
|
||||
bindless_descriptor,
|
||||
required_binding_array_size,
|
||||
);
|
||||
|
||||
binding_resource_arrays
|
||||
@ -1310,6 +1334,7 @@ where
|
||||
&'a self,
|
||||
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||
fallback_bindless_resources: &'a FallbackBindlessResources,
|
||||
required_binding_array_size: Option<u32>,
|
||||
) {
|
||||
// We have one binding resource array per sampler type.
|
||||
for (bindless_resource_type, fallback_sampler) in [
|
||||
@ -1326,34 +1351,41 @@ where
|
||||
&fallback_bindless_resources.comparison_sampler,
|
||||
),
|
||||
] {
|
||||
let mut sampler_bindings = vec![];
|
||||
|
||||
match self.samplers.get(&bindless_resource_type) {
|
||||
Some(sampler_bindless_binding_array) => {
|
||||
let sampler_bindings = sampler_bindless_binding_array
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|maybe_bindless_binding| match *maybe_bindless_binding {
|
||||
Some(ref bindless_binding) => &bindless_binding.resource,
|
||||
None => &**fallback_sampler,
|
||||
})
|
||||
.collect();
|
||||
binding_resource_arrays.push((
|
||||
&*sampler_bindless_binding_array.binding_number,
|
||||
BindingResourceArray::Samplers(sampler_bindings),
|
||||
));
|
||||
for maybe_bindless_binding in sampler_bindless_binding_array.bindings.iter() {
|
||||
match *maybe_bindless_binding {
|
||||
Some(ref bindless_binding) => {
|
||||
sampler_bindings.push(&*bindless_binding.resource);
|
||||
}
|
||||
None => sampler_bindings.push(&**fallback_sampler),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None => {
|
||||
// Fill with a single fallback sampler.
|
||||
let binding_number = bindless_resource_type
|
||||
.binding_number()
|
||||
.expect("Sampler bindless resource type must have a binding number");
|
||||
|
||||
binding_resource_arrays.push((
|
||||
&**binding_number,
|
||||
BindingResourceArray::Samplers(vec![&**fallback_sampler]),
|
||||
));
|
||||
sampler_bindings.push(&**fallback_sampler);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(required_binding_array_size) = required_binding_array_size {
|
||||
sampler_bindings.extend(
|
||||
iter::repeat(&**fallback_sampler)
|
||||
.take(required_binding_array_size as usize - sampler_bindings.len()),
|
||||
);
|
||||
}
|
||||
|
||||
let binding_number = bindless_resource_type
|
||||
.binding_number()
|
||||
.expect("Sampler bindless resource type must have a binding number");
|
||||
|
||||
binding_resource_arrays.push((
|
||||
&**binding_number,
|
||||
BindingResourceArray::Samplers(sampler_bindings),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,6 +1395,7 @@ where
|
||||
&'a self,
|
||||
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||
fallback_image: &'a FallbackImage,
|
||||
required_binding_array_size: Option<u32>,
|
||||
) {
|
||||
for (bindless_resource_type, fallback_image) in [
|
||||
(BindlessResourceType::Texture1d, &fallback_image.d1),
|
||||
@ -1378,34 +1411,41 @@ where
|
||||
&fallback_image.cube_array,
|
||||
),
|
||||
] {
|
||||
let mut texture_bindings = vec![];
|
||||
|
||||
let binding_number = bindless_resource_type
|
||||
.binding_number()
|
||||
.expect("Texture bindless resource type must have a binding number");
|
||||
|
||||
match self.textures.get(&bindless_resource_type) {
|
||||
Some(texture_bindless_binding_array) => {
|
||||
let texture_bindings = texture_bindless_binding_array
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|maybe_bindless_binding| match *maybe_bindless_binding {
|
||||
Some(ref bindless_binding) => &*bindless_binding.resource,
|
||||
None => &*fallback_image.texture_view,
|
||||
})
|
||||
.collect();
|
||||
binding_resource_arrays.push((
|
||||
&*texture_bindless_binding_array.binding_number,
|
||||
BindingResourceArray::TextureViews(texture_bindings),
|
||||
));
|
||||
for maybe_bindless_binding in texture_bindless_binding_array.bindings.iter() {
|
||||
match *maybe_bindless_binding {
|
||||
Some(ref bindless_binding) => {
|
||||
texture_bindings.push(&*bindless_binding.resource);
|
||||
}
|
||||
None => texture_bindings.push(&*fallback_image.texture_view),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None => {
|
||||
// Fill with a single fallback image.
|
||||
let binding_number = bindless_resource_type
|
||||
.binding_number()
|
||||
.expect("Texture bindless resource type must have a binding number");
|
||||
|
||||
binding_resource_arrays.push((
|
||||
binding_number,
|
||||
BindingResourceArray::TextureViews(vec![&*fallback_image.texture_view]),
|
||||
));
|
||||
texture_bindings.push(&*fallback_image.texture_view);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(required_binding_array_size) = required_binding_array_size {
|
||||
texture_bindings.extend(
|
||||
iter::repeat(&*fallback_image.texture_view)
|
||||
.take(required_binding_array_size as usize - texture_bindings.len()),
|
||||
);
|
||||
}
|
||||
|
||||
binding_resource_arrays.push((
|
||||
binding_number,
|
||||
BindingResourceArray::TextureViews(texture_bindings),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1416,6 +1456,7 @@ where
|
||||
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
||||
bindless_descriptor: &'a BindlessDescriptor,
|
||||
required_binding_array_size: Option<u32>,
|
||||
) {
|
||||
for bindless_buffer_descriptor in bindless_descriptor.buffers.iter() {
|
||||
let Some(buffer_bindless_binding_array) =
|
||||
@ -1426,14 +1467,17 @@ where
|
||||
// `BindlessDescriptor::resources`.
|
||||
continue;
|
||||
};
|
||||
let buffer_bindings = buffer_bindless_binding_array
|
||||
|
||||
let fallback_buffer = fallback_buffers
|
||||
.get(&bindless_buffer_descriptor.bindless_index)
|
||||
.expect("Fallback buffer should exist");
|
||||
|
||||
let mut buffer_bindings: Vec<_> = buffer_bindless_binding_array
|
||||
.bindings
|
||||
.iter()
|
||||
.map(|maybe_bindless_binding| {
|
||||
let buffer = match *maybe_bindless_binding {
|
||||
None => fallback_buffers
|
||||
.get(&bindless_buffer_descriptor.bindless_index)
|
||||
.expect("Fallback buffer should exist"),
|
||||
None => fallback_buffer,
|
||||
Some(ref bindless_binding) => &bindless_binding.resource,
|
||||
};
|
||||
BufferBinding {
|
||||
@ -1443,6 +1487,18 @@ where
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if let Some(required_binding_array_size) = required_binding_array_size {
|
||||
buffer_bindings.extend(
|
||||
iter::repeat(BufferBinding {
|
||||
buffer: fallback_buffer,
|
||||
offset: 0,
|
||||
size: None,
|
||||
})
|
||||
.take(required_binding_array_size as usize - buffer_bindings.len()),
|
||||
);
|
||||
}
|
||||
|
||||
binding_resource_arrays.push((
|
||||
&*buffer_bindless_binding_array.binding_number,
|
||||
BindingResourceArray::Buffers(buffer_bindings),
|
||||
|
Loading…
Reference in New Issue
Block a user