Allow binding raw descriptor sets (#2423)

This commit is contained in:
marc0246 2024-10-23 16:07:57 +02:00 committed by GitHub
parent 6da1f96c73
commit dac6871d97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 342 additions and 193 deletions

View File

@ -843,14 +843,12 @@ impl Task for RenderTask {
0, 0,
&[ &[
// Bind the uniform buffer designated for this frame. // Bind the uniform buffer designated for this frame.
self.uniform_buffer_sets[frame_index as usize] self.uniform_buffer_sets[frame_index as usize].as_raw(),
.clone()
.into(),
// Bind the currently most up-to-date texture. // Bind the currently most up-to-date texture.
self.sampler_sets[self.current_texture_index.load(Ordering::Relaxed) as usize] self.sampler_sets[self.current_texture_index.load(Ordering::Relaxed) as usize]
.clone() .as_raw(),
.into(),
], ],
&[],
)?; )?;
cbf.bind_vertex_buffers(0, &[self.vertex_buffer_id], &[0], &[], &[])?; cbf.bind_vertex_buffers(0, &[self.vertex_buffer_id], &[0], &[], &[])?;

View File

@ -1,5 +1,5 @@
use crate::{App, RenderContext}; use crate::{App, RenderContext};
use std::{slice, sync::Arc}; use std::sync::Arc;
use vulkano::{ use vulkano::{
image::{mip_level_extent, Image}, image::{mip_level_extent, Image},
pipeline::{ pipeline::{
@ -80,7 +80,8 @@ impl Task for BloomTask {
PipelineBindPoint::Compute, PipelineBindPoint::Compute,
&rcx.pipeline_layout, &rcx.pipeline_layout,
0, 0,
slice::from_ref(&rcx.descriptor_set), &[&rcx.descriptor_set],
&[],
)?; )?;
let bloom_image = tcx.image(self.bloom_image_id)?.image(); let bloom_image = tcx.image(self.bloom_image_id)?.image();
@ -141,7 +142,7 @@ impl Task for BloomTask {
} }
cbf.destroy_object(bloom_image.clone()); cbf.destroy_object(bloom_image.clone());
cbf.destroy_object(rcx.descriptor_set.as_ref().0.clone()); cbf.destroy_object(rcx.descriptor_set.clone());
Ok(()) Ok(())
} }

View File

@ -11,7 +11,8 @@ use vulkano::{
DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo,
DescriptorType, DescriptorType,
}, },
DescriptorImageViewInfo, DescriptorSet, DescriptorSetWithOffsets, WriteDescriptorSet, sys::RawDescriptorSet,
DescriptorImageViewInfo, WriteDescriptorSet,
}, },
device::{ device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned, physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, DeviceOwned,
@ -80,7 +81,7 @@ pub struct RenderContext {
recreate_swapchain: bool, recreate_swapchain: bool,
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>, descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
sampler: Arc<Sampler>, sampler: Arc<Sampler>,
descriptor_set: DescriptorSetWithOffsets, descriptor_set: Arc<RawDescriptorSet>,
task_graph: ExecutableTaskGraph<Self>, task_graph: ExecutableTaskGraph<Self>,
scene_node_id: NodeId, scene_node_id: NodeId,
tonemap_node_id: NodeId, tonemap_node_id: NodeId,
@ -500,7 +501,7 @@ fn window_size_dependent_setup(
pipeline_layout: &Arc<PipelineLayout>, pipeline_layout: &Arc<PipelineLayout>,
sampler: &Arc<Sampler>, sampler: &Arc<Sampler>,
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>, descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
) -> (Id<Image>, DescriptorSetWithOffsets) { ) -> (Id<Image>, Arc<RawDescriptorSet>) {
let device = resources.device(); let device = resources.device();
let swapchain_state = resources.swapchain(swapchain_id).unwrap(); let swapchain_state = resources.swapchain(swapchain_id).unwrap();
let images = swapchain_state.images(); let images = swapchain_state.images();
@ -570,30 +571,31 @@ fn window_size_dependent_setup(
.unwrap() .unwrap()
}); });
let descriptor_set = DescriptorSet::new( let descriptor_set = RawDescriptorSet::new(
descriptor_set_allocator.clone(), descriptor_set_allocator.clone(),
pipeline_layout.set_layouts()[0].clone(), &pipeline_layout.set_layouts()[0],
[ 0,
WriteDescriptorSet::sampler(0, sampler.clone()),
WriteDescriptorSet::image_view_with_layout(
1,
DescriptorImageViewInfo {
image_view: bloom_texture_view,
image_layout: ImageLayout::General,
},
),
WriteDescriptorSet::image_view_with_layout_array(
2,
0,
bloom_mip_chain_views.map(|image_view| DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::General,
}),
),
],
[],
) )
.unwrap(); .unwrap();
let writes = &[
WriteDescriptorSet::sampler(0, sampler.clone()),
WriteDescriptorSet::image_view_with_layout(
1,
DescriptorImageViewInfo {
image_view: bloom_texture_view,
image_layout: ImageLayout::General,
},
),
WriteDescriptorSet::image_view_with_layout_array(
2,
0,
bloom_mip_chain_views.map(|image_view| DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::General,
}),
),
];
unsafe { descriptor_set.update(writes, &[]) }.unwrap();
(bloom_image_id, descriptor_set.into()) (bloom_image_id, Arc::new(descriptor_set))
} }

View File

@ -124,7 +124,8 @@ impl Task for TonemapTask {
PipelineBindPoint::Graphics, PipelineBindPoint::Graphics,
&rcx.pipeline_layout, &rcx.pipeline_layout,
0, 0,
slice::from_ref(&rcx.descriptor_set), &[&rcx.descriptor_set],
&[],
)?; )?;
let swapchain_state = tcx.swapchain(self.swapchain_id)?; let swapchain_state = tcx.swapchain(self.swapchain_id)?;

View File

@ -3,6 +3,7 @@ use crate::{
command_buffer::{auto::SetOrPush, sys::RecordingCommandBuffer, AutoCommandBufferBuilder}, command_buffer::{auto::SetOrPush, sys::RecordingCommandBuffer, AutoCommandBufferBuilder},
descriptor_set::{ descriptor_set::{
layout::{DescriptorBindingFlags, DescriptorSetLayoutCreateFlags, DescriptorType}, layout::{DescriptorBindingFlags, DescriptorSetLayoutCreateFlags, DescriptorType},
sys::RawDescriptorSet,
DescriptorBindingResources, DescriptorBufferInfo, DescriptorSetResources, DescriptorBindingResources, DescriptorBufferInfo, DescriptorSetResources,
DescriptorSetWithOffsets, DescriptorSetsCollection, WriteDescriptorSet, DescriptorSetWithOffsets, DescriptorSetsCollection, WriteDescriptorSet,
}, },
@ -47,6 +48,8 @@ impl<L> AutoCommandBufferBuilder<L> {
} }
} }
// TODO: The validation here is somewhat duplicated because of how different the parameters are
// here compared to the raw command buffer.
fn validate_bind_descriptor_sets( fn validate_bind_descriptor_sets(
&self, &self,
pipeline_bind_point: PipelineBindPoint, pipeline_bind_point: PipelineBindPoint,
@ -54,13 +57,155 @@ impl<L> AutoCommandBufferBuilder<L> {
first_set: u32, first_set: u32,
descriptor_sets: &[DescriptorSetWithOffsets], descriptor_sets: &[DescriptorSetWithOffsets],
) -> Result<(), Box<ValidationError>> { ) -> Result<(), Box<ValidationError>> {
self.inner.validate_bind_descriptor_sets( self.inner.validate_bind_descriptor_sets_inner(
pipeline_bind_point, pipeline_bind_point,
pipeline_layout, pipeline_layout,
first_set, first_set,
descriptor_sets, descriptor_sets.len(),
)?; )?;
let properties = self.device().physical_device().properties();
for (descriptor_sets_index, set) in descriptor_sets.iter().enumerate() {
let set_num = first_set + descriptor_sets_index as u32;
let (set, dynamic_offsets) = set.as_ref();
// VUID-vkCmdBindDescriptorSets-commonparent
assert_eq!(self.device(), set.device());
let set_layout = set.layout();
let pipeline_set_layout = &pipeline_layout.set_layouts()[set_num as usize];
if !pipeline_set_layout.is_compatible_with(set_layout) {
return Err(Box::new(ValidationError {
problem: format!(
"`descriptor_sets[{0}]` (for set number {1}) is not compatible with \
`pipeline_layout.set_layouts()[{1}]`",
descriptor_sets_index, set_num
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358"],
..Default::default()
}));
}
let mut dynamic_offsets_remaining = dynamic_offsets;
let mut required_dynamic_offset_count = 0;
for (&binding_num, binding) in set_layout.bindings() {
let required_alignment = match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
properties.min_uniform_buffer_offset_alignment
}
DescriptorType::StorageBufferDynamic => {
properties.min_storage_buffer_offset_alignment
}
_ => continue,
};
let count = if binding
.binding_flags
.intersects(DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT)
{
set.variable_descriptor_count()
} else {
binding.descriptor_count
} as usize;
required_dynamic_offset_count += count;
if !dynamic_offsets_remaining.is_empty() {
let split_index = min(count, dynamic_offsets_remaining.len());
let dynamic_offsets = &dynamic_offsets_remaining[..split_index];
dynamic_offsets_remaining = &dynamic_offsets_remaining[split_index..];
let resources = set.resources();
let elements = match resources.binding(binding_num) {
Some(DescriptorBindingResources::Buffer(elements)) => elements.as_slice(),
_ => unreachable!(),
};
for (index, (&offset, element)) in
dynamic_offsets.iter().zip(elements).enumerate()
{
if !is_aligned(offset as DeviceSize, required_alignment) {
match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::UniformBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_uniform_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971",
],
..Default::default()
}));
}
DescriptorType::StorageBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::StorageBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_storage_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972",
],
..Default::default()
}));
}
_ => unreachable!(),
}
}
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
if offset as DeviceSize + range.end > buffer.size() {
return Err(Box::new(ValidationError {
problem: format!(
"the dynamic offset of `descriptor_sets[{}]` \
(for set number {}) for binding {} index {}, when \
added to `range.end` of the descriptor write, is \
greater than the size of the bound buffer",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979"],
..Default::default()
}));
}
}
}
}
}
if dynamic_offsets.len() != required_dynamic_offset_count {
return Err(Box::new(ValidationError {
problem: format!(
"the number of dynamic offsets provided for `descriptor_sets[{}]` \
(for set number {}) does not equal the number required ({})",
descriptor_sets_index, set_num, required_dynamic_offset_count,
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-dynamicOffsetCount-00359"],
..Default::default()
}));
}
}
Ok(()) Ok(())
} }
@ -73,7 +218,6 @@ impl<L> AutoCommandBufferBuilder<L> {
descriptor_sets: impl DescriptorSetsCollection, descriptor_sets: impl DescriptorSetsCollection,
) -> &mut Self { ) -> &mut Self {
let descriptor_sets = descriptor_sets.into_vec(); let descriptor_sets = descriptor_sets.into_vec();
if descriptor_sets.is_empty() { if descriptor_sets.is_empty() {
return self; return self;
} }
@ -95,11 +239,21 @@ impl<L> AutoCommandBufferBuilder<L> {
"bind_descriptor_sets", "bind_descriptor_sets",
Default::default(), Default::default(),
move |out: &mut RecordingCommandBuffer| { move |out: &mut RecordingCommandBuffer| {
let dynamic_offsets: SmallVec<[_; 32]> = descriptor_sets
.iter()
.flat_map(|x| x.as_ref().1.iter().copied())
.collect();
let descriptor_sets: SmallVec<[_; 12]> = descriptor_sets
.iter()
.map(|x| x.as_ref().0.as_raw())
.collect();
out.bind_descriptor_sets_unchecked( out.bind_descriptor_sets_unchecked(
pipeline_bind_point, pipeline_bind_point,
&pipeline_layout, &pipeline_layout,
first_set, first_set,
&descriptor_sets, &descriptor_sets,
&dynamic_offsets,
); );
}, },
); );
@ -434,13 +588,15 @@ impl RecordingCommandBuffer {
pipeline_bind_point: PipelineBindPoint, pipeline_bind_point: PipelineBindPoint,
pipeline_layout: &PipelineLayout, pipeline_layout: &PipelineLayout,
first_set: u32, first_set: u32,
descriptor_sets: &[DescriptorSetWithOffsets], descriptor_sets: &[&RawDescriptorSet],
dynamic_offsets: &[u32],
) -> Result<&mut Self, Box<ValidationError>> { ) -> Result<&mut Self, Box<ValidationError>> {
self.validate_bind_descriptor_sets( self.validate_bind_descriptor_sets(
pipeline_bind_point, pipeline_bind_point,
pipeline_layout, pipeline_layout,
first_set, first_set,
descriptor_sets, descriptor_sets,
dynamic_offsets,
)?; )?;
Ok(self.bind_descriptor_sets_unchecked( Ok(self.bind_descriptor_sets_unchecked(
@ -448,6 +604,7 @@ impl RecordingCommandBuffer {
pipeline_layout, pipeline_layout,
first_set, first_set,
descriptor_sets, descriptor_sets,
dynamic_offsets,
)) ))
} }
@ -456,7 +613,138 @@ impl RecordingCommandBuffer {
pipeline_bind_point: PipelineBindPoint, pipeline_bind_point: PipelineBindPoint,
pipeline_layout: &PipelineLayout, pipeline_layout: &PipelineLayout,
first_set: u32, first_set: u32,
descriptor_sets: &[DescriptorSetWithOffsets], descriptor_sets: &[&RawDescriptorSet],
dynamic_offsets: &[u32],
) -> Result<(), Box<ValidationError>> {
self.validate_bind_descriptor_sets_inner(
pipeline_bind_point,
pipeline_layout,
first_set,
descriptor_sets.len(),
)?;
let properties = self.device().physical_device().properties();
let mut dynamic_offsets_remaining = dynamic_offsets;
let mut required_dynamic_offset_count = 0;
for (descriptor_sets_index, set) in descriptor_sets.iter().enumerate() {
let set_num = first_set + descriptor_sets_index as u32;
// VUID-vkCmdBindDescriptorSets-commonparent
assert_eq!(self.device(), set.device());
let set_layout = set.layout();
let pipeline_set_layout = &pipeline_layout.set_layouts()[set_num as usize];
if !pipeline_set_layout.is_compatible_with(set_layout) {
return Err(Box::new(ValidationError {
problem: format!(
"`descriptor_sets[{0}]` (for set number {1}) is not compatible with \
`pipeline_layout.set_layouts()[{1}]`",
descriptor_sets_index, set_num
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358"],
..Default::default()
}));
}
for (&binding_num, binding) in set_layout.bindings() {
let required_alignment = match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
properties.min_uniform_buffer_offset_alignment
}
DescriptorType::StorageBufferDynamic => {
properties.min_storage_buffer_offset_alignment
}
_ => continue,
};
let count = if binding
.binding_flags
.intersects(DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT)
{
set.variable_descriptor_count()
} else {
binding.descriptor_count
} as usize;
required_dynamic_offset_count += count;
if !dynamic_offsets_remaining.is_empty() {
let split_index = min(count, dynamic_offsets_remaining.len());
let dynamic_offsets = &dynamic_offsets_remaining[..split_index];
dynamic_offsets_remaining = &dynamic_offsets_remaining[split_index..];
for (index, &offset) in dynamic_offsets.iter().enumerate() {
if !is_aligned(offset as DeviceSize, required_alignment) {
match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::UniformBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_uniform_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971",
],
..Default::default()
}));
}
DescriptorType::StorageBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::StorageBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_storage_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972",
],
..Default::default()
}));
}
_ => unreachable!(),
}
}
}
}
}
}
if dynamic_offsets.len() != required_dynamic_offset_count {
return Err(Box::new(ValidationError {
problem: format!(
"the number of dynamic offsets provided does not equal the number required \
({})",
required_dynamic_offset_count,
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-dynamicOffsetCount-00359"],
..Default::default()
}));
}
Ok(())
}
fn validate_bind_descriptor_sets_inner(
&self,
pipeline_bind_point: PipelineBindPoint,
pipeline_layout: &PipelineLayout,
first_set: u32,
descriptor_sets: usize,
) -> Result<(), Box<ValidationError>> { ) -> Result<(), Box<ValidationError>> {
pipeline_bind_point pipeline_bind_point
.validate_device(self.device()) .validate_device(self.device())
@ -508,7 +796,7 @@ impl RecordingCommandBuffer {
} }
} }
if first_set + descriptor_sets.len() as u32 > pipeline_layout.set_layouts().len() as u32 { if first_set + descriptor_sets as u32 > pipeline_layout.set_layouts().len() as u32 {
return Err(Box::new(ValidationError { return Err(Box::new(ValidationError {
problem: "`first_set + descriptor_sets.len()` is greater than \ problem: "`first_set + descriptor_sets.len()` is greater than \
`pipeline_layout.set_layouts().len()`" `pipeline_layout.set_layouts().len()`"
@ -518,148 +806,6 @@ impl RecordingCommandBuffer {
})); }));
} }
let properties = self.device().physical_device().properties();
for (descriptor_sets_index, set) in descriptor_sets.iter().enumerate() {
let set_num = first_set + descriptor_sets_index as u32;
let (set, dynamic_offsets) = set.as_ref();
// VUID-vkCmdBindDescriptorSets-commonparent
assert_eq!(self.device(), set.device());
let set_layout = set.layout();
let pipeline_set_layout = &pipeline_layout.set_layouts()[set_num as usize];
if !pipeline_set_layout.is_compatible_with(set_layout) {
return Err(Box::new(ValidationError {
problem: format!(
"`descriptor_sets[{0}]` (for set number {1}) is not compatible with \
`pipeline_layout.set_layouts()[{1}]`",
descriptor_sets_index, set_num
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-pDescriptorSets-00358"],
..Default::default()
}));
}
let mut dynamic_offsets_remaining = dynamic_offsets;
let mut required_dynamic_offset_count = 0;
for (&binding_num, binding) in set_layout.bindings() {
let required_alignment = match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
properties.min_uniform_buffer_offset_alignment
}
DescriptorType::StorageBufferDynamic => {
properties.min_storage_buffer_offset_alignment
}
_ => continue,
};
let count = if binding
.binding_flags
.intersects(DescriptorBindingFlags::VARIABLE_DESCRIPTOR_COUNT)
{
set.variable_descriptor_count()
} else {
binding.descriptor_count
} as usize;
required_dynamic_offset_count += count;
if !dynamic_offsets_remaining.is_empty() {
let split_index = min(count, dynamic_offsets_remaining.len());
let dynamic_offsets = &dynamic_offsets_remaining[..split_index];
dynamic_offsets_remaining = &dynamic_offsets_remaining[split_index..];
let resources = set.resources();
let elements = match resources.binding(binding_num) {
Some(DescriptorBindingResources::Buffer(elements)) => elements.as_slice(),
_ => unreachable!(),
};
for (index, (&offset, element)) in
dynamic_offsets.iter().zip(elements).enumerate()
{
if !is_aligned(offset as DeviceSize, required_alignment) {
match binding.descriptor_type {
DescriptorType::UniformBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::UniformBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_uniform_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01971",
],
..Default::default()
}));
}
DescriptorType::StorageBufferDynamic => {
return Err(Box::new(ValidationError {
problem: format!(
"the descriptor type of `descriptor_sets[{}]` \
(for set number {}) is \
`DescriptorType::StorageBufferDynamic`, but the \
dynamic offset provided for binding {} index {} is \
not aligned to the \
`min_storage_buffer_offset_alignment` device property",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &[
"VUID-vkCmdBindDescriptorSets-pDynamicOffsets-01972",
],
..Default::default()
}));
}
_ => unreachable!(),
}
}
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
if offset as DeviceSize + range.end > buffer.size() {
return Err(Box::new(ValidationError {
problem: format!(
"the dynamic offset of `descriptor_sets[{}]` \
(for set number {}) for binding {} index {}, when \
added to `range.end` of the descriptor write, is \
greater than the size of the bound buffer",
descriptor_sets_index, set_num, binding_num, index,
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979"],
..Default::default()
}));
}
}
}
}
}
if dynamic_offsets.len() != required_dynamic_offset_count {
return Err(Box::new(ValidationError {
problem: format!(
"the number of dynamic offsets provided for `descriptor_sets[{}]` \
(for set number {}) does not equal the number required ({})",
descriptor_sets_index, set_num, required_dynamic_offset_count,
)
.into(),
vuids: &["VUID-vkCmdBindDescriptorSets-dynamicOffsetCount-00359"],
..Default::default()
}));
}
}
Ok(()) Ok(())
} }
@ -669,20 +815,15 @@ impl RecordingCommandBuffer {
pipeline_bind_point: PipelineBindPoint, pipeline_bind_point: PipelineBindPoint,
pipeline_layout: &PipelineLayout, pipeline_layout: &PipelineLayout,
first_set: u32, first_set: u32,
descriptor_sets: &[DescriptorSetWithOffsets], descriptor_sets: &[&RawDescriptorSet],
dynamic_offsets: &[u32],
) -> &mut Self { ) -> &mut Self {
if descriptor_sets.is_empty() { if descriptor_sets.is_empty() {
return self; return self;
} }
let descriptor_sets_vk: SmallVec<[_; 12]> = descriptor_sets let descriptor_sets_vk: SmallVec<[_; 12]> =
.iter() descriptor_sets.iter().map(|x| x.handle()).collect();
.map(|x| x.as_ref().0.handle())
.collect();
let dynamic_offsets_vk: SmallVec<[_; 32]> = descriptor_sets
.iter()
.flat_map(|x| x.as_ref().1.iter().copied())
.collect();
let fns = self.device().fns(); let fns = self.device().fns();
(fns.v1_0.cmd_bind_descriptor_sets)( (fns.v1_0.cmd_bind_descriptor_sets)(
@ -692,8 +833,8 @@ impl RecordingCommandBuffer {
first_set, first_set,
descriptor_sets_vk.len() as u32, descriptor_sets_vk.len() as u32,
descriptor_sets_vk.as_ptr(), descriptor_sets_vk.as_ptr(),
dynamic_offsets_vk.len() as u32, dynamic_offsets.len() as u32,
dynamic_offsets_vk.as_ptr(), dynamic_offsets.as_ptr(),
); );
self self

View File

@ -144,6 +144,12 @@ impl DescriptorSet {
Ok(Arc::new(set)) Ok(Arc::new(set))
} }
/// Returns the inner raw descriptor set.
#[inline]
pub fn as_raw(&self) -> &RawDescriptorSet {
&self.inner
}
/// Returns the allocation of the descriptor set. /// Returns the allocation of the descriptor set.
#[inline] #[inline]
pub fn alloc(&self) -> &DescriptorPoolAlloc { pub fn alloc(&self) -> &DescriptorPoolAlloc {