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 ) {
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 ) {
out.bind_pipeline_graphics(&self.pipeline);
}
@@ -803,6 +859,10 @@ impl SyncCommandBufferBuilder {
impl Command for Cmd ) {
out.bind_pipeline_compute(&self.pipeline);
}
@@ -872,6 +932,10 @@ impl SyncCommandBufferBuilder {
D: ImageAccess + Send + Sync + 'static,
R: Iterator ) {
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 ) {
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 ) {
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 ) {
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 ) {
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 ) {
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 ) {
out.set_scissor(self.first_scissor, self.scissors.take().unwrap());
}
@@ -1944,6 +2154,10 @@ impl SyncCommandBufferBuilder {
impl Command for Cmd
where I: Iterator ) {
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 ) {
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());
}