diff --git a/vulkano/src/command_buffer/auto.rs b/vulkano/src/command_buffer/auto.rs index b6b5fee8b9..30d4ba93e2 100644 --- a/vulkano/src/command_buffer/auto.rs +++ b/vulkano/src/command_buffer/auto.rs @@ -833,6 +833,7 @@ err_gen!(CopyQueryPoolResultsError { err_gen!(FillBufferError { AutoCommandBufferBuilderContextError, CheckFillBufferError, + SyncCommandBufferBuilderError, }); err_gen!(DebugMarkerError { @@ -931,6 +932,7 @@ err_gen!(ResetQueryPoolError { err_gen!(UpdateBufferError { AutoCommandBufferBuilderContextError, CheckUpdateBufferError, + SyncCommandBufferBuilderError, }); /// Errors that can happen when calling [`clear_attachments`](AutoCommandBufferBuilder::clear_attachments) diff --git a/vulkano/src/command_buffer/commands/bind_push.rs b/vulkano/src/command_buffer/commands/bind_push.rs index 85921fde8e..36d4c7130d 100644 --- a/vulkano/src/command_buffer/commands/bind_push.rs +++ b/vulkano/src/command_buffer/commands/bind_push.rs @@ -475,7 +475,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBindIndexBuffer" + "bind_index_buffer" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -484,7 +484,7 @@ impl SyncCommandBufferBuilder { } self.current_state.index_buffer = Some((buffer.clone(), index_ty)); - self.append_command(Cmd { buffer, index_ty }, []).unwrap(); + self.commands.push(Box::new(Cmd { buffer, index_ty })); } /// Calls `vkCmdBindPipeline` on the builder with a compute pipeline. @@ -496,7 +496,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBindPipeline" + "bind_pipeline_compute" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -505,7 +505,7 @@ impl SyncCommandBufferBuilder { } self.current_state.pipeline_compute = Some(pipeline.clone()); - self.append_command(Cmd { pipeline }, []).unwrap(); + self.commands.push(Box::new(Cmd { pipeline })); } /// Calls `vkCmdBindPipeline` on the builder with a graphics pipeline. @@ -517,7 +517,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBindPipeline" + "bind_pipeline_graphics" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -534,7 +534,7 @@ impl SyncCommandBufferBuilder { .map(|(s, _)| s), ); self.current_state.pipeline_graphics = Some(pipeline.clone()); - self.append_command(Cmd { pipeline }, []).unwrap(); + self.commands.push(Box::new(Cmd { pipeline })); } /// Starts the process of binding vertex buffers. Returns an intermediate struct which can be @@ -570,7 +570,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdPushConstants" + "push_constants" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -594,17 +594,13 @@ impl SyncCommandBufferBuilder { ); out.set_len(size as usize); - self.append_command( - Cmd { - pipeline_layout: pipeline_layout.clone(), - stages, - offset, - size, - data: out.into(), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + pipeline_layout: pipeline_layout.clone(), + stages, + offset, + size, + data: out.into(), + })); // TODO: Push constant invalidations. // The Vulkan spec currently is unclear about this, so Vulkano currently just marks @@ -634,7 +630,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdPushDescriptorSetKHR" + "push_descriptor_set" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -672,16 +668,12 @@ impl SyncCommandBufferBuilder { set_resources.update(write); } - self.append_command( - Cmd { - pipeline_bind_point, - pipeline_layout, - set_num, - descriptor_writes, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + pipeline_bind_point, + pipeline_layout, + set_num, + descriptor_writes, + })); } } @@ -720,7 +712,7 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBindDescriptorSets" + "bind_descriptor_sets" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -754,17 +746,12 @@ impl<'b> SyncCommandBufferBuilderBindDescriptorSets<'b> { .insert(first_set + set_num as u32, SetOrPush::Set(set.clone())); } - self.builder - .append_command( - Cmd { - descriptor_sets: self.descriptor_sets, - pipeline_bind_point, - pipeline_layout, - first_set, - }, - [], - ) - .unwrap(); + self.builder.commands.push(Box::new(Cmd { + descriptor_sets: self.descriptor_sets, + pipeline_bind_point, + pipeline_layout, + first_set, + })); } } @@ -793,7 +780,7 @@ impl<'a> SyncCommandBufferBuilderBindVertexBuffer<'a> { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBindVertexBuffers" + "bind_vertex_buffers" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -808,16 +795,11 @@ impl<'a> SyncCommandBufferBuilderBindVertexBuffer<'a> { .insert(first_set + i as u32, buffer.clone()); } - self.builder - .append_command( - Cmd { - first_set, - inner: Mutex::new(Some(self.inner)), - buffers: self.buffers, - }, - [], - ) - .unwrap(); + self.builder.commands.push(Box::new(Cmd { + first_set, + inner: Mutex::new(Some(self.inner)), + buffers: self.buffers, + })); } } diff --git a/vulkano/src/command_buffer/commands/debug.rs b/vulkano/src/command_buffer/commands/debug.rs index f5f27989bf..45ffa0317c 100644 --- a/vulkano/src/command_buffer/commands/debug.rs +++ b/vulkano/src/command_buffer/commands/debug.rs @@ -126,7 +126,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBeginDebugUtilsLabelEXT" + "debug_marker_begin" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -134,7 +134,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { name, color }, []).unwrap(); + self.commands.push(Box::new(Cmd { name, color })); } /// Calls `vkCmdEndDebugUtilsLabelEXT` on the builder. @@ -150,7 +150,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdEndDebugUtilsLabelEXT" + "debug_marker_end" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -158,7 +158,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd {}, []).unwrap(); + self.commands.push(Box::new(Cmd {})); } /// Calls `vkCmdInsertDebugUtilsLabelEXT` on the builder. @@ -175,7 +175,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdInsertDebugUtilsLabelEXT" + "debug_marker_insert" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -183,7 +183,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { name, color }, []).unwrap(); + self.commands.push(Box::new(Cmd { name, color })); } } diff --git a/vulkano/src/command_buffer/commands/dynamic_state.rs b/vulkano/src/command_buffer/commands/dynamic_state.rs index 70b0903965..5cfb394341 100644 --- a/vulkano/src/command_buffer/commands/dynamic_state.rs +++ b/vulkano/src/command_buffer/commands/dynamic_state.rs @@ -1095,7 +1095,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetBlendConstants" + "set_blend_constants" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1103,7 +1103,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { constants }, []).unwrap(); + self.commands.push(Box::new(Cmd { constants })); self.current_state.blend_constants = Some(constants); } @@ -1124,7 +1124,7 @@ impl SyncCommandBufferBuilder { I: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdSetColorWriteEnableEXT" + "set_color_write_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1134,13 +1134,9 @@ impl SyncCommandBufferBuilder { let enables: SmallVec<[bool; 4]> = enables.into_iter().collect(); self.current_state.color_write_enable = Some(enables.clone()); - self.append_command( - Cmd { - enables: Mutex::new(Some(enables)), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + enables: Mutex::new(Some(enables)), + })); } /// Calls `vkCmdSetCullModeEXT` on the builder. @@ -1152,7 +1148,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetCullModeEXT" + "set_cull_mode" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1160,7 +1156,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { cull_mode }, []).unwrap(); + self.commands.push(Box::new(Cmd { cull_mode })); self.current_state.cull_mode = Some(cull_mode); } @@ -1175,7 +1171,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthBias" + "set_depth_bias" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1183,15 +1179,11 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - constant_factor, - clamp, - slope_factor, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + constant_factor, + clamp, + slope_factor, + })); self.current_state.depth_bias = Some(DepthBias { constant_factor, clamp, @@ -1208,7 +1200,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthBiasEnableEXT" + "set_depth_bias_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1216,7 +1208,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.depth_bias_enable = Some(enable); } @@ -1230,7 +1222,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthBounds" + "set_depth_bounds" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1238,7 +1230,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { min, max }, []).unwrap(); + self.commands.push(Box::new(Cmd { min, max })); self.current_state.depth_bounds = Some((min, max)); } @@ -1251,7 +1243,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthBoundsTestEnableEXT" + "set_depth_bounds_test_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1259,7 +1251,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.depth_bounds_test_enable = Some(enable); } @@ -1272,7 +1264,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthCompareOpEXT" + "set_depth_compare_op" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1280,7 +1272,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { compare_op }, []).unwrap(); + self.commands.push(Box::new(Cmd { compare_op })); self.current_state.depth_compare_op = Some(compare_op); } @@ -1293,7 +1285,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthTestEnableEXT" + "set_depth_test_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1301,7 +1293,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.depth_test_enable = Some(enable); } @@ -1314,7 +1306,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetDepthWriteEnableEXT" + "set_depth_write_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1322,7 +1314,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.depth_write_enable = Some(enable); } @@ -1341,7 +1333,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetRectangle" + "set_discard_rectangle" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1358,14 +1350,10 @@ impl SyncCommandBufferBuilder { .insert(num, rectangle.clone()); } - self.append_command( - Cmd { - first_rectangle, - rectangles: Mutex::new(rectangles), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + first_rectangle, + rectangles: Mutex::new(rectangles), + })); } /// Calls `vkCmdSetFrontFaceEXT` on the builder. @@ -1377,7 +1365,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetFrontFaceEXT" + "set_front_face" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1385,7 +1373,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { face }, []).unwrap(); + self.commands.push(Box::new(Cmd { face })); self.current_state.front_face = Some(face); } @@ -1399,7 +1387,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetLineStippleEXT" + "set_line_stipple" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1407,7 +1395,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { factor, pattern }, []).unwrap(); + self.commands.push(Box::new(Cmd { factor, pattern })); self.current_state.line_stipple = Some(LineStipple { factor, pattern }); } @@ -1420,7 +1408,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetLineWidth" + "set_line_width" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1428,7 +1416,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { line_width }, []).unwrap(); + self.commands.push(Box::new(Cmd { line_width })); self.current_state.line_width = Some(line_width); } @@ -1441,7 +1429,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetLogicOpEXT" + "set_logic_op" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1449,7 +1437,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { logic_op }, []).unwrap(); + self.commands.push(Box::new(Cmd { logic_op })); self.current_state.logic_op = Some(logic_op); } @@ -1462,7 +1450,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetPatchControlPointsEXT" + "set_patch_control_points" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1470,7 +1458,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { num }, []).unwrap(); + self.commands.push(Box::new(Cmd { num })); self.current_state.patch_control_points = Some(num); } @@ -1483,7 +1471,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetPrimitiveRestartEnableEXT" + "set_primitive_restart_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1491,7 +1479,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.primitive_restart_enable = Some(enable); } @@ -1504,7 +1492,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetPrimitiveTopologyEXT" + "set_primitive_topology" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1512,7 +1500,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { topology }, []).unwrap(); + self.commands.push(Box::new(Cmd { topology })); self.current_state.primitive_topology = Some(topology); } @@ -1525,7 +1513,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetRasterizerDiscardEnableEXT" + "set_rasterizer_discard_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1533,7 +1521,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.rasterizer_discard_enable = Some(enable); } @@ -1547,7 +1535,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetStencilCompareMask" + "set_stencil_compare_mask" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1555,14 +1543,10 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - faces, - compare_mask, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + faces, + compare_mask, + })); let faces = ash::vk::StencilFaceFlags::from(faces); @@ -1595,7 +1579,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetStencilOpEXT" + "set_stencil_op" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1609,17 +1593,13 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - faces, - fail_op, - pass_op, - depth_fail_op, - compare_op, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + faces, + fail_op, + pass_op, + depth_fail_op, + compare_op, + })); let faces = ash::vk::StencilFaceFlags::from(faces); @@ -1652,7 +1632,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetStencilReference" + "set_stencil_reference" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1660,7 +1640,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { faces, reference }, []).unwrap(); + self.commands.push(Box::new(Cmd { faces, reference })); let faces = ash::vk::StencilFaceFlags::from(faces); @@ -1682,7 +1662,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetStencilTestEnableEXT" + "set_stencil_test_enable" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1690,7 +1670,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { enable }, []).unwrap(); + self.commands.push(Box::new(Cmd { enable })); self.current_state.stencil_test_enable = Some(enable); } @@ -1704,7 +1684,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetStencilWriteMask" + "set_stencil_write_mask" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1712,7 +1692,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { faces, write_mask }, []).unwrap(); + self.commands.push(Box::new(Cmd { faces, write_mask })); let faces = ash::vk::StencilFaceFlags::from(faces); @@ -1740,7 +1720,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetScissor" + "set_scissor" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1755,14 +1735,10 @@ impl SyncCommandBufferBuilder { self.current_state.scissor.insert(num, scissor.clone()); } - self.append_command( - Cmd { - first_scissor, - scissors: Mutex::new(scissors), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + first_scissor, + scissors: Mutex::new(scissors), + })); } /// Calls `vkCmdSetScissorWithCountEXT` on the builder. @@ -1779,7 +1755,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetScissorWithCountEXT" + "set_scissor_with_count" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1789,13 +1765,9 @@ impl SyncCommandBufferBuilder { let scissors: SmallVec<[Scissor; 2]> = scissors.into_iter().collect(); self.current_state.scissor_with_count = Some(scissors.clone()); - self.append_command( - Cmd { - scissors: Mutex::new(scissors), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + scissors: Mutex::new(scissors), + })); } /// Calls `vkCmdSetViewport` on the builder. @@ -1813,7 +1785,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetViewport" + "set_viewport" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1828,14 +1800,10 @@ impl SyncCommandBufferBuilder { self.current_state.viewport.insert(num, viewport.clone()); } - self.append_command( - Cmd { - first_viewport, - viewports: Mutex::new(viewports), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + first_viewport, + viewports: Mutex::new(viewports), + })); } /// Calls `vkCmdSetViewportWithCountEXT` on the builder. @@ -1852,7 +1820,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetViewportWithCountEXT" + "set_viewport_with_count" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1862,13 +1830,9 @@ impl SyncCommandBufferBuilder { let viewports: SmallVec<[Viewport; 2]> = viewports.into_iter().collect(); self.current_state.viewport_with_count = Some(viewports.clone()); - self.append_command( - Cmd { - viewports: Mutex::new(viewports), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + viewports: Mutex::new(viewports), + })); } } diff --git a/vulkano/src/command_buffer/commands/image.rs b/vulkano/src/command_buffer/commands/image.rs index 8d7b0abd3a..32452f09f1 100644 --- a/vulkano/src/command_buffer/commands/image.rs +++ b/vulkano/src/command_buffer/commands/image.rs @@ -11,20 +11,22 @@ use crate::{ command_buffer::{ auto::ClearDepthStencilImageError, commands::transfer::{is_overlapping_ranges, is_overlapping_regions}, - synced::{Command, KeyTy, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, + synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, AutoCommandBufferBuilderContextError, BlitImageError, ClearColorImageError, }, device::{Device, DeviceOwned}, format::{ClearValue, NumericType}, - image::{ImageAccess, ImageAspects, ImageDimensions, ImageLayout, SampleCount}, + image::{ + ImageAccess, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceRange, SampleCount, + }, sampler::Filter, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, VulkanObject, }; use parking_lot::Mutex; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::{error, fmt, sync::Arc}; /// # Commands that operate on images. @@ -845,7 +847,7 @@ impl SyncCommandBufferBuilder { R: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdBlitImage" + "blit_image" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -860,8 +862,6 @@ impl SyncCommandBufferBuilder { } } - let mut resources: SmallVec<[_; 2]> = SmallVec::new(); - // if its the same image in source and destination, we need to lock it once let source_key = ( source.conflict_key(), @@ -873,12 +873,19 @@ impl SyncCommandBufferBuilder { destination.current_mip_levels_access(), destination.current_array_layers_access(), ); - if source_key == destination_key { - resources.push(( - KeyTy::Image(source.clone()), + + let resources: SmallVec<[_; 2]> = if source_key == destination_key { + smallvec![( "source_and_destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: source.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: source.format().aspects(), + mip_levels: source.current_mip_levels_access(), + array_layers: source.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -890,18 +897,23 @@ impl SyncCommandBufferBuilder { }, exclusive: true, }, - // TODO: should, we take the layout as parameter? if so, which? source or destination? - ImageLayout::General, - ImageLayout::General, - )), - )); + start_layout: ImageLayout::General, + end_layout: ImageLayout::General, + }, + )] } else { - resources.extend([ + smallvec![ ( - KeyTy::Image(source.clone()), "source".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: source.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: source.format().aspects(), + mip_levels: source.current_mip_levels_access(), + array_layers: source.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -912,15 +924,21 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - source_layout, - source_layout, - )), + start_layout: source_layout, + end_layout: source_layout, + }, ), ( - KeyTy::Image(destination.clone()), "destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: destination.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: destination.format().aspects(), + mip_levels: destination.current_mip_levels_access(), + array_layers: destination.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -931,24 +949,29 @@ impl SyncCommandBufferBuilder { }, exclusive: true, }, - destination_layout, - destination_layout, - )), + start_layout: destination_layout, + end_layout: destination_layout, + }, ), - ]); + ] + }; + + for resource in &resources { + self.check_resource_conflicts(resource)?; } - self.append_command( - Cmd { - source, - source_layout, - destination, - destination_layout, - regions: Mutex::new(Some(regions)), - filter, - }, - resources, - )?; + self.commands.push(Box::new(Cmd { + source, + source_layout, + destination, + destination_layout, + regions: Mutex::new(Some(regions)), + filter, + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -982,7 +1005,7 @@ impl SyncCommandBufferBuilder { + 'static, { fn name(&self) -> &'static str { - "vkCmdClearColorImage" + "clear_color_image" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -995,33 +1018,46 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { + let resources = [( + "target".into(), + Resource::Image { image: image.clone(), - layout, - color, - regions: Mutex::new(Some(regions)), - }, - [( - KeyTy::Image(image), - "target".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + subresource_range: ImageSubresourceRange { + // TODO: + aspects: image.format().aspects(), + mip_levels: image.current_mip_levels_access(), + array_layers: image.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - layout, - layout, - )), - )], - )?; + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + start_layout: layout, + end_layout: layout, + }, + )]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + image, + layout, + color, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -1058,7 +1094,7 @@ impl SyncCommandBufferBuilder { + 'static, { fn name(&self) -> &'static str { - "vkCmdClearColorImage" + "clear_depth_stencil_image" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1071,33 +1107,46 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { + let resources = [( + "target".into(), + Resource::Image { image: image.clone(), - layout, - clear_value, - regions: Mutex::new(Some(regions)), - }, - [( - KeyTy::Image(image), - "target".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + subresource_range: ImageSubresourceRange { + // TODO: + aspects: image.format().aspects(), + mip_levels: image.current_mip_levels_access(), + array_layers: image.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() }, - layout, - layout, - )), - )], - )?; + exclusive: true, + }, + start_layout: layout, + end_layout: layout, + }, + )]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + image, + layout, + clear_value, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } diff --git a/vulkano/src/command_buffer/commands/pipeline.rs b/vulkano/src/command_buffer/commands/pipeline.rs index 88a294dd43..0a043f28c4 100644 --- a/vulkano/src/command_buffer/commands/pipeline.rs +++ b/vulkano/src/command_buffer/commands/pipeline.rs @@ -11,7 +11,7 @@ use crate::{ buffer::{view::BufferViewAbstract, BufferAccess, TypedBufferAccess}, command_buffer::{ synced::{ - Command, CommandBufferState, KeyTy, SyncCommandBufferBuilder, + Command, CommandBufferState, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError, }, sys::UnsafeCommandBufferBuilder, @@ -23,7 +23,9 @@ use crate::{ descriptor_set::{layout::DescriptorType, DescriptorBindingResources}, device::{Device, DeviceOwned}, format::Format, - image::{view::ImageViewType, ImageAccess, ImageLayout, ImageViewAbstract, SampleCount}, + image::{ + view::ImageViewType, ImageAccess, ImageSubresourceRange, ImageViewAbstract, SampleCount, + }, pipeline::{ graphics::{ input_assembly::PrimitiveTopology, @@ -61,7 +63,7 @@ impl AutoCommandBufferBuilder { check_dispatch(self.device(), group_counts)?; unsafe { - self.inner.dispatch(group_counts); + self.inner.dispatch(group_counts)?; } Ok(self) @@ -131,7 +133,7 @@ impl AutoCommandBufferBuilder { unsafe { self.inner - .draw(vertex_count, instance_count, first_vertex, first_instance); + .draw(vertex_count, instance_count, first_vertex, first_instance)?; } Ok(self) @@ -244,7 +246,7 @@ impl AutoCommandBufferBuilder { first_index, vertex_offset, first_instance, - ); + )?; } Ok(self) @@ -1644,14 +1646,17 @@ impl fmt::Display for CheckDispatchError { impl SyncCommandBufferBuilder { /// Calls `vkCmdDispatch` on the builder. #[inline] - pub unsafe fn dispatch(&mut self, group_counts: [u32; 3]) { + pub unsafe fn dispatch( + &mut self, + group_counts: [u32; 3], + ) -> Result<(), SyncCommandBufferBuilderError> { struct Cmd { group_counts: [u32; 3], } impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDispatch" + "dispatch" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1668,8 +1673,17 @@ impl SyncCommandBufferBuilder { pipeline.descriptor_requirements(), ); - self.append_command(Cmd { group_counts }, resources) - .unwrap(); + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { group_counts })); + + for resource in resources { + self.add_resource(resource); + } + + Ok(()) } /// Calls `vkCmdDispatchIndirect` on the builder. @@ -1684,7 +1698,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDispatchIndirect" + "dispatch_indirect" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1700,9 +1714,17 @@ impl SyncCommandBufferBuilder { PipelineBindPoint::Compute, pipeline.descriptor_requirements(), ); - self.add_indirect_buffer_resources(&mut resources, indirect_buffer.clone()); + self.add_indirect_buffer_resources(&mut resources, &indirect_buffer); + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } - self.append_command(Cmd { indirect_buffer }, resources)?; + self.commands.push(Box::new(Cmd { indirect_buffer })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -1715,7 +1737,7 @@ impl SyncCommandBufferBuilder { instance_count: u32, first_vertex: u32, first_instance: u32, - ) { + ) -> Result<(), SyncCommandBufferBuilderError> { struct Cmd { vertex_count: u32, instance_count: u32, @@ -1725,7 +1747,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDraw" + "draw" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1748,16 +1770,22 @@ impl SyncCommandBufferBuilder { ); self.add_vertex_buffer_resources(&mut resources, pipeline.vertex_input_state()); - self.append_command( - Cmd { - vertex_count, - instance_count, - first_vertex, - first_instance, - }, - resources, - ) - .unwrap(); + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + vertex_count, + instance_count, + first_vertex, + first_instance, + })); + + for resource in resources { + self.add_resource(resource); + } + + Ok(()) } /// Calls `vkCmdDrawIndexed` on the builder. @@ -1769,7 +1797,7 @@ impl SyncCommandBufferBuilder { first_index: u32, vertex_offset: i32, first_instance: u32, - ) { + ) -> Result<(), SyncCommandBufferBuilderError> { struct Cmd { index_count: u32, instance_count: u32, @@ -1780,7 +1808,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDrawIndexed" + "draw_indexed" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1805,17 +1833,23 @@ impl SyncCommandBufferBuilder { self.add_vertex_buffer_resources(&mut resources, pipeline.vertex_input_state()); self.add_index_buffer_resources(&mut resources); - self.append_command( - Cmd { - index_count, - instance_count, - first_index, - vertex_offset, - first_instance, - }, - resources, - ) - .unwrap(); + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + index_count, + instance_count, + first_index, + vertex_offset, + first_instance, + })); + + for resource in resources { + self.add_resource(resource); + } + + Ok(()) } /// Calls `vkCmdDrawIndirect` on the builder. @@ -1834,7 +1868,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDrawIndirect" + "draw_indirect" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1851,16 +1885,21 @@ impl SyncCommandBufferBuilder { pipeline.descriptor_requirements(), ); self.add_vertex_buffer_resources(&mut resources, pipeline.vertex_input_state()); - self.add_indirect_buffer_resources(&mut resources, indirect_buffer.clone()); + self.add_indirect_buffer_resources(&mut resources, &indirect_buffer); - self.append_command( - Cmd { - indirect_buffer, - draw_count, - stride, - }, - resources, - )?; + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + indirect_buffer, + draw_count, + stride, + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -1881,7 +1920,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdDrawIndexedIndirect" + "draw_indexed_indirect" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1903,27 +1942,28 @@ impl SyncCommandBufferBuilder { ); self.add_vertex_buffer_resources(&mut resources, pipeline.vertex_input_state()); self.add_index_buffer_resources(&mut resources); - self.add_indirect_buffer_resources(&mut resources, indirect_buffer.clone()); + self.add_indirect_buffer_resources(&mut resources, &indirect_buffer); - self.append_command( - Cmd { - indirect_buffer, - draw_count, - stride, - }, - resources, - )?; + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + indirect_buffer, + draw_count, + stride, + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } fn add_descriptor_set_resources<'a>( &self, - resources: &mut Vec<( - KeyTy, - Cow<'static, str>, - Option<(PipelineMemoryAccess, ImageLayout, ImageLayout)>, - )>, + resources: &mut Vec<(Cow<'static, str>, Resource)>, pipeline_bind_point: PipelineBindPoint, descriptor_requirements: impl IntoIterator, ) { @@ -1938,6 +1978,15 @@ impl SyncCommandBufferBuilder { [&binding] .descriptor_type; + // 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. + if descriptor_type == DescriptorType::InputAttachment { + continue; + } + // TODO: Maybe include this on DescriptorRequirements? let access = PipelineMemoryAccess { stages: reqs.stages.into(), @@ -1977,31 +2026,37 @@ impl SyncCommandBufferBuilder { }); let buffer_resource = - move |(access, buffer): (PipelineMemoryAccess, Arc)| { + move |(memory, buffer): (PipelineMemoryAccess, Arc)| { + let range = 0..buffer.size(); // TODO: ( - KeyTy::Buffer(buffer), format!("Buffer bound to set {} descriptor {}", set, binding).into(), - Some((access, ImageLayout::Undefined, ImageLayout::Undefined)), + Resource::Buffer { + buffer, + range, + memory, + }, ) }; let image_resource = - move |(access, image): (PipelineMemoryAccess, Arc)| { + move |(memory, image): (PipelineMemoryAccess, Arc)| { + let subresource_range = ImageSubresourceRange { + // TODO: + aspects: image.format().aspects(), + mip_levels: image.current_mip_levels_access(), + array_layers: image.current_array_layers_access(), + }; let layout = image .descriptor_layouts() .expect("descriptor_layouts must return Some when used in an image view") .layout_for(descriptor_type); ( - KeyTy::Image(image), format!("Image bound to set {} descriptor {}", set, binding).into(), - if descriptor_type == DescriptorType::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. - None - } else { - Some((access, layout, layout)) + Resource::Image { + image, + subresource_range, + memory, + start_layout: layout, + end_layout: layout, }, ) }; @@ -2065,20 +2120,17 @@ impl SyncCommandBufferBuilder { fn add_vertex_buffer_resources( &self, - resources: &mut Vec<( - KeyTy, - Cow<'static, str>, - Option<(PipelineMemoryAccess, ImageLayout, ImageLayout)>, - )>, + resources: &mut Vec<(Cow<'static, str>, Resource)>, vertex_input: &VertexInputState, ) { resources.extend(vertex_input.bindings.iter().map(|(&binding_num, _)| { - let buffer = self.current_state.vertex_buffers[&binding_num].clone(); + let vertex_buffer = &self.current_state.vertex_buffers[&binding_num]; ( - KeyTy::Buffer(buffer), format!("Vertex buffer binding {}", binding_num).into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: vertex_buffer.clone(), + range: 0..vertex_buffer.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { vertex_input: true, ..PipelineStages::none() @@ -2089,27 +2141,19 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + }, ) })); } - fn add_index_buffer_resources( - &self, - resources: &mut Vec<( - KeyTy, - Cow<'static, str>, - Option<(PipelineMemoryAccess, ImageLayout, ImageLayout)>, - )>, - ) { - let index_buffer = self.current_state.index_buffer.as_ref().unwrap().0.clone(); + fn add_index_buffer_resources(&self, resources: &mut Vec<(Cow<'static, str>, Resource)>) { + let index_buffer = &self.current_state.index_buffer.as_ref().unwrap().0; resources.push(( - KeyTy::Buffer(index_buffer), "index buffer".into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: index_buffer.clone(), + range: 0..index_buffer.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { vertex_input: true, ..PipelineStages::none() @@ -2120,26 +2164,21 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + }, )); } fn add_indirect_buffer_resources( &self, - resources: &mut Vec<( - KeyTy, - Cow<'static, str>, - Option<(PipelineMemoryAccess, ImageLayout, ImageLayout)>, - )>, - indirect_buffer: Arc, + resources: &mut Vec<(Cow<'static, str>, Resource)>, + indirect_buffer: &Arc, ) { resources.push(( - KeyTy::Buffer(indirect_buffer), "indirect buffer".into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: indirect_buffer.clone(), + range: 0..indirect_buffer.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { draw_indirect: true, ..PipelineStages::none() @@ -2150,9 +2189,7 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + }, )); } } diff --git a/vulkano/src/command_buffer/commands/query.rs b/vulkano/src/command_buffer/commands/query.rs index a9ff4b45e7..2939b122cb 100644 --- a/vulkano/src/command_buffer/commands/query.rs +++ b/vulkano/src/command_buffer/commands/query.rs @@ -11,13 +11,12 @@ use crate::{ buffer::TypedBufferAccess, command_buffer::{ auto::QueryState, - synced::{Command, KeyTy, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, + synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, AutoCommandBufferBuilderContextError, BeginQueryError, CopyQueryPoolResultsError, EndQueryError, ResetQueryPoolError, WriteTimestampError, }, device::{physical::QueueFamily, Device, DeviceOwned}, - image::ImageLayout, query::{ GetResultsError, QueriesRange, Query, QueryControlFlags, QueryPool, QueryResultElement, QueryResultFlags, QueryType, @@ -591,7 +590,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBeginQuery" + "begin_query" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -599,15 +598,11 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - query_pool, - query, - flags, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + query_pool, + query, + flags, + })); } /// Calls `vkCmdEndQuery` on the builder. @@ -620,7 +615,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdEndQuery" + "end_query" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -628,7 +623,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { query_pool, query }, []).unwrap(); + self.commands.push(Box::new(Cmd { query_pool, query })); } /// Calls `vkCmdWriteTimestamp` on the builder. @@ -647,7 +642,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdWriteTimestamp" + "write_timestamp" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -655,15 +650,11 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - query_pool, - query, - stage, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + query_pool, + query, + stage, + })); } /// Calls `vkCmdCopyQueryPoolResults` on the builder. @@ -696,7 +687,7 @@ impl SyncCommandBufferBuilder { T: QueryResultElement, { fn name(&self) -> &'static str { - "vkCmdCopyQueryPoolResults" + "copy_query_pool_results" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -709,34 +700,40 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - query_pool, - queries, - destination: destination.clone(), - stride, - flags, - }, - [( - KeyTy::Buffer(destination), - "destination".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + let resources = [( + "destination".into(), + Resource::Buffer { + buffer: destination.clone(), + range: 0..destination.size(), // TODO: + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - )], - )?; + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + }, + )]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + query_pool, + queries, + destination, + stride, + flags, + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -751,7 +748,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdResetQueryPool" + "reset_query_pool" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -759,14 +756,10 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - query_pool, - queries, - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + query_pool, + queries, + })); } } diff --git a/vulkano/src/command_buffer/commands/render_pass.rs b/vulkano/src/command_buffer/commands/render_pass.rs index c64bb75fde..9f061fbd8c 100644 --- a/vulkano/src/command_buffer/commands/render_pass.rs +++ b/vulkano/src/command_buffer/commands/render_pass.rs @@ -13,7 +13,7 @@ use crate::{ auto::{ClearAttachmentsError, RenderPassState}, pool::CommandPoolBuilderAlloc, synced::{ - Command, CommandBufferState, KeyTy, SyncCommandBufferBuilder, + Command, CommandBufferState, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError, }, sys::UnsafeCommandBufferBuilder, @@ -23,7 +23,7 @@ use crate::{ format::{ClearValue, NumericType}, image::{ attachment::{ClearAttachment, ClearRect}, - ImageAspects, + ImageAspects, ImageSubresourceRange, }, pipeline::GraphicsPipeline, render_pass::{Framebuffer, LoadOp}, @@ -375,7 +375,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdBeginRenderPass" + "begin_render_pass" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -402,11 +402,20 @@ impl SyncCommandBufferBuilder { .iter() .enumerate() .map(|(num, desc)| { + let image = render_pass_begin_info.framebuffer.attachments()[num].image(); + let subresource_range = ImageSubresourceRange { + // TODO: + aspects: image.format().aspects(), + mip_levels: image.current_mip_levels_access(), + array_layers: image.current_array_layers_access(), + }; + ( - KeyTy::Image(render_pass_begin_info.framebuffer.attachments()[num].image()), format!("attachment {}", num).into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image, + subresource_range, + memory: PipelineMemoryAccess { stages: PipelineStages { all_commands: true, ..PipelineStages::none() @@ -421,22 +430,28 @@ impl SyncCommandBufferBuilder { }, // TODO: suboptimal exclusive: true, // TODO: suboptimal ; note: remember to always pass true if desc.initial_layout != desc.final_layout }, - desc.initial_layout, - desc.final_layout, - )), + start_layout: desc.initial_layout, + end_layout: desc.final_layout, + }, ) }) .collect::>(); - self.append_command( - Cmd { - render_pass_begin_info: Mutex::new(render_pass_begin_info), - subpass_contents, - }, - resources, - )?; + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + render_pass_begin_info: Mutex::new(render_pass_begin_info), + subpass_contents, + })); + + for resource in resources { + self.add_resource(resource); + } self.latest_render_pass_enter = Some(self.commands.len() - 1); + Ok(()) } @@ -449,7 +464,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdNextSubpass" + "next_subpass" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -457,7 +472,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { subpass_contents }, []).unwrap(); + self.commands.push(Box::new(Cmd { subpass_contents })); } /// Calls `vkCmdEndRenderPass` on the builder. @@ -467,7 +482,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdEndRenderPass" + "end_render_pass" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -475,7 +490,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd, []).unwrap(); + self.commands.push(Box::new(Cmd)); debug_assert!(self.latest_render_pass_enter.is_some()); self.latest_render_pass_enter = None; } @@ -496,7 +511,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdClearAttachments" + "clear_attachments" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -509,14 +524,10 @@ impl SyncCommandBufferBuilder { let attachments: SmallVec<[_; 3]> = attachments.into_iter().collect(); let rects: SmallVec<[_; 4]> = rects.into_iter().collect(); - self.append_command( - Cmd { - attachments: Mutex::new(attachments), - rects: Mutex::new(rects), - }, - [], - ) - .unwrap(); + self.commands.push(Box::new(Cmd { + attachments: Mutex::new(attachments), + rects: Mutex::new(rects), + })); } } diff --git a/vulkano/src/command_buffer/commands/secondary.rs b/vulkano/src/command_buffer/commands/secondary.rs index 7bf524e3af..42ba5a061b 100644 --- a/vulkano/src/command_buffer/commands/secondary.rs +++ b/vulkano/src/command_buffer/commands/secondary.rs @@ -10,13 +10,13 @@ use crate::{ command_buffer::{ pool::CommandPoolBuilderAlloc, - synced::{Command, KeyTy, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, + synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, AutoCommandBufferBuilderContextError, CommandBufferExecError, CommandBufferInheritanceRenderPassInfo, CommandBufferUsage, ExecuteCommandsError, PrimaryAutoCommandBuffer, SecondaryCommandBuffer, SubpassContents, }, - image::ImageLayout, + image::ImageSubresourceRange, query::QueryType, SafeDeref, VulkanObject, }; @@ -232,7 +232,7 @@ impl<'a> SyncCommandBufferBuilderExecuteCommands<'a> { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdExecuteCommands" + "execute_commands" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -248,39 +248,54 @@ impl<'a> SyncCommandBufferBuilderExecuteCommands<'a> { let mut resources = Vec::new(); for (cbuf_num, cbuf) in self.inner.iter().enumerate() { for buf_num in 0..cbuf.num_buffers() { + let (buffer, memory) = cbuf.buffer(buf_num).unwrap(); resources.push(( - KeyTy::Buffer(cbuf.buffer(buf_num).unwrap().0.clone()), format!("Buffer bound to secondary command buffer {}", cbuf_num).into(), - Some(( - cbuf.buffer(buf_num).unwrap().1, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + Resource::Buffer { + buffer: buffer.clone(), + range: 0..buffer.size(), // TODO: + memory, + }, )); } for img_num in 0..cbuf.num_images() { - let (_, memory, start_layout, end_layout) = cbuf.image(img_num).unwrap(); + let (image, memory, start_layout, end_layout) = cbuf.image(img_num).unwrap(); resources.push(( - KeyTy::Image(cbuf.image(img_num).unwrap().0.clone()), format!("Image bound to secondary command buffer {}", cbuf_num).into(), - Some((memory, start_layout, end_layout)), + Resource::Image { + image: image.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: image.format().aspects(), + mip_levels: image.current_mip_levels_access(), + array_layers: image.current_array_layers_access(), + }, + memory, + start_layout, + end_layout, + }, )); } } resources }; - self.builder.append_command( - Cmd(self - .inner - .into_iter() - .map(|cbuf| { - cbuf.lock_record()?; - Ok(DropUnlock(cbuf)) - }) - .collect::, CommandBufferExecError>>()?), - resources, - )?; + for resource in &resources { + self.builder.check_resource_conflicts(resource)?; + } + + self.builder.commands.push(Box::new(Cmd(self + .inner + .into_iter() + .map(|cbuf| { + cbuf.lock_record()?; + Ok(DropUnlock(cbuf)) + }) + .collect::, CommandBufferExecError>>()?))); + + for resource in resources { + self.builder.add_resource(resource); + } Ok(()) } diff --git a/vulkano/src/command_buffer/commands/sync.rs b/vulkano/src/command_buffer/commands/sync.rs index 5ce628d0df..428976a90e 100644 --- a/vulkano/src/command_buffer/commands/sync.rs +++ b/vulkano/src/command_buffer/commands/sync.rs @@ -33,7 +33,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdSetEvent" + "set_event" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -41,7 +41,7 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { event, stages }, []).unwrap(); + self.commands.push(Box::new(Cmd { event, stages })); } /// Calls `vkCmdResetEvent` on the builder. @@ -54,7 +54,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdResetEvent" + "reset_event" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -62,13 +62,13 @@ impl SyncCommandBufferBuilder { } } - self.append_command(Cmd { event, stages }, []).unwrap(); + self.commands.push(Box::new(Cmd { event, stages })); } } impl UnsafeCommandBufferBuilder { #[inline] - pub unsafe fn pipeline_barrier(&mut self, dependency_info: DependencyInfo) { + pub unsafe fn pipeline_barrier(&mut self, dependency_info: &DependencyInfo) { if dependency_info.is_empty() { return; } @@ -86,7 +86,7 @@ impl UnsafeCommandBufferBuilder { let memory_barriers: SmallVec<[_; 2]> = memory_barriers .into_iter() .map(|barrier| { - let MemoryBarrier { + let &MemoryBarrier { source_stages, source_access, destination_stages, @@ -112,14 +112,14 @@ impl UnsafeCommandBufferBuilder { let buffer_memory_barriers: SmallVec<[_; 8]> = buffer_memory_barriers .into_iter() .map(|barrier| { - let BufferMemoryBarrier { + let &BufferMemoryBarrier { source_stages, source_access, destination_stages, destination_access, queue_family_transfer, - buffer, - range, + ref buffer, + ref range, _ne: _, } = barrier; @@ -154,7 +154,7 @@ impl UnsafeCommandBufferBuilder { let image_memory_barriers: SmallVec<[_; 8]> = image_memory_barriers .into_iter() .map(|barrier| { - let ImageMemoryBarrier { + let &ImageMemoryBarrier { source_stages, source_access, destination_stages, @@ -162,8 +162,8 @@ impl UnsafeCommandBufferBuilder { old_layout, new_layout, queue_family_transfer, - image, - subresource_range, + ref image, + ref subresource_range, _ne: _, } = barrier; @@ -203,7 +203,7 @@ impl UnsafeCommandBufferBuilder { transfer.destination_index }), image: image.internal_object(), - subresource_range: subresource_range.into(), + subresource_range: subresource_range.clone().into(), ..Default::default() } }) @@ -236,7 +236,7 @@ impl UnsafeCommandBufferBuilder { let memory_barriers: SmallVec<[_; 2]> = memory_barriers .into_iter() .map(|barrier| { - let MemoryBarrier { + let &MemoryBarrier { source_stages, source_access, destination_stages, @@ -263,14 +263,14 @@ impl UnsafeCommandBufferBuilder { let buffer_memory_barriers: SmallVec<[_; 8]> = buffer_memory_barriers .into_iter() .map(|barrier| { - let BufferMemoryBarrier { + let &BufferMemoryBarrier { source_stages, source_access, destination_stages, destination_access, queue_family_transfer, - buffer, - range, + ref buffer, + ref range, _ne: _, } = barrier; @@ -306,7 +306,7 @@ impl UnsafeCommandBufferBuilder { let image_memory_barriers: SmallVec<[_; 8]> = image_memory_barriers .into_iter() .map(|barrier| { - let ImageMemoryBarrier { + let &ImageMemoryBarrier { source_stages, source_access, destination_stages, @@ -314,8 +314,8 @@ impl UnsafeCommandBufferBuilder { old_layout, new_layout, queue_family_transfer, - image, - subresource_range, + ref image, + ref subresource_range, _ne: _, } = barrier; @@ -356,14 +356,23 @@ impl UnsafeCommandBufferBuilder { transfer.destination_index }), image: image.internal_object(), - subresource_range: subresource_range.into(), + subresource_range: subresource_range.clone().into(), ..Default::default() } }) .collect(); - debug_assert!(!src_stage_mask.is_empty()); - debug_assert!(!dst_stage_mask.is_empty()); + if src_stage_mask.is_empty() { + // "VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT is [...] equivalent to + // VK_PIPELINE_STAGE_2_NONE in the first scope." + src_stage_mask |= ash::vk::PipelineStageFlags::TOP_OF_PIPE; + } + + if dst_stage_mask.is_empty() { + // "VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT is [...] equivalent to + // VK_PIPELINE_STAGE_2_NONE in the second scope." + dst_stage_mask |= ash::vk::PipelineStageFlags::BOTTOM_OF_PIPE; + } let fns = self.device.fns(); fns.v1_0.cmd_pipeline_barrier( diff --git a/vulkano/src/command_buffer/commands/transfer.rs b/vulkano/src/command_buffer/commands/transfer.rs index 09b87d91a4..ea9e788fa3 100644 --- a/vulkano/src/command_buffer/commands/transfer.rs +++ b/vulkano/src/command_buffer/commands/transfer.rs @@ -10,19 +10,22 @@ use crate::{ buffer::{BufferAccess, BufferContents, BufferInner, TypedBufferAccess}, command_buffer::{ - synced::{Command, KeyTy, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, + synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, sys::UnsafeCommandBufferBuilder, AutoCommandBufferBuilder, CopyBufferError, CopyBufferImageError, CopyImageError, FillBufferError, UpdateBufferError, }, device::{Device, DeviceOwned}, format::{Format, NumericType}, - image::{ImageAccess, ImageAspect, ImageAspects, ImageDimensions, ImageLayout, SampleCount}, + image::{ + ImageAccess, ImageAspect, ImageAspects, ImageDimensions, ImageLayout, + ImageSubresourceRange, SampleCount, + }, sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, DeviceSize, SafeDeref, VulkanObject, }; use parking_lot::Mutex; -use smallvec::SmallVec; +use smallvec::{smallvec, SmallVec}; use std::{cmp, error, fmt, mem::size_of_val, sync::Arc}; /// # Commands to transfer data to a resource, either from the host or from another resource. @@ -185,7 +188,7 @@ impl AutoCommandBufferBuilder { unsafe { self.ensure_outside_render_pass()?; check_fill_buffer(self.device(), buffer.as_ref())?; - self.inner.fill_buffer(buffer, data); + self.inner.fill_buffer(buffer, data)?; Ok(self) } } @@ -211,7 +214,7 @@ impl AutoCommandBufferBuilder { let size_of_data = size_of_val(data.deref()) as DeviceSize; if buffer.size() >= size_of_data { - self.inner.update_buffer(buffer, data); + self.inner.update_buffer(buffer, data)?; } else { unimplemented!() // TODO: //self.inner.update_buffer(buffer.slice(0 .. size_of_data), data); @@ -1112,7 +1115,7 @@ impl SyncCommandBufferBuilder { R: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdCopyBuffer" + "copy_buffer" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1124,15 +1127,14 @@ impl SyncCommandBufferBuilder { } } - let mut resources: SmallVec<[_; 2]> = SmallVec::new(); - // if its the same image in source and destination, we need to lock it once - if source.conflict_key() == destination.conflict_key() { - resources.push(( - KeyTy::Buffer(source.clone()), + let resources: SmallVec<[_; 2]> = if source.conflict_key() == destination.conflict_key() { + smallvec![( "source_and_destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: source.clone(), + range: 0..source.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1144,17 +1146,16 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - )); + }, + )] } else { - resources.extend([ + smallvec![ ( - KeyTy::Buffer(source.clone()), "source".into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: source.clone(), + range: 0..source.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1165,15 +1166,14 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + }, ), ( - KeyTy::Buffer(destination.clone()), "destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Buffer { + buffer: destination.clone(), + range: 0..destination.size(), // TODO: + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1184,21 +1184,24 @@ impl SyncCommandBufferBuilder { }, exclusive: true, }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), + }, ), - ]); + ] + }; + + for resource in &resources { + self.check_resource_conflicts(resource)?; } - self.append_command( - Cmd { - source, - destination, - regions: Mutex::new(Some(regions)), - }, - resources, - )?; + self.commands.push(Box::new(Cmd { + source, + destination, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -1230,7 +1233,7 @@ impl SyncCommandBufferBuilder { R: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdCopyBufferToImage" + "copy_buffer_to_image" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1243,61 +1246,77 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - source: source.clone(), - destination: destination.clone(), - destination_layout, - regions: Mutex::new(Some(regions)), - }, - [ - ( - KeyTy::Buffer(source), - "source".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::none() - }, - exclusive: false, + let resources = [ + ( + "source".into(), + Resource::Buffer { + buffer: source.clone(), + range: 0..source.size(), // TODO: + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - ), - ( - KeyTy::Image(destination), - "destination".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + access: AccessFlags { + transfer_read: true, + ..AccessFlags::none() }, - destination_layout, - destination_layout, - )), - ), - ], - )?; + exclusive: false, + }, + }, + ), + ( + "destination".into(), + Resource::Image { + image: destination.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: destination.format().aspects(), + mip_levels: destination.current_mip_levels_access(), + array_layers: destination.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + start_layout: destination_layout, + end_layout: destination_layout, + }, + ), + ]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + source, + destination, + destination_layout, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } /// Calls `vkCmdFillBuffer` on the builder. #[inline] - pub unsafe fn fill_buffer(&mut self, buffer: Arc, data: u32) { + pub unsafe fn fill_buffer( + &mut self, + buffer: Arc, + data: u32, + ) -> Result<(), SyncCommandBufferBuilderError> { struct Cmd { buffer: Arc, data: u32, @@ -1305,7 +1324,7 @@ impl SyncCommandBufferBuilder { impl Command for Cmd { fn name(&self) -> &'static str { - "vkCmdFillBuffer" + "fill_buffer" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1313,37 +1332,45 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { + let resources = [( + "destination".into(), + Resource::Buffer { buffer: buffer.clone(), - data, - }, - [( - KeyTy::Buffer(buffer), - "destination".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + range: 0..buffer.size(), // TODO: + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - )], - ) - .unwrap(); + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + }, + )]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { buffer, data })); + + for resource in resources { + self.add_resource(resource); + } + + Ok(()) } /// Calls `vkCmdUpdateBuffer` on the builder. #[inline] - pub unsafe fn update_buffer(&mut self, buffer: Arc, data: Dd) + pub unsafe fn update_buffer( + &mut self, + buffer: Arc, + data: Dd, + ) -> Result<(), SyncCommandBufferBuilderError> where D: BufferContents + ?Sized, Dd: SafeDeref + Send + Sync + 'static, @@ -1359,7 +1386,7 @@ impl SyncCommandBufferBuilder { Dd: SafeDeref + Send + Sync + 'static, { fn name(&self) -> &'static str { - "vkCmdUpdateBuffer" + "update_buffer" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1367,32 +1394,36 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { + let resources = [( + "destination".into(), + Resource::Buffer { buffer: buffer.clone(), - data, - }, - [( - KeyTy::Buffer(buffer), - "destination".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + range: 0..buffer.size(), // TODO: + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - )], - ) - .unwrap(); + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + }, + )]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { buffer, data })); + + for resource in resources { + self.add_resource(resource); + } + + Ok(()) } /// Calls `vkCmdCopyImage` on the builder. @@ -1424,7 +1455,7 @@ impl SyncCommandBufferBuilder { R: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdCopyImage" + "copy_image" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1438,8 +1469,6 @@ impl SyncCommandBufferBuilder { } } - let mut resources: SmallVec<[_; 2]> = SmallVec::new(); - // if its the same image in source and destination, we need to lock it once let source_key = ( source.conflict_key(), @@ -1451,12 +1480,19 @@ impl SyncCommandBufferBuilder { destination.current_mip_levels_access(), destination.current_array_layers_access(), ); - if source_key == destination_key { - resources.push(( - KeyTy::Image(source.clone()), + + let resources: SmallVec<[_; 2]> = if source_key == destination_key { + smallvec![( "source_and_destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: source.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: source.format().aspects(), + mip_levels: source.current_mip_levels_access(), + array_layers: source.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1468,18 +1504,23 @@ impl SyncCommandBufferBuilder { }, exclusive: true, }, - // TODO: should, we take the layout as parameter? if so, which? source or destination? - ImageLayout::General, - ImageLayout::General, - )), - )); + start_layout: ImageLayout::General, + end_layout: ImageLayout::General, + }, + )] } else { - resources.extend([ + smallvec![ ( - KeyTy::Image(source.clone()), "source".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: source.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: source.format().aspects(), + mip_levels: source.current_mip_levels_access(), + array_layers: source.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1490,15 +1531,21 @@ impl SyncCommandBufferBuilder { }, exclusive: false, }, - source_layout, - source_layout, - )), + start_layout: source_layout, + end_layout: source_layout, + }, ), ( - KeyTy::Image(destination.clone()), "destination".into(), - Some(( - PipelineMemoryAccess { + Resource::Image { + image: destination.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: destination.format().aspects(), + mip_levels: destination.current_mip_levels_access(), + array_layers: destination.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { stages: PipelineStages { transfer: true, ..PipelineStages::none() @@ -1509,23 +1556,28 @@ impl SyncCommandBufferBuilder { }, exclusive: true, }, - destination_layout, - destination_layout, - )), + start_layout: destination_layout, + end_layout: destination_layout, + }, ), - ]); + ] + }; + + for resource in &resources { + self.check_resource_conflicts(resource)?; } - self.append_command( - Cmd { - source, - source_layout, - destination, - destination_layout, - regions: Mutex::new(Some(regions)), - }, - resources, - )?; + self.commands.push(Box::new(Cmd { + source, + source_layout, + destination, + destination_layout, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } @@ -1557,7 +1609,7 @@ impl SyncCommandBufferBuilder { R: IntoIterator + Send + Sync, { fn name(&self) -> &'static str { - "vkCmdCopyImageToBuffer" + "copy_image_to_buffer" } unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { @@ -1570,54 +1622,66 @@ impl SyncCommandBufferBuilder { } } - self.append_command( - Cmd { - source: source.clone(), - destination: destination.clone(), - source_layout, - regions: Mutex::new(Some(regions)), - }, - [ - ( - KeyTy::Image(source), - "source".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_read: true, - ..AccessFlags::none() - }, - exclusive: false, + let resources = [ + ( + "source".into(), + Resource::Image { + image: source.clone(), + subresource_range: ImageSubresourceRange { + // TODO: + aspects: source.format().aspects(), + mip_levels: source.current_mip_levels_access(), + array_layers: source.current_array_layers_access(), + }, + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() }, - source_layout, - source_layout, - )), - ), - ( - KeyTy::Buffer(destination), - "destination".into(), - Some(( - PipelineMemoryAccess { - stages: PipelineStages { - transfer: true, - ..PipelineStages::none() - }, - access: AccessFlags { - transfer_write: true, - ..AccessFlags::none() - }, - exclusive: true, + access: AccessFlags { + transfer_read: true, + ..AccessFlags::none() }, - ImageLayout::Undefined, - ImageLayout::Undefined, - )), - ), - ], - )?; + exclusive: false, + }, + start_layout: source_layout, + end_layout: source_layout, + }, + ), + ( + "destination".into(), + Resource::Buffer { + buffer: destination.clone(), + range: 0..destination.size(), // TODO: + memory: PipelineMemoryAccess { + stages: PipelineStages { + transfer: true, + ..PipelineStages::none() + }, + access: AccessFlags { + transfer_write: true, + ..AccessFlags::none() + }, + exclusive: true, + }, + }, + ), + ]; + + for resource in &resources { + self.check_resource_conflicts(resource)?; + } + + self.commands.push(Box::new(Cmd { + source, + destination, + source_layout, + regions: Mutex::new(Some(regions)), + })); + + for resource in resources { + self.add_resource(resource); + } Ok(()) } diff --git a/vulkano/src/command_buffer/synced/builder.rs b/vulkano/src/command_buffer/synced/builder.rs index 1a431c5a52..773572fb2f 100644 --- a/vulkano/src/command_buffer/synced/builder.rs +++ b/vulkano/src/command_buffer/synced/builder.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use super::{Command, KeyTy, SyncCommandBuffer}; +use super::{Command, Resource, SyncCommandBuffer}; pub use crate::command_buffer::commands::{ bind_push::{ SyncCommandBufferBuilderBindDescriptorSets, SyncCommandBufferBuilderBindVertexBuffer, @@ -24,7 +24,7 @@ use crate::{ }, descriptor_set::{DescriptorSetResources, DescriptorSetWithOffsets}, device::{Device, DeviceOwned}, - image::{sys::UnsafeImage, ImageAccess, ImageLayout}, + image::{sys::UnsafeImage, ImageAccess, ImageLayout, ImageSubresourceRange}, pipeline::{ graphics::{ color_blend::LogicOp, @@ -48,7 +48,7 @@ use std::{ borrow::Cow, collections::{hash_map::Entry, HashMap}, error, fmt, - mem::replace, + ops::Range, sync::Arc, }; @@ -107,13 +107,6 @@ pub struct SyncCommandBufferBuilder { // Current binding/setting state. pub(in crate::command_buffer) current_state: CurrentState, - // `true` if the builder has been put in an inconsistent state. This happens when - // `append_command` throws an error, because some changes to the internal state have already - // been made at that point and can't be reverted. - // TODO: throw the error in `append_command` _before_ any state changes are made, - // so that this is no longer needed. - is_poisoned: bool, - // True if we're a secondary command buffer. is_secondary: bool, } @@ -175,7 +168,6 @@ impl SyncCommandBufferBuilder { buffers: Vec::new(), images: Vec::new(), current_state: Default::default(), - is_poisoned: false, is_secondary, } } @@ -197,6 +189,148 @@ impl SyncCommandBufferBuilder { self.current_state = Default::default(); } + pub(in crate::command_buffer) fn check_resource_conflicts( + &self, + resource: &(Cow<'static, str>, Resource), + ) -> Result<(), SyncCommandBufferBuilderError> { + let (resource_name, resource) = resource; + + match resource { + &Resource::Buffer { + ref buffer, + ref range, + ref memory, + } => { + debug_assert!(memory.stages.supported_access().contains(&memory.access)); + + if let Some(conflicting_use) = + self.find_buffer_conflict(buffer, range.clone(), memory) + { + return Err(SyncCommandBufferBuilderError::Conflict { + command_param: resource_name.clone(), + previous_command_name: self.commands[conflicting_use.command_index].name(), + previous_command_offset: conflicting_use.command_index, + previous_command_param: conflicting_use.name.clone(), + }); + } + } + &Resource::Image { + ref image, + ref subresource_range, + ref memory, + start_layout, + end_layout, + } => { + debug_assert!(memory.exclusive || start_layout == end_layout); + debug_assert!(memory.stages.supported_access().contains(&memory.access)); + debug_assert!(end_layout != ImageLayout::Undefined); + debug_assert!(end_layout != ImageLayout::Preinitialized); + + if let Some(conflicting_use) = self.find_image_conflict( + image, + subresource_range.clone(), + memory, + start_layout, + end_layout, + ) { + return Err(SyncCommandBufferBuilderError::Conflict { + command_param: resource_name.clone(), + previous_command_name: self.commands[conflicting_use.command_index].name(), + previous_command_offset: conflicting_use.command_index, + previous_command_param: conflicting_use.name.clone(), + }); + } + } + } + + Ok(()) + } + + fn find_buffer_conflict( + &self, + buffer: &dyn BufferAccess, + mut range: Range, + memory: &PipelineMemoryAccess, + ) -> Option<&BufferUse> { + // Barriers work differently in render passes, so if we're in one, we can only insert a + // barrier before the start of the render pass. + let last_allowed_barrier_index = + self.latest_render_pass_enter.unwrap_or(self.commands.len()); + + let inner = buffer.inner(); + range.start += inner.offset; + range.end += inner.offset; + + let range_map = self.buffers2.get(inner.buffer)?; + + for (range, state) in range_map.range(&range) { + if let Some(state) = state { + debug_assert!(state + .resource_uses + .iter() + .all(|resource_use| resource_use.command_index <= self.commands.len())); + + if memory.exclusive || state.memory.exclusive { + // If there is a resource use at a position beyond where we can insert a + // barrier, then there is an unsolvable conflict. + if let Some(conflicting_use) = state.resource_uses.iter().find(|resource_use| { + resource_use.command_index >= last_allowed_barrier_index + }) { + return Some(conflicting_use); + } + } + } + } + + None + } + + fn find_image_conflict( + &self, + image: &dyn ImageAccess, + subresource_range: ImageSubresourceRange, + memory: &PipelineMemoryAccess, + start_layout: ImageLayout, + end_layout: ImageLayout, + ) -> Option<&ImageUse> { + // Barriers work differently in render passes, so if we're in one, we can only insert a + // barrier before the start of the render pass. + let last_allowed_barrier_index = + self.latest_render_pass_enter.unwrap_or(self.commands.len()); + + let inner = image.inner(); + + let range_map = self.images2.get(inner.image)?; + + for range in inner.image.iter_ranges(subresource_range) { + for (range, state) in range_map.range(&range) { + if let Some(state) = state { + debug_assert!(state + .resource_uses + .iter() + .all(|resource_use| resource_use.command_index <= self.commands.len())); + + if memory.exclusive + || state.memory.exclusive + || state.current_layout != start_layout + { + // If there is a resource use at a position beyond where we can insert a + // barrier, then there is an unsolvable conflict. + if let Some(conflicting_use) = + state.resource_uses.iter().find(|resource_use| { + resource_use.command_index >= last_allowed_barrier_index + }) + { + return Some(conflicting_use); + } + } + } + } + } + + None + } + // Adds a command to be processed by the builder. // // The `resources` argument should contain each buffer or image used by the command. @@ -209,74 +343,60 @@ impl SyncCommandBufferBuilder { // 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. #[inline] - pub(in crate::command_buffer) fn append_command( + pub(in crate::command_buffer) fn add_resource( &mut self, - command: C, - resources: impl IntoIterator< - Item = ( - KeyTy, - Cow<'static, str>, - Option<(PipelineMemoryAccess, ImageLayout, ImageLayout)>, - ), - >, - ) -> Result<(), SyncCommandBufferBuilderError> - where - C: Command + 'static, - { - // TODO: see comment for the `is_poisoned` member in the struct - assert!( - !self.is_poisoned, - "The builder has been put in an inconsistent state by a previous error" - ); - - // Note that we don't submit the command to the inner command buffer yet. - let (latest_command_id, end) = { - self.commands.push(Box::new(command)); - let latest_command_id = self.commands.len() - 1; - let end = self.latest_render_pass_enter.unwrap_or(latest_command_id); - (latest_command_id, end) - }; - - for (resource_ty, resource_name, resource) in resources { - if let Some((memory, start_layout, end_layout)) = resource { - // Anti-dumbness checks. - debug_assert!(memory.exclusive || start_layout == end_layout); - debug_assert!(memory.stages.supported_access().contains(&memory.access)); - - match resource_ty { - KeyTy::Buffer(buffer) => { - debug_assert!(start_layout == ImageLayout::Undefined); - debug_assert!(end_layout == ImageLayout::Undefined); - self.add_buffer(buffer, resource_name, memory)?; - } - KeyTy::Image(image) => { - debug_assert!(end_layout != ImageLayout::Undefined); - debug_assert!(end_layout != ImageLayout::Preinitialized); - self.add_image(image, resource_name, memory, start_layout, end_layout)?; - } - } + resource: (Cow<'static, str>, Resource), + ) { + let (resource_name, resource) = resource; + + match resource { + Resource::Buffer { + buffer, + range, + memory, + } => { + self.add_buffer(resource_name, buffer, range, memory); + } + Resource::Image { + image, + subresource_range, + memory, + start_layout, + end_layout, + } => { + self.add_image( + resource_name, + image, + subresource_range, + memory, + start_layout, + end_layout, + ); } } - - Ok(()) } fn add_buffer( &mut self, - buffer: Arc, resource_name: Cow<'static, str>, + buffer: Arc, + mut range: Range, memory: PipelineMemoryAccess, - ) -> Result<(), SyncCommandBufferBuilderError> { - let latest_command_id = self.commands.len() - 1; - let end = self.latest_render_pass_enter.unwrap_or(latest_command_id); + ) { + // Barriers work differently in render passes, so if we're in one, we can only insert a + // barrier before the start of the render pass. + let last_allowed_barrier_index = self + .latest_render_pass_enter + .unwrap_or(self.commands.len() - 1); let inner = buffer.inner(); + range.start += inner.offset; + range.end += inner.offset; + let range_map = self .buffers2 .entry(inner.buffer.clone()) .or_insert_with(|| [(0..inner.buffer.size(), None)].into_iter().collect()); - - let range = inner.offset..inner.offset + buffer.size(); range_map.split_at(&range.start); range_map.split_at(&range.end); @@ -284,11 +404,6 @@ impl SyncCommandBufferBuilder { match state { // Situation where this resource was used before in this command buffer. Some(state) => { - debug_assert!(state - .resource_uses - .iter() - .all(|resource_use| resource_use.command_index <= latest_command_id)); - // Find out if we have a collision with the pending commands. if memory.exclusive || state.memory.exclusive { // Collision found between `latest_command_id` and `collision_cmd_id`. @@ -297,49 +412,24 @@ impl SyncCommandBufferBuilder { // collision. But since the pipeline barrier is going to be submitted before // the flushed commands, it would be a mistake if `collision_cmd_id` hasn't // been flushed yet. - let first_unflushed_cmd_id = self.first_unflushed; - - if state.resource_uses.iter().any(|resource_use| { - resource_use.command_index >= first_unflushed_cmd_id - }) { + if state + .resource_uses + .iter() + .any(|resource_use| resource_use.command_index >= self.first_unflushed) + { unsafe { // Flush the pending barrier. - let barrier = - replace(&mut self.pending_barrier, DependencyInfo::default()); - self.inner.pipeline_barrier(barrier); + self.inner.pipeline_barrier(&self.pending_barrier); + self.pending_barrier.clear(); + self.barriers.push(self.first_unflushed); // Track inserted barriers - // Flush the commands if possible, or return an error if not possible. + for command in &mut self.commands + [self.first_unflushed..last_allowed_barrier_index] { - let start = self.first_unflushed; - self.barriers.push(start); // Track inserted barriers - - if let Some(conflicting_use) = state - .resource_uses - .iter() - .find(|resource_use| resource_use.command_index >= end) - { - // TODO: see comment for the `is_poisoned` member in the struct - self.is_poisoned = true; - - let cmd2 = &self.commands[latest_command_id]; - - return Err(SyncCommandBufferBuilderError::Conflict { - command1_name: self.commands - [conflicting_use.command_index] - .name(), - command1_param: conflicting_use.name.clone(), - command1_offset: conflicting_use.command_index, - - command2_name: self.commands[latest_command_id].name(), - command2_param: resource_name.clone(), - command2_offset: latest_command_id, - }); - } - for command in &mut self.commands[start..end] { - command.send(&mut self.inner); - } - self.first_unflushed = end; + command.send(&mut self.inner); } + + self.first_unflushed = last_allowed_barrier_index; } } @@ -356,7 +446,7 @@ impl SyncCommandBufferBuilder { }); state.resource_uses.push(BufferUse { - command_index: latest_command_id, + command_index: self.commands.len() - 1, name: resource_name.clone(), }); @@ -376,7 +466,7 @@ impl SyncCommandBufferBuilder { None => { *state = Some(BufferState { resource_uses: vec![BufferUse { - command_index: latest_command_id, + command_index: self.commands.len() - 1, name: resource_name.clone(), }], @@ -392,31 +482,50 @@ impl SyncCommandBufferBuilder { } self.buffers.push((buffer, memory)); - Ok(()) } fn add_image( &mut self, - image: Arc, resource_name: Cow<'static, str>, + image: Arc, + subresource_range: ImageSubresourceRange, memory: PipelineMemoryAccess, start_layout: ImageLayout, end_layout: ImageLayout, - ) -> Result<(), SyncCommandBufferBuilderError> { - let latest_command_id = self.commands.len() - 1; - let end = self.latest_render_pass_enter.unwrap_or(latest_command_id); + ) { + // Barriers work differently in render passes, so if we're in one, we can only insert a + // barrier before the start of the render pass. + let last_allowed_barrier_index = self + .latest_render_pass_enter + .unwrap_or(self.commands.len() - 1); let inner = image.inner(); - let range_map = self - .images2 - .entry(inner.image.clone()) - .or_insert_with(|| [(0..inner.image.range_size(), None)].into_iter().collect()); - - for range in inner.image.iter_ranges( - image.format().aspects(), - image.current_mip_levels_access(), - image.current_array_layers_access(), - ) { + + let range_map = self.images2.entry(inner.image.clone()).or_insert_with(|| { + [( + 0..inner.image.range_size(), + if !self.is_secondary && !image.is_layout_initialized() { + unsafe { + image.layout_initialized(); + } + + Some(ImageState { + resource_uses: Vec::new(), + memory: PipelineMemoryAccess::default(), + exclusive_any: false, + initial_layout: image.initial_layout(), + current_layout: image.initial_layout(), + final_layout: image.final_layout_requirement(), + }) + } else { + None + }, + )] + .into_iter() + .collect() + }); + + for range in inner.image.iter_ranges(subresource_range) { range_map.split_at(&range.start); range_map.split_at(&range.end); @@ -424,11 +533,6 @@ impl SyncCommandBufferBuilder { match state { // Situation where this resource was used before in this command buffer. Some(state) => { - debug_assert!(state - .resource_uses - .iter() - .all(|resource_use| resource_use.command_index <= latest_command_id)); - // Find out if we have a collision with the pending commands. if memory.exclusive || state.memory.exclusive @@ -440,53 +544,22 @@ impl SyncCommandBufferBuilder { // collision. But since the pipeline barrier is going to be submitted before // the flushed commands, it would be a mistake if `collision_cmd_id` hasn't // been flushed yet. - let first_unflushed_cmd_id = self.first_unflushed; - if state.resource_uses.iter().any(|resource_use| { - resource_use.command_index >= first_unflushed_cmd_id + resource_use.command_index >= self.first_unflushed }) || state.current_layout != start_layout { unsafe { // Flush the pending barrier. - let barrier = replace( - &mut self.pending_barrier, - DependencyInfo::default(), - ); - self.inner.pipeline_barrier(barrier); + self.inner.pipeline_barrier(&self.pending_barrier); + self.pending_barrier.clear(); + self.barriers.push(self.first_unflushed); // Track inserted barriers - // Flush the commands if possible, or return an error if not possible. + for command in &mut self.commands + [self.first_unflushed..last_allowed_barrier_index] { - let start = self.first_unflushed; - self.barriers.push(start); // Track inserted barriers - - if let Some(conflicting_use) = state - .resource_uses - .iter() - .find(|resource_use| resource_use.command_index >= end) - { - // TODO: see comment for the `is_poisoned` member in the struct - self.is_poisoned = true; - - let cmd2 = &self.commands[latest_command_id]; - - return Err(SyncCommandBufferBuilderError::Conflict { - command1_name: self.commands - [conflicting_use.command_index] - .name(), - command1_param: conflicting_use.name.clone(), - command1_offset: conflicting_use.command_index, - - command2_name: self.commands[latest_command_id] - .name(), - command2_param: resource_name.clone(), - command2_offset: latest_command_id, - }); - } - for command in &mut self.commands[start..end] { - command.send(&mut self.inner); - } - self.first_unflushed = end; + command.send(&mut self.inner); } + self.first_unflushed = last_allowed_barrier_index; } } @@ -507,7 +580,7 @@ impl SyncCommandBufferBuilder { }); state.resource_uses.push(ImageUse { - command_index: latest_command_id, + command_index: self.commands.len() - 1, name: resource_name.clone(), }); @@ -531,83 +604,67 @@ impl SyncCommandBufferBuilder { // Situation where this is the first time we use this resource in this command buffer. None => { - // We need to perform some tweaks if the initial layout requirement of the image - // is different from the first layout usage. let mut actually_exclusive = memory.exclusive; - let mut actual_start_layout = start_layout; + let mut initial_layout = start_layout; + let initial_layout_requirement = image.initial_layout_requirement(); + // If this is the first use of the image, and the start layout of the + // command differs from the default layout of the image, insert a transition + // from the default layout to `start_layout` before the command. if !self.is_secondary - && start_layout != ImageLayout::Undefined - && start_layout != ImageLayout::Preinitialized + && !matches!( + start_layout, + ImageLayout::Undefined | ImageLayout::Preinitialized, + ) + && initial_layout_requirement != start_layout { - let initial_layout_requirement = image.initial_layout_requirement(); - - // Checks if the image is initialized and transitions it - // if it isn't - let is_layout_initialized = image.is_layout_initialized(); - - if initial_layout_requirement != start_layout || !is_layout_initialized - { - // A layout transition is a write, so if we perform one, we need - // exclusive access. - actually_exclusive = true; - - // Note that we transition from `bottom_of_pipe`, which means that we - // wait for all the previous commands to be entirely finished. This is - // suboptimal, but: - // - // - If we're at the start of the command buffer we have no choice anyway, - // because we have no knowledge about what comes before. - // - If we're in the middle of the command buffer, this pipeline is going - // to be merged with an existing barrier. While it may still be - // suboptimal in some cases, in the general situation it will be ok. - // - unsafe { - let from_layout = if is_layout_initialized { - if initial_layout_requirement != start_layout { - actual_start_layout = initial_layout_requirement; - } - - initial_layout_requirement - } else { - actual_start_layout = image.initial_layout(); - image.initial_layout() - }; - self.pending_barrier.image_memory_barriers.push( - ImageMemoryBarrier { - source_stages: PipelineStages { - bottom_of_pipe: true, - ..PipelineStages::none() - }, - source_access: AccessFlags::none(), - destination_stages: memory.stages, - destination_access: memory.access, - old_layout: from_layout, - new_layout: start_layout, - subresource_range: inner - .image - .range_to_subresources(range.clone()), - ..ImageMemoryBarrier::image(inner.image.clone()) - }, - ); - image.layout_initialized(); - } - } + // A layout transition is a write, so if we perform one, we need + // exclusive access. + actually_exclusive = true; + initial_layout = initial_layout_requirement; + + // Note that we transition from `bottom_of_pipe`, which means that we + // wait for all the previous commands to be entirely finished. This is + // suboptimal, but: + // + // - If we're at the start of the command buffer we have no choice anyway, + // because we have no knowledge about what comes before. + // - If we're in the middle of the command buffer, this pipeline is going + // to be merged with an existing barrier. While it may still be + // suboptimal in some cases, in the general situation it will be ok. + // + self.pending_barrier + .image_memory_barriers + .push(ImageMemoryBarrier { + source_stages: PipelineStages { + bottom_of_pipe: true, + ..PipelineStages::none() + }, + source_access: AccessFlags::none(), + destination_stages: memory.stages, + destination_access: memory.access, + old_layout: initial_layout_requirement, + new_layout: start_layout, + subresource_range: inner + .image + .range_to_subresources(range.clone()), + ..ImageMemoryBarrier::image(inner.image.clone()) + }); } *state = Some(ImageState { resource_uses: vec![ImageUse { - command_index: latest_command_id, + command_index: self.commands.len() - 1, name: resource_name.clone(), }], memory: PipelineMemoryAccess { stages: memory.stages, access: memory.access, - exclusive: actually_exclusive, + exclusive: actually_exclusive, // TODO: is this correct, or should it be memory.exclusive? }, exclusive_any: actually_exclusive, - initial_layout: actual_start_layout, + initial_layout, current_layout: end_layout, final_layout: image.final_layout_requirement(), }); @@ -617,25 +674,20 @@ impl SyncCommandBufferBuilder { } self.images.push((image, memory, start_layout, end_layout)); - Ok(()) } /// Builds the command buffer and turns it into a `SyncCommandBuffer`. #[inline] pub fn build(mut self) -> Result { - // TODO: see comment for the `is_poisoned` member in the struct - assert!( - !self.is_poisoned, - "The builder has been put in an inconsistent state by a previous error" - ); - debug_assert!(self.latest_render_pass_enter.is_none() || self.pending_barrier.is_empty()); // The commands that haven't been sent to the inner command buffer yet need to be sent. unsafe { - self.inner.pipeline_barrier(self.pending_barrier); + self.inner.pipeline_barrier(&self.pending_barrier); + self.pending_barrier.clear(); let start = self.first_unflushed; self.barriers.push(start); // Track inserted barriers + for command in &mut self.commands[start..] { command.send(&mut self.inner); } @@ -644,9 +696,6 @@ impl SyncCommandBufferBuilder { // Transition images to their desired final layout. if !self.is_secondary { unsafe { - // TODO: this could be optimized by merging the barrier with the barrier above? - let mut barrier = DependencyInfo::default(); - for (image, range_map) in self.images2.iter_mut() { for (range, state) in range_map .iter_mut() @@ -656,26 +705,28 @@ impl SyncCommandBufferBuilder { continue; } - barrier.image_memory_barriers.push(ImageMemoryBarrier { - source_stages: state.memory.stages, - source_access: state.memory.access, - destination_stages: PipelineStages { - top_of_pipe: true, - ..PipelineStages::none() - }, - destination_access: AccessFlags::none(), - old_layout: state.current_layout, - new_layout: state.final_layout, - subresource_range: image.range_to_subresources(range.clone()), - ..ImageMemoryBarrier::image(image.clone()) - }); + self.pending_barrier + .image_memory_barriers + .push(ImageMemoryBarrier { + source_stages: state.memory.stages, + source_access: state.memory.access, + destination_stages: PipelineStages { + top_of_pipe: true, + ..PipelineStages::none() + }, + destination_access: AccessFlags::none(), + old_layout: state.current_layout, + new_layout: state.final_layout, + subresource_range: image.range_to_subresources(range.clone()), + ..ImageMemoryBarrier::image(image.clone()) + }); state.exclusive_any = true; state.current_layout = state.final_layout; } } - self.inner.pipeline_barrier(barrier); + self.inner.pipeline_barrier(&self.pending_barrier); } } @@ -761,13 +812,10 @@ impl fmt::Debug for SyncCommandBufferBuilder { pub enum SyncCommandBufferBuilderError { /// Unsolvable 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, + command_param: Cow<'static, str>, + previous_command_name: &'static str, + previous_command_offset: usize, + previous_command_param: Cow<'static, str>, }, ExecError(CommandBufferExecError), diff --git a/vulkano/src/command_buffer/synced/mod.rs b/vulkano/src/command_buffer/synced/mod.rs index b09c66bb52..0d031cd568 100644 --- a/vulkano/src/command_buffer/synced/mod.rs +++ b/vulkano/src/command_buffer/synced/mod.rs @@ -77,7 +77,7 @@ use super::{ use crate::{ buffer::{sys::UnsafeBuffer, BufferAccess}, device::{Device, DeviceOwned, Queue}, - image::{sys::UnsafeImage, ImageAccess, ImageLayout}, + image::{sys::UnsafeImage, ImageAccess, ImageLayout, ImageSubresourceRange}, sync::{ AccessCheckError, AccessError, AccessFlags, GpuFuture, PipelineMemoryAccess, PipelineStages, }, @@ -475,9 +475,19 @@ struct ImageUse { /// Type of resource whose state is to be tracked. #[derive(Clone)] -pub(super) enum KeyTy { - Buffer(Arc), - Image(Arc), +pub(super) enum Resource { + Buffer { + buffer: Arc, + range: Range, + memory: PipelineMemoryAccess, + }, + Image { + image: Arc, + subresource_range: ImageSubresourceRange, + memory: PipelineMemoryAccess, + start_layout: ImageLayout, + end_layout: ImageLayout, + }, } // Trait for single commands within the list of commands. @@ -499,7 +509,6 @@ impl std::fmt::Debug for dyn Command { #[cfg(test)] mod tests { use super::SyncCommandBufferBuilder; - use super::SyncCommandBufferBuilderError; use crate::buffer::BufferUsage; use crate::buffer::CpuAccessibleBuffer; use crate::buffer::ImmutableBuffer; @@ -529,6 +538,7 @@ mod tests { fn basic_creation() { unsafe { let (device, queue) = gfx_dev_and_queue!(); + let pool = Device::standard_command_pool(&device, queue.family()); let pool_builder_alloc = pool .allocate(CommandBufferLevel::Primary, 1) @@ -536,16 +546,14 @@ mod tests { .next() .unwrap(); - assert!(matches!( - SyncCommandBufferBuilder::new( - &pool_builder_alloc.inner(), - CommandBufferBeginInfo { - usage: CommandBufferUsage::MultipleSubmit, - ..Default::default() - }, - ), - Ok(_) - )); + SyncCommandBufferBuilder::new( + &pool_builder_alloc.inner(), + CommandBufferBeginInfo { + usage: CommandBufferUsage::MultipleSubmit, + ..Default::default() + }, + ) + .unwrap(); } } @@ -612,7 +620,7 @@ mod tests { .collect::>(); // Ensure that the builder added a barrier between the two writes - assert_eq!(&names, &["vkCmdExecuteCommands", "vkCmdExecuteCommands"]); + assert_eq!(&names, &["execute_commands", "execute_commands"]); assert_eq!(&primary.barriers, &[0, 1]); } @@ -631,15 +639,7 @@ mod tests { secondary.into_iter().for_each(|secondary| { ec.add(secondary); }); - - // The two writes can't be split up by a barrier because they are part of the same - // command. Therefore an error. - // TODO: Would be nice if SyncCommandBufferBuilder would split the commands - // automatically in order to insert a barrier. - assert!(matches!( - ec.submit(), - Err(SyncCommandBufferBuilderError::Conflict { .. }) - )); + ec.submit().unwrap(); } } } diff --git a/vulkano/src/command_buffer/synced/tests.rs b/vulkano/src/command_buffer/synced/tests.rs deleted file mode 100644 index d40654ba38..0000000000 --- a/vulkano/src/command_buffer/synced/tests.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// or the MIT -// license , -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use crate::buffer::BufferUsage; -use crate::buffer::CpuAccessibleBuffer; -use crate::command_buffer::pool::CommandPool; -use crate::command_buffer::pool::CommandPoolBuilderAlloc; -use crate::command_buffer::synced::base::SyncCommandBufferBuilder; -use crate::command_buffer::synced::base::SyncCommandBufferBuilderError; -use crate::command_buffer::sys::Flags; -use crate::command_buffer::Kind; -use crate::device::Device; -use std::iter; - -#[test] -fn basic_creation() { - unsafe { - let (device, queue) = gfx_dev_and_queue!(); - let pool = Device::standard_command_pool(&device, queue.family()); - let pool_builder_alloc = pool.alloc(false, 1).unwrap().next().unwrap(); - SyncCommandBufferBuilder::new(&pool_builder_alloc.inner(), Kind::primary(), Flags::None) - .unwrap(); - } -} - -#[test] -fn basic_conflict() { - unsafe { - let (device, queue) = gfx_dev_and_queue!(); - - let pool = Device::standard_command_pool(&device, queue.family()); - let pool_builder_alloc = pool.alloc(false, 1).unwrap().next().unwrap(); - let mut sync = SyncCommandBufferBuilder::new( - &pool_builder_alloc.inner(), - Kind::primary(), - Flags::None, - ) - .unwrap(); - let buf = CpuAccessibleBuffer::from_data(device, BufferUsage::all(), false, 0u32).unwrap(); - - match sync.copy_buffer(buf.clone(), buf.clone(), iter::once((0, 0, 4))) { - Err(SyncCommandBufferBuilderError::Conflict { .. }) => (), - _ => panic!(), - }; - } -} diff --git a/vulkano/src/image/sys.rs b/vulkano/src/image/sys.rs index 372316b8e9..2d79742513 100644 --- a/vulkano/src/image/sys.rs +++ b/vulkano/src/image/sys.rs @@ -14,8 +14,8 @@ //! that you create must wrap around the types in this module. use super::{ - ImageAspect, ImageAspects, ImageCreateFlags, ImageDimensions, ImageLayout, - ImageSubresourceRange, ImageTiling, ImageUsage, SampleCount, SampleCounts, + ImageAspect, ImageCreateFlags, ImageDimensions, ImageLayout, ImageSubresourceRange, + ImageTiling, ImageUsage, SampleCount, SampleCounts, }; use crate::{ buffer::cpu_access::{ReadLockError, WriteLockError}, @@ -1003,18 +1003,18 @@ impl UnsafeImage { #[inline] pub(crate) fn iter_ranges( &self, - aspects: ImageAspects, - mip_levels: Range, - array_layers: Range, + subresource_range: ImageSubresourceRange, ) -> SubresourceRangeIterator { - assert!(self.format().unwrap().aspects().contains(&aspects)); - assert!(mip_levels.end <= self.mip_levels); - assert!(array_layers.end <= self.dimensions.array_layers()); + assert!(self + .format() + .unwrap() + .aspects() + .contains(&subresource_range.aspects)); + assert!(subresource_range.mip_levels.end <= self.mip_levels); + assert!(subresource_range.array_layers.end <= self.dimensions.array_layers()); SubresourceRangeIterator::new( - aspects, - mip_levels, - array_layers, + subresource_range, &self.aspect_list, self.aspect_size, self.mip_levels, @@ -1994,27 +1994,30 @@ pub(crate) struct SubresourceRangeIterator { impl SubresourceRangeIterator { fn new( - aspects: ImageAspects, - mip_levels: Range, - array_layers: Range, + subresource_range: ImageSubresourceRange, image_aspect_list: &[ImageAspect], image_aspect_size: DeviceSize, image_mip_levels: u32, image_mip_level_size: DeviceSize, image_array_layers: u32, ) -> Self { - assert!(!mip_levels.is_empty()); - assert!(!array_layers.is_empty()); + assert!(!subresource_range.mip_levels.is_empty()); + assert!(!subresource_range.array_layers.is_empty()); - let next_fn = if array_layers.start != 0 || array_layers.end != image_array_layers { + let next_fn = if subresource_range.array_layers.start != 0 + || subresource_range.array_layers.end != image_array_layers + { Self::next_some_layers - } else if mip_levels.start != 0 || mip_levels.end != image_mip_levels { + } else if subresource_range.mip_levels.start != 0 + || subresource_range.mip_levels.end != image_mip_levels + { Self::next_some_levels_all_layers } else { Self::next_all_levels_all_layers }; - let mut aspect_nums = aspects + let mut aspect_nums = subresource_range + .aspects .iter() .map(|aspect| image_aspect_list.iter().position(|&a| a == aspect).unwrap()) .collect::>() @@ -2022,14 +2025,14 @@ impl SubresourceRangeIterator { .peekable(); assert!(aspect_nums.len() != 0); let current_aspect_num = aspect_nums.next(); - let current_mip_level = mip_levels.start; + let current_mip_level = subresource_range.mip_levels.start; Self { next_fn, image_aspect_size, image_mip_level_size, - mip_levels, - array_layers, + mip_levels: subresource_range.mip_levels, + array_layers: subresource_range.array_layers, aspect_nums, current_aspect_num, @@ -2114,6 +2117,7 @@ mod tests { use crate::image::ImageAspect; use crate::image::ImageAspects; use crate::image::ImageDimensions; + use crate::image::ImageSubresourceRange; use crate::image::SampleCount; use crate::DeviceSize; use smallvec::SmallVec; @@ -2354,15 +2358,17 @@ mod tests { // Whole image let mut iter = SubresourceRangeIterator::new( - ImageAspects { - color: true, - depth: true, - stencil: true, - plane0: true, - ..ImageAspects::none() + ImageSubresourceRange { + aspects: ImageAspects { + color: true, + depth: true, + stencil: true, + plane0: true, + ..ImageAspects::none() + }, + mip_levels: 0..6, + array_layers: 0..8, }, - 0..6, - 0..8, &image_aspect_list, asp, image_mip_levels, @@ -2374,15 +2380,17 @@ mod tests { // Only some aspects let mut iter = SubresourceRangeIterator::new( - ImageAspects { - color: true, - depth: true, - stencil: false, - plane0: true, - ..ImageAspects::none() + ImageSubresourceRange { + aspects: ImageAspects { + color: true, + depth: true, + stencil: false, + plane0: true, + ..ImageAspects::none() + }, + mip_levels: 0..6, + array_layers: 0..8, }, - 0..6, - 0..8, &image_aspect_list, asp, image_mip_levels, @@ -2395,15 +2403,17 @@ mod tests { // Two aspects, and only some of the mip levels let mut iter = SubresourceRangeIterator::new( - ImageAspects { - color: false, - depth: true, - stencil: true, - plane0: false, - ..ImageAspects::none() + ImageSubresourceRange { + aspects: ImageAspects { + color: false, + depth: true, + stencil: true, + plane0: false, + ..ImageAspects::none() + }, + mip_levels: 2..4, + array_layers: 0..8, }, - 2..4, - 0..8, &image_aspect_list, asp, image_mip_levels, @@ -2416,15 +2426,17 @@ mod tests { // One aspect, one mip level, only some of the array layers let mut iter = SubresourceRangeIterator::new( - ImageAspects { - color: true, - depth: false, - stencil: false, - plane0: false, - ..ImageAspects::none() + ImageSubresourceRange { + aspects: ImageAspects { + color: true, + depth: false, + stencil: false, + plane0: false, + ..ImageAspects::none() + }, + mip_levels: 0..1, + array_layers: 2..4, }, - 0..1, - 2..4, &image_aspect_list, asp, image_mip_levels, @@ -2439,15 +2451,17 @@ mod tests { // Two aspects, two mip levels, only some of the array layers let mut iter = SubresourceRangeIterator::new( - ImageAspects { - color: false, - depth: true, - stencil: true, - plane0: false, - ..ImageAspects::none() + ImageSubresourceRange { + aspects: ImageAspects { + color: false, + depth: true, + stencil: true, + plane0: false, + ..ImageAspects::none() + }, + mip_levels: 2..4, + array_layers: 6..8, }, - 2..4, - 6..8, &image_aspect_list, asp, image_mip_levels, diff --git a/vulkano/src/image/traits.rs b/vulkano/src/image/traits.rs index 901fb74523..1b6e93317e 100644 --- a/vulkano/src/image/traits.rs +++ b/vulkano/src/image/traits.rs @@ -74,7 +74,7 @@ pub unsafe trait ImageAccess: Send + Sync { false } - unsafe fn initial_layout(&self) -> ImageLayout { + fn initial_layout(&self) -> ImageLayout { self.inner().image.initial_layout() } diff --git a/vulkano/src/sync/pipeline.rs b/vulkano/src/sync/pipeline.rs index d5e780dacc..adc9e5e2f7 100644 --- a/vulkano/src/sync/pipeline.rs +++ b/vulkano/src/sync/pipeline.rs @@ -20,7 +20,7 @@ use std::{ macro_rules! pipeline_stages { ($($elem:ident, $var:ident => $val:ident, $queue:expr;)+) => ( - #[derive(Debug, Copy, Clone, PartialEq, Eq)] + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct PipelineStages { $( pub $elem: bool, @@ -261,7 +261,7 @@ pipeline_stages! { macro_rules! access_flags { ($($elem:ident => $val:ident,)+) => ( - #[derive(Debug, Copy, Clone, PartialEq, Eq)] + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[allow(missing_docs)] pub struct AccessFlags { $( @@ -363,7 +363,7 @@ access_flags! { } /// The full specification of memory access by the pipeline for a particular resource. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] pub struct PipelineMemoryAccess { /// The pipeline stages the resource will be accessed in. pub stages: PipelineStages, @@ -409,6 +409,14 @@ impl DependencyInfo { && self.buffer_memory_barriers.is_empty() && self.image_memory_barriers.is_empty() } + + /// Clears all barriers. + #[inline] + pub fn clear(&mut self) { + self.memory_barriers.clear(); + self.buffer_memory_barriers.clear(); + self.image_memory_barriers.clear(); + } } impl Default for DependencyInfo {