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
|
//! allocator manages each bind group, assigning slots to materials as
|
||||||
//! appropriate.
|
//! appropriate.
|
||||||
|
|
||||||
use core::{marker::PhantomData, mem};
|
use core::{iter, marker::PhantomData, mem};
|
||||||
|
|
||||||
use bevy_derive::{Deref, DerefMut};
|
use bevy_derive::{Deref, DerefMut};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
@ -23,6 +23,7 @@ use bevy_render::{
|
|||||||
UnpreparedBindGroup, WgpuSampler, WgpuTextureView,
|
UnpreparedBindGroup, WgpuSampler, WgpuTextureView,
|
||||||
},
|
},
|
||||||
renderer::{RenderDevice, RenderQueue},
|
renderer::{RenderDevice, RenderQueue},
|
||||||
|
settings::WgpuFeatures,
|
||||||
texture::FallbackImage,
|
texture::FallbackImage,
|
||||||
};
|
};
|
||||||
use bevy_utils::default;
|
use bevy_utils::default;
|
||||||
@ -812,6 +813,7 @@ where
|
|||||||
&self.fallback_buffers,
|
&self.fallback_buffers,
|
||||||
fallback_image,
|
fallback_image,
|
||||||
&self.bindless_descriptor,
|
&self.bindless_descriptor,
|
||||||
|
self.slab_capacity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1171,6 +1173,7 @@ where
|
|||||||
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
||||||
fallback_image: &FallbackImage,
|
fallback_image: &FallbackImage,
|
||||||
bindless_descriptor: &BindlessDescriptor,
|
bindless_descriptor: &BindlessDescriptor,
|
||||||
|
slab_capacity: u32,
|
||||||
) {
|
) {
|
||||||
// Create the bindless index table buffer if needed.
|
// Create the bindless index table buffer if needed.
|
||||||
self.bindless_index_table.buffer.prepare(render_device);
|
self.bindless_index_table.buffer.prepare(render_device);
|
||||||
@ -1188,6 +1191,7 @@ where
|
|||||||
fallback_buffers,
|
fallback_buffers,
|
||||||
fallback_image,
|
fallback_image,
|
||||||
bindless_descriptor,
|
bindless_descriptor,
|
||||||
|
slab_capacity,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,17 +1205,30 @@ where
|
|||||||
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
fallback_buffers: &HashMap<BindlessIndex, Buffer>,
|
||||||
fallback_image: &FallbackImage,
|
fallback_image: &FallbackImage,
|
||||||
bindless_descriptor: &BindlessDescriptor,
|
bindless_descriptor: &BindlessDescriptor,
|
||||||
|
slab_capacity: u32,
|
||||||
) {
|
) {
|
||||||
// If the bind group is clean, then do nothing.
|
// If the bind group is clean, then do nothing.
|
||||||
if self.bind_group.is_some() {
|
if self.bind_group.is_some() {
|
||||||
return;
|
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(
|
let binding_resource_arrays = self.create_binding_resource_arrays(
|
||||||
fallback_bindless_resources,
|
fallback_bindless_resources,
|
||||||
fallback_buffers,
|
fallback_buffers,
|
||||||
fallback_image,
|
fallback_image,
|
||||||
bindless_descriptor,
|
bindless_descriptor,
|
||||||
|
required_binding_array_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut bind_group_entries = vec![BindGroupEntry {
|
let mut bind_group_entries = vec![BindGroupEntry {
|
||||||
@ -1282,6 +1299,7 @@ where
|
|||||||
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
||||||
fallback_image: &'a FallbackImage,
|
fallback_image: &'a FallbackImage,
|
||||||
bindless_descriptor: &'a BindlessDescriptor,
|
bindless_descriptor: &'a BindlessDescriptor,
|
||||||
|
required_binding_array_size: Option<u32>,
|
||||||
) -> Vec<(&'a u32, BindingResourceArray<'a>)> {
|
) -> Vec<(&'a u32, BindingResourceArray<'a>)> {
|
||||||
let mut binding_resource_arrays = vec![];
|
let mut binding_resource_arrays = vec![];
|
||||||
|
|
||||||
@ -1289,16 +1307,22 @@ where
|
|||||||
self.create_sampler_binding_resource_arrays(
|
self.create_sampler_binding_resource_arrays(
|
||||||
&mut binding_resource_arrays,
|
&mut binding_resource_arrays,
|
||||||
fallback_bindless_resources,
|
fallback_bindless_resources,
|
||||||
|
required_binding_array_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Build texture bindings.
|
// 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.
|
// Build buffer bindings.
|
||||||
self.create_buffer_binding_resource_arrays(
|
self.create_buffer_binding_resource_arrays(
|
||||||
&mut binding_resource_arrays,
|
&mut binding_resource_arrays,
|
||||||
fallback_buffers,
|
fallback_buffers,
|
||||||
bindless_descriptor,
|
bindless_descriptor,
|
||||||
|
required_binding_array_size,
|
||||||
);
|
);
|
||||||
|
|
||||||
binding_resource_arrays
|
binding_resource_arrays
|
||||||
@ -1310,6 +1334,7 @@ where
|
|||||||
&'a self,
|
&'a self,
|
||||||
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||||
fallback_bindless_resources: &'a FallbackBindlessResources,
|
fallback_bindless_resources: &'a FallbackBindlessResources,
|
||||||
|
required_binding_array_size: Option<u32>,
|
||||||
) {
|
) {
|
||||||
// We have one binding resource array per sampler type.
|
// We have one binding resource array per sampler type.
|
||||||
for (bindless_resource_type, fallback_sampler) in [
|
for (bindless_resource_type, fallback_sampler) in [
|
||||||
@ -1326,34 +1351,41 @@ where
|
|||||||
&fallback_bindless_resources.comparison_sampler,
|
&fallback_bindless_resources.comparison_sampler,
|
||||||
),
|
),
|
||||||
] {
|
] {
|
||||||
|
let mut sampler_bindings = vec![];
|
||||||
|
|
||||||
match self.samplers.get(&bindless_resource_type) {
|
match self.samplers.get(&bindless_resource_type) {
|
||||||
Some(sampler_bindless_binding_array) => {
|
Some(sampler_bindless_binding_array) => {
|
||||||
let sampler_bindings = sampler_bindless_binding_array
|
for maybe_bindless_binding in sampler_bindless_binding_array.bindings.iter() {
|
||||||
.bindings
|
match *maybe_bindless_binding {
|
||||||
.iter()
|
Some(ref bindless_binding) => {
|
||||||
.map(|maybe_bindless_binding| match *maybe_bindless_binding {
|
sampler_bindings.push(&*bindless_binding.resource);
|
||||||
Some(ref bindless_binding) => &bindless_binding.resource,
|
}
|
||||||
None => &**fallback_sampler,
|
None => sampler_bindings.push(&**fallback_sampler),
|
||||||
})
|
}
|
||||||
.collect();
|
}
|
||||||
binding_resource_arrays.push((
|
|
||||||
&*sampler_bindless_binding_array.binding_number,
|
|
||||||
BindingResourceArray::Samplers(sampler_bindings),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
// Fill with a single fallback sampler.
|
// Fill with a single fallback sampler.
|
||||||
let binding_number = bindless_resource_type
|
sampler_bindings.push(&**fallback_sampler);
|
||||||
.binding_number()
|
|
||||||
.expect("Sampler bindless resource type must have a binding number");
|
|
||||||
|
|
||||||
binding_resource_arrays.push((
|
|
||||||
&**binding_number,
|
|
||||||
BindingResourceArray::Samplers(vec![&**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,
|
&'a self,
|
||||||
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||||
fallback_image: &'a FallbackImage,
|
fallback_image: &'a FallbackImage,
|
||||||
|
required_binding_array_size: Option<u32>,
|
||||||
) {
|
) {
|
||||||
for (bindless_resource_type, fallback_image) in [
|
for (bindless_resource_type, fallback_image) in [
|
||||||
(BindlessResourceType::Texture1d, &fallback_image.d1),
|
(BindlessResourceType::Texture1d, &fallback_image.d1),
|
||||||
@ -1378,34 +1411,41 @@ where
|
|||||||
&fallback_image.cube_array,
|
&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) {
|
match self.textures.get(&bindless_resource_type) {
|
||||||
Some(texture_bindless_binding_array) => {
|
Some(texture_bindless_binding_array) => {
|
||||||
let texture_bindings = texture_bindless_binding_array
|
for maybe_bindless_binding in texture_bindless_binding_array.bindings.iter() {
|
||||||
.bindings
|
match *maybe_bindless_binding {
|
||||||
.iter()
|
Some(ref bindless_binding) => {
|
||||||
.map(|maybe_bindless_binding| match *maybe_bindless_binding {
|
texture_bindings.push(&*bindless_binding.resource);
|
||||||
Some(ref bindless_binding) => &*bindless_binding.resource,
|
}
|
||||||
None => &*fallback_image.texture_view,
|
None => texture_bindings.push(&*fallback_image.texture_view),
|
||||||
})
|
}
|
||||||
.collect();
|
}
|
||||||
binding_resource_arrays.push((
|
|
||||||
&*texture_bindless_binding_array.binding_number,
|
|
||||||
BindingResourceArray::TextureViews(texture_bindings),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
// Fill with a single fallback image.
|
// Fill with a single fallback image.
|
||||||
let binding_number = bindless_resource_type
|
texture_bindings.push(&*fallback_image.texture_view);
|
||||||
.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]),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>)>,
|
binding_resource_arrays: &'b mut Vec<(&'a u32, BindingResourceArray<'a>)>,
|
||||||
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
fallback_buffers: &'a HashMap<BindlessIndex, Buffer>,
|
||||||
bindless_descriptor: &'a BindlessDescriptor,
|
bindless_descriptor: &'a BindlessDescriptor,
|
||||||
|
required_binding_array_size: Option<u32>,
|
||||||
) {
|
) {
|
||||||
for bindless_buffer_descriptor in bindless_descriptor.buffers.iter() {
|
for bindless_buffer_descriptor in bindless_descriptor.buffers.iter() {
|
||||||
let Some(buffer_bindless_binding_array) =
|
let Some(buffer_bindless_binding_array) =
|
||||||
@ -1426,14 +1467,17 @@ where
|
|||||||
// `BindlessDescriptor::resources`.
|
// `BindlessDescriptor::resources`.
|
||||||
continue;
|
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
|
.bindings
|
||||||
.iter()
|
.iter()
|
||||||
.map(|maybe_bindless_binding| {
|
.map(|maybe_bindless_binding| {
|
||||||
let buffer = match *maybe_bindless_binding {
|
let buffer = match *maybe_bindless_binding {
|
||||||
None => fallback_buffers
|
None => fallback_buffer,
|
||||||
.get(&bindless_buffer_descriptor.bindless_index)
|
|
||||||
.expect("Fallback buffer should exist"),
|
|
||||||
Some(ref bindless_binding) => &bindless_binding.resource,
|
Some(ref bindless_binding) => &bindless_binding.resource,
|
||||||
};
|
};
|
||||||
BufferBinding {
|
BufferBinding {
|
||||||
@ -1443,6 +1487,18 @@ where
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.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((
|
binding_resource_arrays.push((
|
||||||
&*buffer_bindless_binding_array.binding_number,
|
&*buffer_bindless_binding_array.binding_number,
|
||||||
BindingResourceArray::Buffers(buffer_bindings),
|
BindingResourceArray::Buffers(buffer_bindings),
|
||||||
|
Loading…
Reference in New Issue
Block a user