command is DeviceOwnedHandle derived now
CommandList helper for submitting many commands in one submit call
This commit is contained in:
parent
9334e8fa9e
commit
ac40cddfb7
|
@ -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(())
|
||||||
|
|
Loading…
Reference in a new issue