command is DeviceOwnedHandle derived now

CommandList helper for submitting many commands in one submit call
This commit is contained in:
Janis 2025-01-05 01:14:32 +01:00
parent 9334e8fa9e
commit ac40cddfb7

View file

@ -1,6 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use crate::{ use crate::{
define_device_owned_handle,
device::DeviceOwned, device::DeviceOwned,
images::{Image, QueueOwnership}, images::{Image, QueueOwnership},
pipeline::{Pipeline, PipelineLayout}, pipeline::{Pipeline, PipelineLayout},
@ -12,6 +13,7 @@ use super::{Device, Queue};
use ash::{prelude::*, vk}; use ash::{prelude::*, vk};
use parking_lot::Mutex; use parking_lot::Mutex;
#[derive(Debug)]
pub struct SingleUseCommandPool { pub struct SingleUseCommandPool {
device: Device, device: Device,
pool: Mutex<vk::CommandPool>, pool: Mutex<vk::CommandPool>,
@ -67,24 +69,66 @@ impl SingleUseCommandPool {
} }
} }
pub struct SingleUseCommand { pub trait CommandBuffer: DeviceOwned<vk::CommandBuffer> {
device: Device, fn queue(&self) -> &Queue;
}
impl CommandBuffer for SingleUseCommand {
fn queue(&self) -> &Queue {
&self.pool.queue
}
}
pub struct CommandList<T: CommandBuffer>(pub Vec<T>);
impl<T: CommandBuffer> CommandList<T> {
/// 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<vk::Semaphore>,
fence: Arc<sync::Fence>,
) -> VkResult<FenceFuture<'a>> {
if self.0.is_empty() {
//exit
}
let buffers = self.0.iter().map(|cmd| cmd.handle()).collect::<Vec<_>>();
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<SingleUseCommandPool>, pool: Arc<SingleUseCommandPool>,
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 !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 { impl SingleUseCommand {
pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> { pub fn new(device: Device, pool: Arc<SingleUseCommandPool>) -> VkResult<Self> {
let buffer = unsafe { let buffer = unsafe {
@ -102,16 +146,13 @@ impl SingleUseCommand {
buffer buffer
}; };
Ok(Self {
device, Self::construct(device, buffer, None, pool)
pool,
buffer,
})
} }
/// Safety: commandbuffer must not be accessed from multiple threads at the same time /// Safety: commandbuffer must not be accessed from multiple threads at the same time
pub unsafe fn buffer(&self) -> vk::CommandBuffer { pub unsafe fn buffer(&self) -> vk::CommandBuffer {
self.buffer self.handle()
} }
//pub fn copy_buffer_to_image(&self, image: &Image2D, buffer: &Buffer, ) //pub fn copy_buffer_to_image(&self, image: &Image2D, buffer: &Buffer, )
@ -152,8 +193,8 @@ impl SingleUseCommand {
.new_layout(new_layout); .new_layout(new_layout);
unsafe { unsafe {
self.device.dev().cmd_pipeline_barrier2( self.device().dev().cmd_pipeline_barrier2(
self.buffer, self.handle(),
&vk::DependencyInfo::default() &vk::DependencyInfo::default()
.dependency_flags(vk::DependencyFlags::BY_REGION) .dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(core::slice::from_ref(&barrier)), .image_memory_barriers(core::slice::from_ref(&barrier)),
@ -169,8 +210,8 @@ impl SingleUseCommand {
dst_region: util::Rect2D, dst_region: util::Rect2D,
) { ) {
unsafe { unsafe {
self.device.dev().cmd_blit_image( self.device().dev().cmd_blit_image(
self.buffer, self.buffer(),
src.image(), src.image(),
vk::ImageLayout::TRANSFER_SRC_OPTIMAL, vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
dst.image(), dst.image(),
@ -201,19 +242,24 @@ impl SingleUseCommand {
regions: &[vk::BufferImageCopy], regions: &[vk::BufferImageCopy],
) { ) {
unsafe { unsafe {
self.device self.device().dev().cmd_copy_buffer_to_image(
.dev() self.handle(),
.cmd_copy_buffer_to_image(self.buffer, buffer, image, layout, regions); buffer,
image,
layout,
regions,
);
} }
} }
pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) { pub fn copy_buffers(&self, src: vk::Buffer, dst: vk::Buffer, regions: &[vk::BufferCopy]) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_copy_buffer(self.buffer, src, dst, regions); .cmd_copy_buffer(self.handle(), src, dst, regions);
} }
} }
#[allow(dead_code)]
pub fn copy_images( pub fn copy_images(
&self, &self,
src: vk::Image, src: vk::Image,
@ -223,8 +269,8 @@ impl SingleUseCommand {
regions: &[vk::ImageCopy], regions: &[vk::ImageCopy],
) { ) {
unsafe { unsafe {
self.device.dev().cmd_copy_image( self.device().dev().cmd_copy_image(
self.buffer, self.handle(),
src, src,
src_layout, src_layout,
dst, dst,
@ -255,8 +301,8 @@ impl SingleUseCommand {
}; };
unsafe { unsafe {
self.device.dev().cmd_clear_color_image( self.device().dev().cmd_clear_color_image(
self.buffer, self.handle(),
image, image,
layout, layout,
&clear_colors, &clear_colors,
@ -267,7 +313,7 @@ impl SingleUseCommand {
pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) { pub fn begin_rendering(&self, rendering_info: vk::RenderingInfo<'_>) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_begin_rendering(self.buffer(), &rendering_info); .cmd_begin_rendering(self.buffer(), &rendering_info);
} }
@ -275,14 +321,14 @@ impl SingleUseCommand {
pub fn set_viewport(&self, viewports: &[vk::Viewport]) { pub fn set_viewport(&self, viewports: &[vk::Viewport]) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_set_viewport(self.buffer(), 0, viewports); .cmd_set_viewport(self.buffer(), 0, viewports);
} }
} }
pub fn set_scissors(&self, scissors: &[vk::Rect2D]) { pub fn set_scissors(&self, scissors: &[vk::Rect2D]) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_set_scissor(self.buffer(), 0, scissors); .cmd_set_scissor(self.buffer(), 0, scissors);
} }
@ -295,8 +341,8 @@ impl SingleUseCommand {
bytes: &[u8], bytes: &[u8],
) { ) {
unsafe { unsafe {
self.device.dev().cmd_push_constants( self.device().dev().cmd_push_constants(
self.buffer, self.handle(),
layout.handle(), layout.handle(),
stage, stage,
offset, offset,
@ -306,7 +352,7 @@ impl SingleUseCommand {
} }
pub fn bind_pipeline(&self, pipeline: &Pipeline) { pub fn bind_pipeline(&self, pipeline: &Pipeline) {
unsafe { unsafe {
self.device.dev().cmd_bind_pipeline( self.device().dev().cmd_bind_pipeline(
self.buffer(), self.buffer(),
pipeline.bind_point(), pipeline.bind_point(),
pipeline.handle(), pipeline.handle(),
@ -315,14 +361,14 @@ impl SingleUseCommand {
} }
pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) { pub fn bind_vertices(&self, buffer: vk::Buffer, offset: u64) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_bind_vertex_buffers(self.buffer(), 0, &[buffer], &[offset]); .cmd_bind_vertex_buffers(self.buffer(), 0, &[buffer], &[offset]);
} }
} }
pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) { pub fn bind_indices(&self, buffer: vk::Buffer, offset: u64, kind: vk::IndexType) {
unsafe { unsafe {
self.device self.device()
.dev() .dev()
.cmd_bind_index_buffer(self.buffer(), buffer, offset, kind); .cmd_bind_index_buffer(self.buffer(), buffer, offset, kind);
} }
@ -336,7 +382,7 @@ impl SingleUseCommand {
) { ) {
use crate::device::DeviceOwned; use crate::device::DeviceOwned;
unsafe { unsafe {
self.device.dev().cmd_bind_descriptor_sets( self.device().dev().cmd_bind_descriptor_sets(
self.buffer(), self.buffer(),
bind_point, bind_point,
layout.handle(), layout.handle(),
@ -357,7 +403,7 @@ impl SingleUseCommand {
instance_offset: u32, instance_offset: u32,
) { ) {
unsafe { unsafe {
self.device.dev().cmd_draw_indexed( self.device().dev().cmd_draw_indexed(
self.buffer(), self.buffer(),
indices, indices,
instances, instances,
@ -370,7 +416,7 @@ impl SingleUseCommand {
pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) { pub fn draw_indexed_indirect(&self, buffer: vk::Buffer, offset: u64, count: u32, stride: u32) {
unsafe { unsafe {
self.device.dev().cmd_draw_indexed_indirect( self.device().dev().cmd_draw_indexed_indirect(
self.buffer(), self.buffer(),
buffer, buffer,
offset, offset,
@ -382,7 +428,7 @@ impl SingleUseCommand {
pub fn end_rendering(&self) { pub fn end_rendering(&self) {
unsafe { 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<vk::Semaphore>, signal: Option<vk::Semaphore>,
fence: Option<vk::Fence>, fence: Option<vk::Fence>,
) -> VkResult<()> { ) -> 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); let mut submit_info = vk::SubmitInfo::default().command_buffers(&buffers);
if let Some(semaphore) = signal.as_ref() { if let Some(semaphore) = signal.as_ref() {
@ -411,7 +457,9 @@ impl SingleUseCommand {
let fence = fence.unwrap_or(vk::Fence::null()); let fence = fence.unwrap_or(vk::Fence::null());
self.pool.queue().with_locked(|queue| unsafe { 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!( tracing::trace!(
"submitted queue {:?} and fence {:?}", "submitted queue {:?} and fence {:?}",
@ -439,7 +487,7 @@ impl SingleUseCommand {
wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>, wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>,
signal: Option<vk::Semaphore>, signal: Option<vk::Semaphore>,
) -> VkResult<()> { ) -> 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)?; let future = self.submit_async(wait, signal, fence)?;
future.block()?; future.block()?;
Ok(()) Ok(())