diff --git a/vulkano/src/command_buffer/auto/builder.rs b/vulkano/src/command_buffer/auto/builder.rs index 43d80e896a..a62989ae63 100644 --- a/vulkano/src/command_buffer/auto/builder.rs +++ b/vulkano/src/command_buffer/auto/builder.rs @@ -1,5 +1,6 @@ use super::{ - CommandBuffer, CommandInfo, RenderPassCommand, Resource, ResourceUseRef2, SubmitState, + CommandBuffer, CommandInfo, PipelineEnum, RenderPassCommand, Resource, ResourceUseRef2, + SubmitState, UsedResources, }; use crate::{ buffer::{Buffer, IndexBuffer, Subbuffer}, @@ -26,7 +27,8 @@ use crate::{ vertex_input::VertexInputState, viewport::{Scissor, Viewport}, }, - ComputePipeline, DynamicState, GraphicsPipeline, PipelineBindPoint, PipelineLayout, + ComputePipeline, DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, + PipelineLayout, }, query::{QueryControlFlags, QueryPool, QueryType}, range_map::RangeMap, @@ -38,12 +40,13 @@ use crate::{ }, DeviceSize, Validated, ValidationError, VulkanError, }; -use ahash::HashMap; +use ahash::{HashMap, HashSet}; use parking_lot::{Mutex, RwLockReadGuard}; use smallvec::SmallVec; use std::{ collections::hash_map::Entry, fmt::Debug, + hash::{Hash, Hasher}, mem::take, ops::{Range, RangeInclusive}, sync::{atomic::AtomicBool, Arc}, @@ -175,20 +178,20 @@ impl RecordingCommandBuffer { ); // Add barriers between the commands. - for (command_info, _) in self.commands.iter() { - auto_sync_state.add_command(command_info).map_err(|err| { + auto_sync_state + .add_command_resources(self.commands.iter().map(|(cmd, _)| cmd)) + .map_err(|err| { Box::new(ValidationError { problem: format!( "unsolvable resource conflict between:\n\ - command resource use: {:?}\n\ - previous conflicting command resource use: {:?}", + command resource use: {:?}\n\ + previous conflicting command resource use: {:?}", err.current_use_ref, err.previous_use_ref, ) .into(), ..Default::default() }) })?; - } let (mut barriers, resources_usage, secondary_resources_usage) = auto_sync_state.build(); let final_barrier_index = self.commands.len(); @@ -266,6 +269,32 @@ impl RecordingCommandBuffer { name: &'static str, used_resources: Vec<(ResourceUseRef2, Resource)>, record_func: impl Fn(&mut RawRecordingCommandBuffer) + Send + Sync + 'static, + ) { + self.add_command_resources( + name, + UsedResources { + direct: used_resources, + deferred: None, + }, + record_func, + ) + } + + pub(in crate::command_buffer) fn add_command_deferred( + &mut self, + name: &'static str, + direct: Vec<(ResourceUseRef2, Resource)>, + deferred: Option<(PipelineEnum, DescriptorSetState)>, + record_func: impl Fn(&mut RawRecordingCommandBuffer) + Send + Sync + 'static, + ) { + self.add_command_resources(name, UsedResources::deferred(direct, deferred), record_func) + } + + fn add_command_resources( + &mut self, + name: &'static str, + used_resources: UsedResources, + record_func: impl Fn(&mut RawRecordingCommandBuffer) + Send + Sync + 'static, ) { self.commands.push(( CommandInfo { @@ -286,7 +315,7 @@ impl RecordingCommandBuffer { self.commands.push(( CommandInfo { name, - used_resources, + used_resources: UsedResources::direct(used_resources), render_pass: RenderPassCommand::Begin, }, Box::new(record_func), @@ -302,7 +331,7 @@ impl RecordingCommandBuffer { self.commands.push(( CommandInfo { name, - used_resources, + used_resources: UsedResources::direct(used_resources), render_pass: RenderPassCommand::End, }, Box::new(record_func), @@ -483,42 +512,131 @@ impl AutoSyncState { self.secondary_resources_usage, ) } +} + +#[derive(Debug)] +struct MergedCommandInfo<'a> { + render_pass: RenderPassCommand, + pipeline: Option<&'a PipelineEnum>, + direct: SmallVec<[(&'a Vec<(ResourceUseRef2, Resource)>, &'static str); 6]>, + deferred: SmallVec<[(&'a DescriptorSetState, &'static str); 6]>, +} + +impl<'a> MergedCommandInfo<'a> { + fn from(value: &'a CommandInfo) -> Self { + let (pipeline, deferred) = if let Some((pipeline, state)) = &value.used_resources.deferred { + (Some(pipeline), SmallVec::from_iter([(state, value.name)])) + } else { + (None, SmallVec::new()) + }; + let direct = if value.used_resources.direct.is_empty() { + SmallVec::new() + } else { + SmallVec::from_iter([(&value.used_resources.direct, value.name)]) + }; + Self { + render_pass: value.render_pass, + pipeline, + direct, + deferred, + } + } + + fn try_merge(&mut self, b: &'a CommandInfo) -> Result<(), MergedCommandInfo<'a>> { + let mut b = Self::from(b); + match (self.render_pass, b.render_pass) { + (RenderPassCommand::None, RenderPassCommand::None) => (), + _ => return Err(b), + } + if !(self.pipeline == b.pipeline || self.pipeline.is_none() || b.pipeline.is_none()) { + return Err(b); + } - fn add_command( + // success + if self.pipeline.is_none() { + self.pipeline = b.pipeline; + } + self.direct.append(&mut b.direct); + self.deferred.append(&mut b.deferred); + Ok(()) + } + + fn resolve_deferred( + &self, + pipeline: &Arc, + ) -> Vec<(ResourceUseRef2, Resource, &'static str)> { + let mut used_resources = Vec::new(); + let deferred_deduplicated = HashSet::from_iter(self.deferred.iter().copied()); + for (state, name) in &deferred_deduplicated { + RecordingCommandBuffer::add_descriptor_sets_resources( + &mut used_resources, + pipeline.as_ref(), + state, + name, + ); + } + used_resources + } +} + +impl AutoSyncState { + fn add_command_resources<'a>( &mut self, - command_info: &CommandInfo, + command_infos: impl Iterator, ) -> Result<(), UnsolvableResourceConflict> { - self.check_resource_conflicts(command_info)?; - self.add_resources(command_info); - - match command_info.render_pass { - RenderPassCommand::None => (), - RenderPassCommand::Begin => { - debug_assert!(self.latest_render_pass_enter.is_none()); - self.latest_render_pass_enter = Some(self.command_index); - } - RenderPassCommand::End => { - debug_assert!(self.latest_render_pass_enter.is_some()); - self.latest_render_pass_enter = None; + let merged = command_infos.fold(Vec::new(), |mut vec: Vec>, cmd| { + if let Some(last) = vec.last_mut() { + match last.try_merge(cmd) { + Ok(_) => vec, + Err(cmd) => { + vec.push(cmd); + vec + } + } + } else { + vec.push(MergedCommandInfo::from(cmd)); + vec } - } + }); - self.command_index += 1; + for cmd in &merged { + let deferred = match &cmd.pipeline { + Some(PipelineEnum::Compute(pipeline)) => cmd.resolve_deferred(pipeline), + Some(PipelineEnum::Graphics(pipeline)) => cmd.resolve_deferred(pipeline), + None => Vec::new(), + }; + let used_resources = || { + cmd.direct + .iter() + .flat_map(|(vec, name)| vec.iter().map(|(a, b)| (a, b, *name))) + .chain(deferred.iter().map(|(a, b, c)| (a, b, *c))) + }; + + self.check_resource_conflicts(used_resources())?; + self.add_resources(used_resources()); + + match cmd.render_pass { + RenderPassCommand::None => (), + RenderPassCommand::Begin => { + debug_assert!(self.latest_render_pass_enter.is_none()); + self.latest_render_pass_enter = Some(self.command_index); + } + RenderPassCommand::End => { + debug_assert!(self.latest_render_pass_enter.is_some()); + self.latest_render_pass_enter = None; + } + } + self.command_index += 1; + } Ok(()) } - fn check_resource_conflicts( + fn check_resource_conflicts<'a>( &self, - command_info: &CommandInfo, + used_resources: impl Iterator, ) -> Result<(), UnsolvableResourceConflict> { - let &CommandInfo { - name: command_name, - ref used_resources, - .. - } = command_info; - - for (use_ref, resource) in used_resources { + for (use_ref, resource, command_name) in used_resources { match *resource { Resource::Buffer { ref buffer, @@ -693,14 +811,11 @@ impl AutoSyncState { /// - `start_layout` and `end_layout` designate the image layout that the image is expected to /// be in when the command starts, and the image layout that the image will be transitioned /// to during the command. When it comes to buffers, you should pass `Undefined` for both. - fn add_resources(&mut self, command_info: &CommandInfo) { - let &CommandInfo { - name: command_name, - ref used_resources, - .. - } = command_info; - - for (use_ref, resource) in used_resources { + fn add_resources<'a>( + &mut self, + used_resources: impl Iterator, + ) { + for (use_ref, resource, command_name) in used_resources { match *resource { Resource::Buffer { ref buffer, @@ -1593,12 +1708,28 @@ pub(in crate::command_buffer) struct RenderPassStateAttachmentResolveInfo { pub(in crate::command_buffer) _image_layout: ImageLayout, } +#[derive(Clone, Debug, Eq, PartialEq)] pub(in crate::command_buffer) struct DescriptorSetState { pub(in crate::command_buffer) descriptor_sets: HashMap, pub(in crate::command_buffer) pipeline_layout: Arc, } -#[derive(Clone)] +impl Hash for DescriptorSetState { + /// HashMaps cannot be hashed, so we do our best job manually + fn hash(&self, state: &mut H) { + self.pipeline_layout.hash(state); + for (id, set_or_push) in &self.descriptor_sets { + id.hash(state); + match set_or_push { + SetOrPush::Set(set) => set.hash(state), + // push descriptors are expensive to hash and compare + SetOrPush::Push(_) => (), + } + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] pub(in crate::command_buffer) enum SetOrPush { Set(DescriptorSetWithOffsets), Push(DescriptorSetResources), diff --git a/vulkano/src/command_buffer/auto/mod.rs b/vulkano/src/command_buffer/auto/mod.rs index c89b376f95..03d9e0848d 100644 --- a/vulkano/src/command_buffer/auto/mod.rs +++ b/vulkano/src/command_buffer/auto/mod.rs @@ -72,6 +72,7 @@ use crate::{ buffer::Subbuffer, device::{Device, DeviceOwned}, image::{Image, ImageLayout, ImageSubresourceRange}, + pipeline::{ComputePipeline, GraphicsPipeline}, sync::PipelineStageAccessFlags, DeviceSize, ValidationError, VulkanObject, }; @@ -287,13 +288,51 @@ pub(super) enum Resource { }, } +pub(in crate::command_buffer) struct UsedResources { + direct: Vec<(ResourceUseRef2, Resource)>, + deferred: Option<(PipelineEnum, DescriptorSetState)>, +} + +#[derive(Clone, Eq, PartialEq)] +pub(in crate::command_buffer) enum PipelineEnum { + Compute(Arc), + Graphics(Arc), +} + +impl Debug for PipelineEnum { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + PipelineEnum::Compute(p) => f.debug_tuple("Compute").field(&p.handle()).finish(), + PipelineEnum::Graphics(p) => f.debug_tuple("Graphics").field(&p.handle()).finish(), + } + } +} + +impl UsedResources { + #[inline] + pub fn direct(direct: Vec<(ResourceUseRef2, Resource)>) -> Self { + Self { + direct, + deferred: None, + } + } + + #[inline] + pub fn deferred( + direct: Vec<(ResourceUseRef2, Resource)>, + deferred: Option<(PipelineEnum, DescriptorSetState)>, + ) -> Self { + Self { direct, deferred } + } +} + struct CommandInfo { name: &'static str, - used_resources: Vec<(ResourceUseRef2, Resource)>, + used_resources: UsedResources, render_pass: RenderPassCommand, } -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] enum RenderPassCommand { None, Begin, diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index 0f2c374619..d30ba1302e 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -4,7 +4,7 @@ use crate::{ acceleration_structure::AccelerationStructure, buffer::{view::BufferView, BufferUsage, Subbuffer}, command_buffer::{ - auto::{RenderPassState, RenderPassStateType, Resource, ResourceUseRef2}, + auto::{PipelineEnum, RenderPassState, RenderPassStateType, Resource, ResourceUseRef2}, sys::RawRecordingCommandBuffer, DispatchIndirectCommand, DrawIndexedIndirectCommand, DrawIndirectCommand, DrawMeshTasksIndirectCommand, RecordingCommandBuffer, ResourceInCommand, SubpassContents, @@ -30,6 +30,7 @@ use crate::{ DeviceSize, Requires, RequiresAllOf, RequiresOneOf, ValidationError, Version, VulkanObject, }; use std::{mem::size_of, sync::Arc}; +use vulkano::command_buffer::auto::DescriptorSetState; macro_rules! vuids { ($vuid_type:ident, $($id:literal),+ $(,)?) => { @@ -104,19 +105,16 @@ impl RecordingCommandBuffer { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn dispatch_unchecked(&mut self, group_counts: [u32; 3]) -> &mut Self { - let pipeline = self - .builder_state - .pipeline_compute - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_compute.as_ref().unwrap(); - let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Compute(pipeline.clone()), state)); - self.add_command( + self.add_command_deferred( "dispatch", - used_resources, + Default::default(), + deferred, move |out: &mut RawRecordingCommandBuffer| { out.dispatch_unchecked(group_counts); }, @@ -185,20 +183,18 @@ impl RecordingCommandBuffer { &mut self, indirect_buffer: Subbuffer<[DispatchIndirectCommand]>, ) -> &mut Self { - let pipeline = self - .builder_state - .pipeline_compute - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_compute.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Compute(pipeline.clone()), state)); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "dispatch", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.dispatch_indirect_unchecked(&indirect_buffer); }, @@ -372,20 +368,18 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); - self.add_command( + self.add_command_deferred( "draw", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_unchecked(vertex_count, instance_count, first_vertex, first_instance); }, @@ -478,21 +472,19 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_indirect", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_indirect_unchecked(&indirect_buffer, draw_count, stride); }, @@ -607,22 +599,20 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); self.add_indirect_buffer_resources(&mut used_resources, count_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_indirect_count", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_indirect_count_unchecked( &indirect_buffer, @@ -845,21 +835,19 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); self.add_index_buffer_resources(&mut used_resources); - self.add_command( + self.add_command_deferred( "draw_indexed", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_indexed_unchecked( index_count, @@ -973,22 +961,20 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); self.add_index_buffer_resources(&mut used_resources); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_indexed_indirect", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_indexed_indirect_unchecked(&indirect_buffer, draw_count, stride); }, @@ -1117,23 +1103,21 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_vertex_buffers_resources(&mut used_resources, pipeline); self.add_index_buffer_resources(&mut used_resources); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); self.add_indirect_buffer_resources(&mut used_resources, count_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_indexed_indirect_count", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_indexed_indirect_count_unchecked( &indirect_buffer, @@ -1313,19 +1297,16 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); - let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); - self.add_command( + self.add_command_deferred( "draw_mesh_tasks", - used_resources, + Default::default(), + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_mesh_tasks_unchecked(group_counts); }, @@ -1427,20 +1408,18 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_mesh_tasks_indirect", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_mesh_tasks_indirect_unchecked(&indirect_buffer, draw_count, stride); }, @@ -1564,21 +1543,19 @@ impl RecordingCommandBuffer { state.pipeline_used = true; } - let pipeline = self - .builder_state - .pipeline_graphics - .as_ref() - .unwrap() - .as_ref(); + let pipeline = self.builder_state.pipeline_graphics.as_ref().unwrap(); let mut used_resources = Vec::new(); - self.add_descriptor_sets_resources(&mut used_resources, pipeline); + let deferred = self + .prepare_descriptor_set_state(pipeline.as_ref()) + .map(|state| (PipelineEnum::Graphics(pipeline.clone()), state)); self.add_indirect_buffer_resources(&mut used_resources, indirect_buffer.as_bytes()); self.add_indirect_buffer_resources(&mut used_resources, count_buffer.as_bytes()); - self.add_command( + self.add_command_deferred( "draw_mesh_tasks_indirect_count", used_resources, + deferred, move |out: &mut RawRecordingCommandBuffer| { out.draw_mesh_tasks_indirect_count_unchecked( &indirect_buffer, @@ -3439,20 +3416,23 @@ impl RecordingCommandBuffer { Ok(()) } - fn add_descriptor_sets_resources( + fn prepare_descriptor_set_state( &self, - used_resources: &mut Vec<(ResourceUseRef2, Resource)>, pipeline: &Pl, - ) { - let descriptor_sets_state = match self - .builder_state + ) -> Option { + self.builder_state .descriptor_sets .get(&pipeline.bind_point()) - { - Some(x) => x, - None => return, - }; + .cloned() + } + pub(in crate::command_buffer) fn add_descriptor_sets_resources( + used_resources: &mut Vec<(ResourceUseRef2, Resource, &'static str)>, + pipeline: &Pl, + descriptor_sets_state: &DescriptorSetState, + name: &'static str, + ) { + // I want to dedup descriptor sets right here for (&(set, binding), binding_reqs) in pipeline.descriptor_binding_requirements() { let descriptor_type = descriptor_sets_state.pipeline_layout.set_layouts()[set as usize] .bindings()[&binding] @@ -3523,6 +3503,7 @@ impl RecordingCommandBuffer { range, memory_access, }, + name, )); } } @@ -3540,6 +3521,7 @@ impl RecordingCommandBuffer { range: range.clone(), memory_access, }, + name, )); } } @@ -3558,6 +3540,7 @@ impl RecordingCommandBuffer { range: buffer_view.range().clone(), memory_access, }, + name, )); } } @@ -3585,6 +3568,7 @@ impl RecordingCommandBuffer { start_layout: image_layout, end_layout: image_layout, }, + name, )); } } @@ -3612,6 +3596,7 @@ impl RecordingCommandBuffer { start_layout: image_layout, end_layout: image_layout, }, + name, )); } } @@ -3631,6 +3616,7 @@ impl RecordingCommandBuffer { range: 0..buffer.size(), memory_access, }, + name, )); } } diff --git a/vulkano/src/descriptor_set/mod.rs b/vulkano/src/descriptor_set/mod.rs index e9fa8052a9..2b928c05b0 100644 --- a/vulkano/src/descriptor_set/mod.rs +++ b/vulkano/src/descriptor_set/mod.rs @@ -318,7 +318,7 @@ impl Hash for DescriptorSet { } /// The resources that are bound to a descriptor set. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct DescriptorSetResources { binding_resources: HashMap, } @@ -435,7 +435,7 @@ impl DescriptorSetResources { } /// The resources that are bound to a single descriptor set binding. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub enum DescriptorBindingResources { None(Elements<()>), Buffer(Elements), @@ -623,7 +623,7 @@ impl DescriptorBindingResources { } } -#[derive(Clone)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub struct DescriptorSetWithOffsets { descriptor_set: Arc, dynamic_offsets: SmallVec<[u32; 4]>, diff --git a/vulkano/src/descriptor_set/update.rs b/vulkano/src/descriptor_set/update.rs index 07f815611b..1ed8fddfab 100644 --- a/vulkano/src/descriptor_set/update.rs +++ b/vulkano/src/descriptor_set/update.rs @@ -1524,7 +1524,7 @@ impl WriteDescriptorSetElements { } /// Parameters to write a buffer reference to a descriptor. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct DescriptorBufferInfo { /// The buffer to write to the descriptor. pub buffer: Subbuffer<[u8]>, @@ -1541,7 +1541,7 @@ pub struct DescriptorBufferInfo { } /// Parameters to write an image view reference to a descriptor. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct DescriptorImageViewInfo { /// The image view to write to the descriptor. pub image_view: Arc,