From ac40cddfb70ee2de4f9400e41e63a96e76da447b Mon Sep 17 00:00:00 2001 From: Janis Date: Sun, 5 Jan 2025 01:14:32 +0100 Subject: [PATCH] command is DeviceOwnedHandle derived now CommandList helper for submitting many commands in one submit call --- crates/renderer/src/commands.rs | 144 +++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 48 deletions(-) diff --git a/crates/renderer/src/commands.rs b/crates/renderer/src/commands.rs index af971cf..a65f7d2 100644 --- a/crates/renderer/src/commands.rs +++ b/crates/renderer/src/commands.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use crate::{ + define_device_owned_handle, device::DeviceOwned, images::{Image, QueueOwnership}, pipeline::{Pipeline, PipelineLayout}, @@ -12,6 +13,7 @@ use super::{Device, Queue}; use ash::{prelude::*, vk}; use parking_lot::Mutex; +#[derive(Debug)] pub struct SingleUseCommandPool { device: Device, pool: Mutex, @@ -67,24 +69,66 @@ impl SingleUseCommandPool { } } -pub struct SingleUseCommand { - device: Device, +pub trait CommandBuffer: DeviceOwned { + fn queue(&self) -> &Queue; +} + +impl CommandBuffer for SingleUseCommand { + fn queue(&self) -> &Queue { + &self.pool.queue + } +} + +pub struct CommandList(pub Vec); + +impl CommandList { + /// all commands in list must be allocated from the same queue. + pub fn submit<'a>( + &'a self, + wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>, + signal: Option, + fence: Arc, + ) -> VkResult> { + if self.0.is_empty() { + //exit + } + let buffers = self.0.iter().map(|cmd| cmd.handle()).collect::>(); + + let mut info = vk::SubmitInfo::default().command_buffers(&buffers); + if let Some((sema, stage)) = wait.as_ref() { + info = info + .wait_dst_stage_mask(core::slice::from_ref(stage)) + .wait_semaphores(core::slice::from_ref(sema)); + } + + if let Some(signal) = signal.as_ref() { + info = info.signal_semaphores(core::slice::from_ref(signal)); + } + + self.0[0].queue().with_locked(|queue| unsafe { + self.0[0] + .device() + .dev() + .queue_submit(queue, &[info], fence.fence()) + })?; + + Ok(FenceFuture::<'a>::new(fence)) + } +} + +define_device_owned_handle! { + #[derive(Debug)] + pub SingleUseCommand(vk::CommandBuffer) { pool: Arc, - buffer: vk::CommandBuffer, + } => |this| unsafe { + this.pool + .pool + .with_locked(|&pool| this.device().dev().free_command_buffers(pool, &[this.handle()])) + } } impl !Sync for SingleUseCommand {} -impl Drop for SingleUseCommand { - fn drop(&mut self) { - unsafe { - self.pool - .pool - .with_locked(|&pool| self.device.dev().free_command_buffers(pool, &[self.buffer])) - }; - } -} - impl SingleUseCommand { pub fn new(device: Device, pool: Arc) -> VkResult { let buffer = unsafe { @@ -102,16 +146,13 @@ impl SingleUseCommand { buffer }; - Ok(Self { - device, - pool, - buffer, - }) + + Self::construct(device, buffer, None, pool) } /// Safety: commandbuffer must not be accessed from multiple threads at the same time pub unsafe fn buffer(&self) -> vk::CommandBuffer { - self.buffer + self.handle() } //pub fn copy_buffer_to_image(&self, image: &Image2D, buffer: &Buffer, ) @@ -152,8 +193,8 @@ impl SingleUseCommand { .new_layout(new_layout); unsafe { - self.device.dev().cmd_pipeline_barrier2( - self.buffer, + self.device().dev().cmd_pipeline_barrier2( + self.handle(), &vk::DependencyInfo::default() .dependency_flags(vk::DependencyFlags::BY_REGION) .image_memory_barriers(core::slice::from_ref(&barrier)), @@ -169,8 +210,8 @@ impl SingleUseCommand { dst_region: util::Rect2D, ) { unsafe { - self.device.dev().cmd_blit_image( - self.buffer, + self.device().dev().cmd_blit_image( + self.buffer(), src.image(), vk::ImageLayout::TRANSFER_SRC_OPTIMAL, dst.image(), @@ -201,19 +242,24 @@ impl SingleUseCommand { regions: &[vk::BufferImageCopy], ) { unsafe { - self.device - .dev() - .cmd_copy_buffer_to_image(self.buffer, buffer, image, layout, regions); + self.device().dev().cmd_copy_buffer_to_image( + self.handle(), + buffer, + image, + layout, + regions, + ); } } pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) { unsafe { - self.device + self.device() .dev() - .cmd_copy_buffer(self.buffer, src, dst, regions); + .cmd_copy_buffer(self.handle(), src, dst, regions); } } + #[allow(dead_code)] pub fn copy_images( &self, src: vk::Image, @@ -223,8 +269,8 @@ impl SingleUseCommand { regions: &[vk::ImageCopy], ) { unsafe { - self.device.dev().cmd_copy_image( - self.buffer, + self.device().dev().cmd_copy_image( + self.handle(), src, src_layout, dst, @@ -255,8 +301,8 @@ impl SingleUseCommand { }; unsafe { - self.device.dev().cmd_clear_color_image( - self.buffer, + self.device().dev().cmd_clear_color_image( + self.handle(), image, layout, &clear_colors, @@ -267,7 +313,7 @@ impl SingleUseCommand { pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) { unsafe { - self.device + self.device() .dev() .cmd_begin_rendering(self.buffer(), &rendering_info); } @@ -275,14 +321,14 @@ impl SingleUseCommand { pub fn set_viewport(&self, viewports: &[vk::Viewport]) { unsafe { - self.device + self.device() .dev() .cmd_set_viewport(self.buffer(), 0, viewports); } } pub fn set_scissors(&self, scissors: &[vk::Rect2D]) { unsafe { - self.device + self.device() .dev() .cmd_set_scissor(self.buffer(), 0, scissors); } @@ -295,8 +341,8 @@ impl SingleUseCommand { bytes: &[u8], ) { unsafe { - self.device.dev().cmd_push_constants( - self.buffer, + self.device().dev().cmd_push_constants( + self.handle(), layout.handle(), stage, offset, @@ -306,7 +352,7 @@ impl SingleUseCommand { } pub fn bind_pipeline(&self, pipeline: &Pipeline) { unsafe { - self.device.dev().cmd_bind_pipeline( + self.device().dev().cmd_bind_pipeline( self.buffer(), pipeline.bind_point(), pipeline.handle(), @@ -315,14 +361,14 @@ impl SingleUseCommand { } pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) { unsafe { - self.device + self.device() .dev() .cmd_bind_vertex_buffers(self.buffer(), 0, &[buffer], &[offset]); } } pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) { unsafe { - self.device + self.device() .dev() .cmd_bind_index_buffer(self.buffer(), buffer, offset, kind); } @@ -336,7 +382,7 @@ impl SingleUseCommand { ) { use crate::device::DeviceOwned; unsafe { - self.device.dev().cmd_bind_descriptor_sets( + self.device().dev().cmd_bind_descriptor_sets( self.buffer(), bind_point, layout.handle(), @@ -357,7 +403,7 @@ impl SingleUseCommand { instance_offset: u32, ) { unsafe { - self.device.dev().cmd_draw_indexed( + self.device().dev().cmd_draw_indexed( self.buffer(), indices, instances, @@ -370,7 +416,7 @@ impl SingleUseCommand { pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) { unsafe { - self.device.dev().cmd_draw_indexed_indirect( + self.device().dev().cmd_draw_indexed_indirect( self.buffer(), buffer, offset, @@ -382,7 +428,7 @@ impl SingleUseCommand { pub fn end_rendering(&self) { unsafe { - self.device.dev().cmd_end_rendering(self.buffer()); + self.device().dev().cmd_end_rendering(self.buffer()); } } @@ -392,9 +438,9 @@ impl SingleUseCommand { signal: Option, fence: Option, ) -> VkResult<()> { - unsafe { self.device.dev().end_command_buffer(self.buffer)? }; + unsafe { self.device().dev().end_command_buffer(self.handle())? }; - let buffers = [self.buffer]; + let buffers = [self.handle()]; let mut submit_info = vk::SubmitInfo::default().command_buffers(&buffers); if let Some(semaphore) = signal.as_ref() { @@ -411,7 +457,9 @@ impl SingleUseCommand { let fence = fence.unwrap_or(vk::Fence::null()); self.pool.queue().with_locked(|queue| unsafe { - self.device.dev().queue_submit(queue, &[submit_info], fence) + self.device() + .dev() + .queue_submit(queue, &[submit_info], fence) })?; tracing::trace!( "submitted queue {:?} and fence {:?}", @@ -439,7 +487,7 @@ impl SingleUseCommand { wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>, signal: Option, ) -> VkResult<()> { - let fence = Arc::new(sync::Fence::create(self.device.clone())?); + let fence = Arc::new(sync::Fence::create(self.device().clone())?); let future = self.submit_async(wait, signal, fence)?; future.block()?; Ok(())