diff --git a/vulkano/src/command_buffer/synced.rs b/vulkano/src/command_buffer/synced.rs index 50c85dd8..ec21216b 100644 --- a/vulkano/src/command_buffer/synced.rs +++ b/vulkano/src/command_buffer/synced.rs @@ -10,6 +10,7 @@ use fnv::FnvHashMap; use smallvec::SmallVec; use std::any::Any; +use std::borrow::Cow; use std::collections::hash_map::Entry; use std::error; use std::fmt; @@ -36,6 +37,7 @@ use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear; use command_buffer::sys::UnsafeCommandBufferBuilderExecuteCommands; use command_buffer::sys::UnsafeCommandBufferBuilderImageBlit; use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier; +use descriptor::descriptor::DescriptorDescTy; use descriptor::descriptor::ShaderStages; use descriptor::descriptor_set::DescriptorSet; use descriptor::pipeline_layout::PipelineLayoutAbstract; @@ -92,6 +94,9 @@ pub struct SyncCommandBufferBuilder

{ // Stores all the commands that were submitted or are going to be submitted to the inner // builder. A copy of this `Arc` is stored in each `BuilderKey`. commands: Arc>>, + + // True if we're a secondary command buffer. + is_secondary: bool, } impl

fmt::Debug for SyncCommandBufferBuilder

{ @@ -105,15 +110,22 @@ impl

fmt::Debug for SyncCommandBufferBuilder

{ #[derive(Debug, Clone)] pub enum SyncCommandBufferBuilderError { /// Unsolvable conflict. - // TODO: add details - Conflict, + Conflict { + command1_name: &'static str, + command1_param: Cow<'static, str>, + command1_offset: usize, + + command2_name: &'static str, + command2_param: Cow<'static, str>, + command2_offset: usize, + }, } impl error::Error for SyncCommandBufferBuilderError { #[inline] fn description(&self) -> &str { match *self { - SyncCommandBufferBuilderError::Conflict => { + SyncCommandBufferBuilderError::Conflict { .. } => { "unsolvable conflict" }, } @@ -133,12 +145,19 @@ struct Commands

{ // `UnsafeCommandBufferBuilder`. first_unflushed: usize, + // If we're currently inside a render pass, contains the index of the `CmdBeginRenderPass` + // command. + latest_render_pass_enter: Option, + // The actual list. commands: Vec + Send + Sync>>, } // A single command within the list of commands. trait Command

{ + // Returns a user-friendly name for the command for error reporting purposes. + fn name(&self) -> &'static str; + // Sends the command to the `UnsafeCommandBufferBuilder`. Calling this method twice on the same // object may lead to a panic. unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

); @@ -154,6 +173,17 @@ trait Command

{ fn image(&self, num: usize) -> &ImageAccess { panic!() } + + // Returns a user-friendly name for the `num`th buffer used by the command, for error + // reporting purposes. + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + panic!() + } + // Returns a user-friendly name for the `num`th image used by the command, for error + // reporting purposes. + fn image_name(&self, num: usize) -> Cow<'static, str> { + panic!() + } } // Key that identifies a resource. Implements `PartialEq`, `Eq` and `Hash` so that two resources @@ -315,8 +345,13 @@ impl

SyncCommandBufferBuilder

{ R: RenderPassAbstract, F: FramebufferAbstract { + let (is_secondary, inside_render_pass) = match kind { + Kind::Primary => (false, false), + Kind::Secondary { ref render_pass, .. } => (true, render_pass.is_some()), + }; + let cmd = UnsafeCommandBufferBuilder::new(pool, kind, flags)?; - Ok(SyncCommandBufferBuilder::from_unsafe_cmd(cmd)) + Ok(SyncCommandBufferBuilder::from_unsafe_cmd(cmd, is_secondary, inside_render_pass)) } /// Builds a `SyncCommandBufferBuilder` from an existing `UnsafeCommandBufferBuilder`. @@ -329,16 +364,24 @@ impl

SyncCommandBufferBuilder

{ /// you must take into account the fact that the `SyncCommandBufferBuilder` won't be aware of /// any existing resource usage. #[inline] - pub unsafe fn from_unsafe_cmd(cmd: UnsafeCommandBufferBuilder

) - -> SyncCommandBufferBuilder

{ + pub unsafe fn from_unsafe_cmd(cmd: UnsafeCommandBufferBuilder

, is_secondary: bool, + inside_render_pass: bool) -> SyncCommandBufferBuilder

{ + let latest_render_pass_enter = if inside_render_pass { + Some(0) + } else { + None + }; + SyncCommandBufferBuilder { inner: cmd, resources: FnvHashMap::default(), pending_barrier: UnsafeCommandBufferBuilderPipelineBarrier::new(), commands: Arc::new(Mutex::new(Commands { first_unflushed: 0, + latest_render_pass_enter, commands: Vec::new(), })), + is_secondary, } } @@ -373,10 +416,9 @@ impl

SyncCommandBufferBuilder

{ Entry::Occupied(entry) => { let collision_command_id = entry.key().command_id; debug_assert!(collision_command_id <= latest_command_id); - if collision_command_id == latest_command_id { - return Err(SyncCommandBufferBuilderError::Conflict); - } + let entry_key_resource_index = entry.key().resource_index; + let entry_key_resource_ty = entry.key().resource_ty; let mut entry = entry.into_mut(); // Find out if we have a collision with the pending commands. @@ -394,11 +436,33 @@ impl

SyncCommandBufferBuilder

{ self.pending_barrier = UnsafeCommandBufferBuilderPipelineBarrier::new(); { let mut commands_lock = self.commands.lock().unwrap(); - let f = commands_lock.first_unflushed; - for command in &mut commands_lock.commands[f .. latest_command_id] { + let start = commands_lock.first_unflushed; + let end = if let Some(rp_enter) = commands_lock.latest_render_pass_enter { + rp_enter + } else { + latest_command_id + }; + if collision_command_id >= end { + return Err(SyncCommandBufferBuilderError::Conflict { + command1_name: commands_lock.commands[collision_command_id].name(), + command1_param: match entry_key_resource_ty { + KeyTy::Buffer => commands_lock.commands[collision_command_id].buffer_name(entry_key_resource_index), + KeyTy::Image => commands_lock.commands[collision_command_id].image_name(entry_key_resource_index), + }, + command1_offset: collision_command_id, + + command2_name: commands_lock.commands[latest_command_id].name(), + command2_param: match resource_ty { + KeyTy::Buffer => commands_lock.commands[latest_command_id].buffer_name(resource_index), + KeyTy::Image => commands_lock.commands[latest_command_id].image_name(resource_index), + }, + command2_offset: latest_command_id, + }); + } + for command in &mut commands_lock.commands[start .. end] { command.send(&mut self.inner); } - commands_lock.first_unflushed = latest_command_id; + commands_lock.first_unflushed = end; } } } @@ -448,7 +512,7 @@ impl

SyncCommandBufferBuilder

{ entry.access = access; entry.exclusive_any = true; entry.exclusive = exclusive; - if exclusive { + if exclusive || end_layout != ImageLayout::Undefined { // Only modify the layout in case of a write, because buffer operations // pass `Undefined` for the layout. While a buffer write *must* set the // layout to `Undefined`, a buffer read must not touch it. @@ -466,7 +530,8 @@ impl

SyncCommandBufferBuilder

{ // Handle the case when the initial layout requirement of the image is different // from the first layout usage. - if resource_ty == KeyTy::Image && start_layout != ImageLayout::Undefined && + if !self.is_secondary && resource_ty == KeyTy::Image && + start_layout != ImageLayout::Undefined && start_layout != ImageLayout::Preinitialized { let commands_lock = self.commands.lock().unwrap(); @@ -515,6 +580,8 @@ impl

SyncCommandBufferBuilder

{ where P: CommandPoolBuilderAlloc { let mut commands_lock = self.commands.lock().unwrap(); + debug_assert!(commands_lock.latest_render_pass_enter.is_none() || + self.pending_barrier.is_empty()); // Flush the commands that haven't been flushed yet. unsafe { @@ -526,37 +593,39 @@ impl

SyncCommandBufferBuilder

{ } // Transition images to their desired final layout. - unsafe { - let mut barrier = UnsafeCommandBufferBuilderPipelineBarrier::new(); + if !self.is_secondary { + unsafe { + let mut barrier = UnsafeCommandBufferBuilderPipelineBarrier::new(); - for (key, mut state) in &mut self.resources { - if key.resource_ty != KeyTy::Image { - continue; + for (key, mut state) in &mut self.resources { + if key.resource_ty != KeyTy::Image { + continue; + } + + let img = commands_lock.commands[key.command_id].image(key.resource_index); + if img.final_layout_requirement() == state.current_layout { + continue; + } + + state.exclusive_any = true; + barrier.add_image_memory_barrier(img, + 0 .. img.mipmap_levels(), + 0 .. img.dimensions().array_layers(), + state.stages, + state.access, + PipelineStages { + bottom_of_pipe: true, + ..PipelineStages::none() + }, // TODO:? + AccessFlagBits::none(), + true, + None, // TODO: access? + state.current_layout, + img.final_layout_requirement()); } - let img = commands_lock.commands[key.command_id].image(key.resource_index); - if img.final_layout_requirement() == state.current_layout { - continue; - } - - state.exclusive_any = true; - barrier.add_image_memory_barrier(img, - 0 .. img.mipmap_levels(), - 0 .. img.dimensions().array_layers(), - state.stages, - state.access, - PipelineStages { - bottom_of_pipe: true, - ..PipelineStages::none() - }, // TODO:? - AccessFlagBits::none(), - true, - None, // TODO: access? - state.current_layout, - img.final_layout_requirement()); + self.inner.pipeline_barrier(&barrier); } - - self.inner.pipeline_barrier(&barrier); } // Fill the `commands` list. @@ -606,6 +675,10 @@ impl

SyncCommandBufferBuilder

{ where F: FramebufferAbstract + Send + Sync + 'static, I: Iterator { + fn name(&self) -> &'static str { + "vkCmdBeginRenderPass" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.begin_render_pass(&self.framebuffer, self.subpass_contents, @@ -627,6 +700,10 @@ impl

SyncCommandBufferBuilder

{ fn image(&self, num: usize) -> &ImageAccess { self.framebuffer.attached_image_view(num).unwrap().parent() } + + fn image_name(&self, num: usize) -> Cow<'static, str> { + format!("attachment {}", num).into() + } } let atch_desc = (0 .. framebuffer.num_attachments()) @@ -658,6 +735,11 @@ impl

SyncCommandBufferBuilder

{ desc.initial_layout, desc.final_layout)?; } + { + let mut cmd_lock = self.commands.lock().unwrap(); + cmd_lock.latest_render_pass_enter = Some(cmd_lock.commands.len() - 1); + } + Ok(()) } @@ -675,6 +757,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where B: BufferAccess + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdBindIndexBuffer" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.bind_index_buffer(&self.buffer, self.index_ty); } @@ -696,6 +782,11 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "index buffer".into() + } } self.commands @@ -731,6 +822,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where Gp: GraphicsPipelineAbstract + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdBindPipeline" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.bind_pipeline_graphics(&self.pipeline); } @@ -764,6 +859,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where Gp: ComputePipelineAbstract + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdBindPipeline" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.bind_pipeline_compute(&self.pipeline); } @@ -833,6 +932,10 @@ impl

SyncCommandBufferBuilder

{ D: ImageAccess + Send + Sync + 'static, R: Iterator { + fn name(&self) -> &'static str { + "vkCmdBlitImage" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.blit_image(self.source.as_ref().unwrap(), self.source_layout, self.destination.as_ref().unwrap(), self.destination_layout, @@ -871,6 +974,16 @@ impl

SyncCommandBufferBuilder

{ panic!() } } + + fn image_name(&self, num: usize) -> Cow<'static, str> { + if num == 0 { + "source".into() + } else if num == 1 { + "destination".into() + } else { + panic!() + } + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -931,6 +1044,10 @@ impl

SyncCommandBufferBuilder

{ where I: ImageAccess + Send + Sync + 'static, R: Iterator + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdClearColorImage" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.clear_color_image(self.image.as_ref().unwrap(), self.layout, self.color, self.regions.take().unwrap()); @@ -955,6 +1072,11 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); self.image.as_ref().unwrap() } + + fn image_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "target".into() + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1001,6 +1123,10 @@ impl

SyncCommandBufferBuilder

{ D: BufferAccess + Send + Sync + 'static, R: Iterator { + fn name(&self) -> &'static str { + "vkCmdCopyBuffer" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.copy_buffer(self.source.as_ref().unwrap(), self.destination.as_ref().unwrap(), @@ -1034,6 +1160,14 @@ impl

SyncCommandBufferBuilder

{ _ => panic!(), } } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + match num { + 0 => "source".into(), + 1 => "destination".into(), + _ => panic!(), + } + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1094,6 +1228,10 @@ impl

SyncCommandBufferBuilder

{ D: ImageAccess + Send + Sync + 'static, R: Iterator { + fn name(&self) -> &'static str { + "vkCmdCopyBufferToImage" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.copy_buffer_to_image(self.source.as_ref().unwrap(), self.destination.as_ref().unwrap(), @@ -1129,10 +1267,20 @@ impl

SyncCommandBufferBuilder

{ self.source.as_ref().unwrap() } + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "source".into() + } + fn image(&self, num: usize) -> &ImageAccess { assert_eq!(num, 0); self.destination.as_ref().unwrap() } + + fn image_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "destination".into() + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1194,6 +1342,10 @@ impl

SyncCommandBufferBuilder

{ D: BufferAccess + Send + Sync + 'static, R: Iterator { + fn name(&self) -> &'static str { + "vkCmdCopyImageToBuffer" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.copy_image_to_buffer(self.source.as_ref().unwrap(), self.source_layout, @@ -1229,10 +1381,20 @@ impl

SyncCommandBufferBuilder

{ self.destination.as_ref().unwrap() } + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "destination".into() + } + fn image(&self, num: usize) -> &ImageAccess { assert_eq!(num, 0); self.source.as_ref().unwrap() } + + fn image_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "source".into() + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1278,6 +1440,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdDispatch" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.dispatch(self.dimensions); } @@ -1307,6 +1473,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where B: BufferAccess + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdDispatchIndirect" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.dispatch_indirect(&self.buffer); } @@ -1328,6 +1498,11 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "indirect buffer".into() + } } self.commands @@ -1363,6 +1538,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdDraw" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.draw(self.vertex_count, self.instance_count, @@ -1397,6 +1576,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdDrawIndexed" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.draw_indexed(self.index_count, self.instance_count, @@ -1434,6 +1617,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where B: BufferAccess + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdDrawIndirect" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.draw_indirect(&self.buffer, self.draw_count, self.stride); } @@ -1455,6 +1642,11 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "indirect buffer".into() + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1493,6 +1685,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where B: BufferAccess + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdDrawIndexedIndirect" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.draw_indexed_indirect(&self.buffer, self.draw_count, self.stride); } @@ -1514,6 +1710,11 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + assert_eq!(num, 0); + "indirect buffer".into() + } } self.commands.lock().unwrap().commands.push(Box::new(Cmd { @@ -1543,6 +1744,10 @@ impl

SyncCommandBufferBuilder

{ struct Cmd; impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdEndRenderPass" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.end_render_pass(); } @@ -1552,7 +1757,10 @@ impl

SyncCommandBufferBuilder

{ } } - self.commands.lock().unwrap().commands.push(Box::new(Cmd)); + let mut cmd_lock = self.commands.lock().unwrap(); + cmd_lock.commands.push(Box::new(Cmd)); + debug_assert!(cmd_lock.latest_render_pass_enter.is_some()); + cmd_lock.latest_render_pass_enter = None; } /// Starts the process of executing secondary command buffers. Returns an intermediate struct @@ -1579,6 +1787,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where B: BufferAccess + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdFillBuffer" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.fill_buffer(&self.buffer, self.data); } @@ -1600,6 +1812,10 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + "destination".into() + } } self.commands @@ -1631,6 +1847,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdNextSubpass" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.next_subpass(self.subpass_contents); } @@ -1665,6 +1885,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where Pl: PipelineLayoutAbstract + Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdPushConstants" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.push_constants::<_, [u8]>(&self.pipeline_layout, self.stages, @@ -1709,6 +1933,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdResetEvent" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.reset_event(&self.event, self.stages); } @@ -1736,6 +1964,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdSetBlendConstants" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_blend_constants(self.constants); } @@ -1762,6 +1994,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdSetDepthBias" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_depth_bias(self.constant_factor, self.clamp, self.slope_factor); } @@ -1787,6 +2023,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdSetDepthBounds" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_depth_bounds(self.min, self.max); } @@ -1812,6 +2052,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdSetEvent" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_event(&self.event, self.stages); } @@ -1839,6 +2083,10 @@ impl

SyncCommandBufferBuilder

{ } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdSetLineWidth" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_line_width(self.line_width); } @@ -1872,6 +2120,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where I: Iterator { + fn name(&self) -> &'static str { + "vkCmdSetScissor" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_scissor(self.first_scissor, self.scissors.take().unwrap()); } @@ -1902,6 +2154,10 @@ impl

SyncCommandBufferBuilder

{ impl Command

for Cmd where I: Iterator { + fn name(&self) -> &'static str { + "vkCmdSetViewport" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.set_viewport(self.first_viewport, self.viewports.take().unwrap()); } @@ -1932,6 +2188,10 @@ impl

SyncCommandBufferBuilder

{ where B: BufferAccess + Send + Sync + 'static, D: Send + Sync + 'static { + fn name(&self) -> &'static str { + "vkCmdUpdateBuffer" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.update_buffer(&self.buffer, &self.data); } @@ -1953,6 +2213,10 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + "destination".into() + } } self.commands @@ -2017,6 +2281,10 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { where Pl: PipelineLayoutAbstract, I: Iterator { + fn name(&self) -> &'static str { + "vkCmdBindDescriptorSets" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.bind_descriptor_sets(self.graphics, &self.pipeline_layout, @@ -2028,12 +2296,119 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { fn into_final_command(self: Box) -> Box { struct Fin(SmallVec<[Box; 12]>); impl FinalCommand for Fin { - /* TODO: implement buffer() and image() */ + fn buffer(&self, mut num: usize) -> &BufferAccess { + for set in self.0.iter() { + if let Some(buf) = set.buffer(num) { + return buf.0; + } + num -= set.num_buffers(); + } + panic!() + } + fn image(&self, mut num: usize) -> &ImageAccess { + for set in self.0.iter() { + if let Some(img) = set.image(num) { + return img.0.parent(); + } + num -= set.num_images(); + } + panic!() + } } Box::new(Fin(self.inner)) } + + fn buffer(&self, mut num: usize) -> &BufferAccess { + for set in self.inner.iter() { + if let Some(buf) = set.buffer(num) { + return buf.0; + } + num -= set.num_buffers(); + } + panic!() + } + + fn buffer_name(&self, mut num: usize) -> Cow<'static, str> { + for (set_num, set) in self.inner.iter().enumerate() { + if let Some(buf) = set.buffer(num) { + return format!("Buffer bound to descriptor {} of set {}", buf.1, set_num).into(); + } + num -= set.num_buffers(); + } + panic!() + } + + fn image(&self, mut num: usize) -> &ImageAccess { + for set in self.inner.iter() { + if let Some(img) = set.image(num) { + return img.0.parent(); + } + num -= set.num_images(); + } + panic!() + } + + fn image_name(&self, mut num: usize) -> Cow<'static, str> { + for (set_num, set) in self.inner.iter().enumerate() { + if let Some(img) = set.image(num) { + return format!("Image bound to descriptor {} of set {}", img.1, set_num).into(); + } + num -= set.num_images(); + } + panic!() + } } + let all_buffers = { + let mut all_buffers = Vec::new(); + for ds in self.inner.iter() { + for buf_num in 0 .. ds.num_buffers() { + let desc = ds.descriptor(ds.buffer(buf_num).unwrap().1 as usize).unwrap(); + let write = !desc.readonly; + let (stages, access) = desc.pipeline_stages_and_access(); + all_buffers.push((write, stages, access)); + } + } + all_buffers + }; + + let all_images = { + let mut all_images = Vec::new(); + for ds in self.inner.iter() { + for img_num in 0 .. ds.num_images() { + let (image_view, desc_num) = ds.image(img_num).unwrap(); + let desc = ds.descriptor(desc_num as usize).unwrap(); + let write = !desc.readonly; + let (stages, access) = desc.pipeline_stages_and_access(); + let mut ignore_me_hack = false; + let layout = match desc.ty { + DescriptorDescTy::CombinedImageSampler(_) => { + image_view.descriptor_set_combined_image_sampler_layout() + }, + DescriptorDescTy::Image(ref img) => { + if img.sampled { + image_view.descriptor_set_sampled_image_layout() + } else { + image_view.descriptor_set_storage_image_layout() + } + }, + DescriptorDescTy::InputAttachment { .. } => { + // FIXME: This is tricky. Since we read from the input attachment + // and this input attachment is being written in an earlier pass, + // vulkano will think that it needs to put a pipeline barrier and will + // return a `Conflict` error. For now as a work-around we simply ignore + // input attachments. + ignore_me_hack = true; + image_view.descriptor_set_input_attachment_layout() + }, + _ => panic!("Tried to bind an image to a non-image descriptor") + }; + all_images.push((write, stages, access, layout, ignore_me_hack)); + } + } + all_images + }; + self.builder .commands .lock() @@ -2047,7 +2422,22 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { dynamic_offsets: Some(dynamic_offsets), })); - // FIXME: add resources + for (n, (write, stages, access)) in all_buffers.into_iter().enumerate() { + self.builder + .prev_cmd_resource(KeyTy::Buffer, + n, write, stages, access, + ImageLayout::Undefined, + ImageLayout::Undefined)?; + } + + for (n, (write, stages, access, layout, ignore_me_hack)) in all_images.into_iter().enumerate() { + if ignore_me_hack { continue; } + self.builder + .prev_cmd_resource(KeyTy::Image, + n, write, stages, access, + layout, + layout)?; + } Ok(()) } @@ -2079,6 +2469,10 @@ impl<'a, P> SyncCommandBufferBuilderBindVertexBuffer<'a, P> { } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdBindVertexBuffers" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.bind_vertex_buffers(self.first_binding, self.inner.take().unwrap()); } @@ -2096,6 +2490,10 @@ impl<'a, P> SyncCommandBufferBuilderBindVertexBuffer<'a, P> { fn buffer(&self, num: usize) -> &BufferAccess { &self.buffers[num] } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + format!("Buffer #{}", num).into() + } } let num_buffers = self.buffers.len(); @@ -2158,6 +2556,10 @@ impl<'a, P> SyncCommandBufferBuilderExecuteCommands<'a, P> { } impl

Command

for Cmd { + fn name(&self) -> &'static str { + "vkCmdExecuteCommands" + } + unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder

) { out.execute_commands(self.inner.take().unwrap()); } diff --git a/vulkano/src/descriptor/descriptor.rs b/vulkano/src/descriptor/descriptor.rs index a2fceae5..81db1bc7 100644 --- a/vulkano/src/descriptor/descriptor.rs +++ b/vulkano/src/descriptor/descriptor.rs @@ -43,6 +43,8 @@ use format::Format; use image::Dimensions; +use sync::AccessFlagBits; +use sync::PipelineStages; use std::cmp; use std::ops::BitOr; use vk; @@ -100,6 +102,56 @@ impl DescriptorDesc { readonly: self.readonly && other.readonly, }) } + + /// Returns the pipeline stages and access flags corresponding to the usage of this descriptor. + /// + /// # Panic + /// + /// Panicks if the type if `Sampler`. + /// + pub fn pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlagBits) { + let stages: PipelineStages = self.stages.into(); + + let access = match self.ty { + DescriptorDescTy::Sampler => panic!(), + DescriptorDescTy::CombinedImageSampler(_) | DescriptorDescTy::Image(_) => { + AccessFlagBits { + shader_read: true, + shader_write: !self.readonly, + .. AccessFlagBits::none() + } + }, + DescriptorDescTy::TexelBuffer { .. } => { + AccessFlagBits { + shader_read: true, + shader_write: !self.readonly, + .. AccessFlagBits::none() + } + }, + DescriptorDescTy::InputAttachment { .. } => { + AccessFlagBits { + input_attachment_read: true, + .. AccessFlagBits::none() + } + }, + DescriptorDescTy::Buffer(ref buf) => { + if buf.storage { + AccessFlagBits { + shader_read: true, + shader_write: !self.readonly, + .. AccessFlagBits::none() + } + } else { + AccessFlagBits { + uniform_read: true, + .. AccessFlagBits::none() + } + } + }, + }; + + (stages, access) + } } /// Describes the content and layout of each array element of a descriptor. @@ -472,6 +524,21 @@ impl BitOr for ShaderStages { } } +impl From for PipelineStages { + #[inline] + fn from(stages: ShaderStages) -> PipelineStages { + PipelineStages { + vertex_shader: stages.vertex, + tessellation_control_shader: stages.tessellation_control, + tessellation_evaluation_shader: stages.tessellation_evaluation, + geometry_shader: stages.geometry, + fragment_shader: stages.fragment, + compute_shader: stages.compute, + .. PipelineStages::none() + } + } +} + #[doc(hidden)] impl Into for ShaderStages { #[inline] diff --git a/vulkano/src/descriptor/descriptor_set/collection.rs b/vulkano/src/descriptor/descriptor_set/collection.rs index 08ff600a..27b22b65 100644 --- a/vulkano/src/descriptor/descriptor_set/collection.rs +++ b/vulkano/src/descriptor/descriptor_set/collection.rs @@ -7,12 +7,9 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use buffer::BufferAccess; use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor_set::DescriptorSet; use descriptor::descriptor_set::DescriptorSetDesc; -use image::ImageAccess; -use std::iter; /// A collection of descriptor set objects. pub unsafe trait DescriptorSetsCollection { @@ -21,18 +18,14 @@ pub unsafe trait DescriptorSetsCollection { /// Returns the number of descriptors in the set. Includes possibly empty descriptors. /// /// Returns `None` if the set is out of range. + // TODO: remove ; user should just use `into_vec` instead fn num_bindings_in_set(&self, set: usize) -> Option; /// Returns the descriptor for the given binding of the given set. /// /// Returns `None` if out of range. + // TODO: remove ; user should just use `into_vec` instead fn descriptor(&self, set: usize, binding: usize) -> Option; - - /// Returns the list of buffers used by this descriptor set. Includes buffer views. - fn buffers_list<'a>(&'a self) -> Box + 'a>; - - /// Returns the list of images used by this descriptor set. Includes image views. - fn images_list<'a>(&'a self) -> Box + 'a>; } unsafe impl DescriptorSetsCollection for () { @@ -50,16 +43,6 @@ unsafe impl DescriptorSetsCollection for () { fn descriptor(&self, set: usize, binding: usize) -> Option { None } - - #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - Box::new(iter::empty()) - } - - #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - Box::new(iter::empty()) - } } unsafe impl DescriptorSetsCollection for T @@ -85,16 +68,6 @@ unsafe impl DescriptorSetsCollection for T _ => None, } } - - #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - DescriptorSet::buffers_list(self) - } - - #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - DescriptorSet::images_list(self) - } } macro_rules! impl_collection { @@ -158,32 +131,6 @@ macro_rules! impl_collection { None } - - #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - #![allow(non_snake_case)] - - let &(ref first, $(ref $others,)*) = self; - let mut output = Vec::new(); - output.extend(first.buffers_list()); - $( - output.extend($others.buffers_list()); - )* - Box::new(output.into_iter()) - } - - #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - #![allow(non_snake_case)] - - let &(ref first, $(ref $others,)*) = self; - let mut output = Vec::new(); - output.extend(first.images_list()); - $( - output.extend($others.images_list()); - )* - Box::new(output.into_iter()) - } } impl_collection!($($others),+); diff --git a/vulkano/src/descriptor/descriptor_set/mod.rs b/vulkano/src/descriptor/descriptor_set/mod.rs index 75a6ed76..f88fc73b 100644 --- a/vulkano/src/descriptor/descriptor_set/mod.rs +++ b/vulkano/src/descriptor/descriptor_set/mod.rs @@ -38,7 +38,7 @@ use SafeDeref; use buffer::BufferAccess; use descriptor::descriptor::DescriptorDesc; -use image::ImageAccess; +use image::ImageViewAccess; pub use self::collection::DescriptorSetsCollection; pub use self::persistent::PersistentDescriptorSet; @@ -78,13 +78,23 @@ pub unsafe trait DescriptorSet: DescriptorSetDesc { /// Returns the inner `UnsafeDescriptorSet`. fn inner(&self) -> &UnsafeDescriptorSet; - /// Returns the list of buffers used by this descriptor set. Includes buffer views. - // TODO: meh for boxing - fn buffers_list<'a>(&'a self) -> Box + 'a>; + /// Returns the number of buffers within this descriptor set. + fn num_buffers(&self) -> usize; + + /// Returns the `index`th buffer of this descriptor set, or `None` if out of range. Also + /// returns the index of the descriptor that uses this buffer. + /// + /// The valid range is between 0 and `num_buffers()`. + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)>; - /// Returns the list of images used by this descriptor set. Includes image views. - // TODO: meh for boxing - fn images_list<'a>(&'a self) -> Box + 'a>; + /// Returns the number of images within this descriptor set. + fn num_images(&self) -> usize; + + /// Returns the `index`th image of this descriptor set, or `None` if out of range. Also returns + /// the index of the descriptor that uses this image. + /// + /// The valid range is between 0 and `num_images()`. + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)>; } unsafe impl DescriptorSet for T @@ -97,13 +107,23 @@ unsafe impl DescriptorSet for T } #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - (**self).buffers_list() + fn num_buffers(&self) -> usize { + (**self).num_buffers() + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + (**self).buffer(index) } #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - (**self).images_list() + fn num_images(&self) -> usize { + (**self).num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + (**self).image(index) } } diff --git a/vulkano/src/descriptor/descriptor_set/persistent.rs b/vulkano/src/descriptor/descriptor_set/persistent.rs index 4e5c6ec6..1f34454a 100644 --- a/vulkano/src/descriptor/descriptor_set/persistent.rs +++ b/vulkano/src/descriptor/descriptor_set/persistent.rs @@ -31,12 +31,8 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract; use device::Device; use device::DeviceOwned; use format::Format; -use image::ImageAccess; -use image::ImageLayout; use image::ImageViewAccess; use sampler::Sampler; -use sync::AccessFlagBits; -use sync::PipelineStages; use OomError; use VulkanObject; @@ -58,21 +54,23 @@ use VulkanObject; /// /// # Example // TODO: -pub struct PersistentDescriptorSet { +pub struct PersistentDescriptorSet { inner: P, resources: R, + pipeline_layout: L, + set_id: usize, layout: Arc } -impl PersistentDescriptorSet<()> { +impl PersistentDescriptorSet { /// Starts the process of building a `PersistentDescriptorSet`. Returns a builder. /// /// # Panic /// /// - Panics if the set id is out of range. /// - pub fn start(layout: Pl, set_id: usize) -> PersistentDescriptorSetBuilder - where Pl: PipelineLayoutAbstract + pub fn start(layout: L, set_id: usize) -> PersistentDescriptorSetBuilder + where L: PipelineLayoutAbstract { assert!(layout.num_sets() > set_id); @@ -88,33 +86,48 @@ impl PersistentDescriptorSet<()> { } } -unsafe impl DescriptorSet for PersistentDescriptorSet where P: DescriptorPoolAlloc { +unsafe impl DescriptorSet for PersistentDescriptorSet + where L: PipelineLayoutAbstract, + P: DescriptorPoolAlloc, + R: PersistentDescriptorSetResources +{ #[inline] fn inner(&self) -> &UnsafeDescriptorSet { self.inner.inner() } #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() + fn num_buffers(&self) -> usize { + self.resources.num_buffers() } #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + self.resources.buffer(index) + } + + #[inline] + fn num_images(&self) -> usize { + self.resources.num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + self.resources.image(index) } } -// TODO: is DescriptorSetDesc really necessary? -unsafe impl DescriptorSetDesc for PersistentDescriptorSet { +unsafe impl DescriptorSetDesc for PersistentDescriptorSet + where L: PipelineLayoutAbstract +{ #[inline] fn num_bindings(&self) -> usize { - unimplemented!() // FIXME: + self.pipeline_layout.num_bindings_in_set(self.set_id).unwrap() } #[inline] fn descriptor(&self, binding: usize) -> Option { - unimplemented!() // FIXME: + self.pipeline_layout.descriptor(self.set_id, binding) } } @@ -154,7 +167,7 @@ impl PersistentDescriptorSetBuilder { /// Builds a `PersistentDescriptorSet` from the builder. #[inline] - pub fn build(self) -> Result, PersistentDescriptorSetBuildError> { + pub fn build(self) -> Result, PersistentDescriptorSetBuildError> { let pool = Device::standard_descriptor_pool(self.layout.device()); self.build_with_pool(pool) } @@ -166,7 +179,7 @@ impl PersistentDescriptorSetBuilder /// Panics if the pool doesn't have the same device as the pipeline layout. /// pub fn build_with_pool

(self, pool: P) - -> Result, PersistentDescriptorSetBuildError> + -> Result, PersistentDescriptorSetBuildError> where P: DescriptorPool { assert_eq!(self.layout.device().internal_object(), @@ -196,6 +209,8 @@ impl PersistentDescriptorSetBuilder Ok(PersistentDescriptorSet { inner: set, resources: self.resources, + pipeline_layout: self.layout, + set_id: self.set_id, layout: set_layout, }) } @@ -419,9 +434,7 @@ impl PersistentDescriptorSetBuilderArray where L: PipelineLayoutAbst writes: self.builder.writes, resources: (self.builder.resources, PersistentDescriptorSetBuf { buffer: buffer, - write: !readonly, - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: + descriptor_num: self.builder.binding_id as u32, }) }, desc: self.desc, @@ -487,9 +500,7 @@ impl PersistentDescriptorSetBuilderArray where L: PipelineLayoutAbst writes: self.builder.writes, resources: (self.builder.resources, PersistentDescriptorSetBufView { view: view, - write: !readonly, - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: + descriptor_num: self.builder.binding_id as u32, }) }, desc: self.desc, @@ -581,14 +592,7 @@ impl PersistentDescriptorSetBuilderArray where L: PipelineLayoutAbst writes: self.builder.writes, resources: (self.builder.resources, PersistentDescriptorSetImg { image: image_view, - write: !readonly, - first_mipmap: 0, // FIXME: - num_mipmaps: 1, // FIXME: - first_layer: 0, // FIXME: - num_layers: 1, // FIXME: - layout: ImageLayout::General, // FIXME: - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: + descriptor_num: self.builder.binding_id as u32, }) }, desc: self.desc, @@ -646,14 +650,7 @@ impl PersistentDescriptorSetBuilderArray where L: PipelineLayoutAbst writes: self.builder.writes, resources: ((self.builder.resources, PersistentDescriptorSetImg { image: image_view, - write: !readonly, - first_mipmap: 0, // FIXME: - num_mipmaps: 1, // FIXME: - first_layer: 0, // FIXME: - num_layers: 1, // FIXME: - layout: ImageLayout::General, // FIXME: - stage: PipelineStages::none(), // FIXME: - access: AccessFlagBits::none(), // FIXME: + descriptor_num: self.builder.binding_id as u32, }), PersistentDescriptorSetSampler { sampler: sampler, }), @@ -772,12 +769,70 @@ fn image_match_desc(image_view: &I, desc: &DescriptorImageDesc) Ok(()) } +pub unsafe trait PersistentDescriptorSetResources { + fn num_buffers(&self) -> usize; + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)>; + fn num_images(&self) -> usize; + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)>; +} + +unsafe impl PersistentDescriptorSetResources for () { + #[inline] + fn num_buffers(&self) -> usize { + 0 + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + None + } + + #[inline] + fn num_images(&self) -> usize { + 0 + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + None + } +} + /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetBuf { buffer: B, - write: bool, - stage: PipelineStages, - access: AccessFlagBits, + descriptor_num: u32, +} + +unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetBuf) + where R: PersistentDescriptorSetResources, + B: BufferAccess, +{ + #[inline] + fn num_buffers(&self) -> usize { + self.0.num_buffers() + 1 + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + if let Some(buf) = self.0.buffer(index) { + Some(buf) + } else if index == self.0.num_buffers() { + Some((&self.1.buffer, self.1.descriptor_num)) + } else { + None + } + } + + #[inline] + fn num_images(&self) -> usize { + self.0.num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + self.0.image(index) + } } /// Internal object related to the `PersistentDescriptorSet` system. @@ -785,22 +840,75 @@ pub struct PersistentDescriptorSetBufView where V: BufferViewRef { view: V, - write: bool, - stage: PipelineStages, - access: AccessFlagBits, + descriptor_num: u32, +} + +unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetBufView) + where R: PersistentDescriptorSetResources, + V: BufferViewRef, +{ + #[inline] + fn num_buffers(&self) -> usize { + self.0.num_buffers() + 1 + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + if let Some(buf) = self.0.buffer(index) { + Some(buf) + } else if index == self.0.num_buffers() { + Some((self.1.view.view().buffer(), self.1.descriptor_num)) + } else { + None + } + } + + #[inline] + fn num_images(&self) -> usize { + self.0.num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + self.0.image(index) + } } /// Internal object related to the `PersistentDescriptorSet` system. pub struct PersistentDescriptorSetImg { image: I, - write: bool, - first_mipmap: u32, - num_mipmaps: u32, - first_layer: u32, - num_layers: u32, - layout: ImageLayout, - stage: PipelineStages, - access: AccessFlagBits, + descriptor_num: u32, +} + +unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetImg) + where R: PersistentDescriptorSetResources, + I: ImageViewAccess, +{ + #[inline] + fn num_buffers(&self) -> usize { + self.0.num_buffers() + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + self.0.buffer(index) + } + + #[inline] + fn num_images(&self) -> usize { + self.0.num_images() + 1 + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + if let Some(img) = self.0.image(index) { + Some(img) + } else if index == self.0.num_images() { + Some((&self.1.image, self.1.descriptor_num)) + } else { + None + } + } } /// Internal object related to the `PersistentDescriptorSet` system. @@ -808,6 +916,30 @@ pub struct PersistentDescriptorSetSampler { sampler: Arc, } +unsafe impl PersistentDescriptorSetResources for (R, PersistentDescriptorSetSampler) + where R: PersistentDescriptorSetResources +{ + #[inline] + fn num_buffers(&self) -> usize { + self.0.num_buffers() + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + self.0.buffer(index) + } + + #[inline] + fn num_images(&self) -> usize { + self.0.num_images() + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + self.0.image(index) + } +} + /// Error related to the persistent descriptor set. #[derive(Debug, Clone)] pub enum PersistentDescriptorSetError { diff --git a/vulkano/src/descriptor/descriptor_set/simple.rs b/vulkano/src/descriptor/descriptor_set/simple.rs index 181a2c5f..0f3d7a3f 100644 --- a/vulkano/src/descriptor/descriptor_set/simple.rs +++ b/vulkano/src/descriptor/descriptor_set/simple.rs @@ -28,7 +28,6 @@ use descriptor::descriptor_set::UnsafeDescriptorSetLayout; use descriptor::pipeline_layout::PipelineLayoutAbstract; use device::Device; use device::DeviceOwned; -use image::ImageAccess; use image::ImageLayout; use image::ImageViewAccess; use sampler::Sampler; @@ -78,13 +77,35 @@ unsafe impl DescriptorSet for SimpleDescriptorSet } #[inline] - fn buffers_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() + fn num_buffers(&self) -> usize { + // Note that since the simple descriptor set is deprecated, and since buffers and images + // within descriptor sets weren't supported before its deprecation, we just return a dummy + // value. + 0 + } + + #[inline] + fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> { + // Note that since the simple descriptor set is deprecated, and since buffers and images + // within descriptor sets weren't supported before its deprecation, we just return a dummy + // value. + None } #[inline] - fn images_list<'a>(&'a self) -> Box + 'a> { - unimplemented!() + fn num_images(&self) -> usize { + // Note that since the simple descriptor set is deprecated, and since buffers and images + // within descriptor sets weren't supported before its deprecation, we just return a dummy + // value. + 0 + } + + #[inline] + fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> { + // Note that since the simple descriptor set is deprecated, and since buffers and images + // within descriptor sets weren't supported before its deprecation, we just return a dummy + // value. + None } }