diff --git a/vulkano/src/command_buffer/synced.rs b/vulkano/src/command_buffer/synced.rs index 4b21ff59..c8d6bd7f 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; @@ -109,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" }, } @@ -147,6 +155,9 @@ struct Commands

{ // 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

); @@ -162,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 @@ -394,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. @@ -422,7 +443,21 @@ impl

SyncCommandBufferBuilder

{ latest_command_id }; if collision_command_id >= end { - return Err(SyncCommandBufferBuilderError::Conflict); + 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); @@ -640,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, @@ -661,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()) @@ -714,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); } @@ -735,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 @@ -770,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); } @@ -803,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); } @@ -872,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, @@ -910,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 { @@ -970,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()); @@ -994,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 { @@ -1040,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(), @@ -1073,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 { @@ -1133,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(), @@ -1168,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 { @@ -1233,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, @@ -1268,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 { @@ -1317,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); } @@ -1346,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); } @@ -1367,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 @@ -1402,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, @@ -1436,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, @@ -1473,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); } @@ -1494,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 { @@ -1532,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); } @@ -1553,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 { @@ -1582,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(); } @@ -1621,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); } @@ -1642,6 +1812,10 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + "destination".into() + } } self.commands @@ -1673,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); } @@ -1707,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, @@ -1751,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); } @@ -1778,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); } @@ -1804,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); } @@ -1829,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); } @@ -1854,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); } @@ -1881,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); } @@ -1914,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()); } @@ -1944,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()); } @@ -1974,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); } @@ -1995,6 +2213,10 @@ impl

SyncCommandBufferBuilder

{ assert_eq!(num, 0); &self.buffer } + + fn buffer_name(&self, num: usize) -> Cow<'static, str> { + "destination".into() + } } self.commands @@ -2059,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, @@ -2102,6 +2328,16 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { 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) { @@ -2111,6 +2347,16 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> { } 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 = { @@ -2215,6 +2461,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()); } @@ -2232,6 +2482,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(); @@ -2294,6 +2548,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()); }