diff --git a/vulkan-rs/src/lib.rs b/vulkan-rs/src/lib.rs index c40ebdd..7af27d6 100644 --- a/vulkan-rs/src/lib.rs +++ b/vulkan-rs/src/lib.rs @@ -42,6 +42,7 @@ pub mod swapchain; pub mod ffi; mod sampler_manager; +mod single_submit; #[derive(Clone, Debug)] pub enum OutOfDate { diff --git a/vulkan-rs/src/prelude.rs b/vulkan-rs/src/prelude.rs index 4278819..288c0f4 100644 --- a/vulkan-rs/src/prelude.rs +++ b/vulkan-rs/src/prelude.rs @@ -47,3 +47,5 @@ pub use super::render_target::{ sub_pass::{ClearValue, CustomTarget, SubPass, SubPassBuilder}, RenderTarget, }; + +pub use super::single_submit::SingleSubmit; diff --git a/vulkan-rs/src/single_submit/mod.rs b/vulkan-rs/src/single_submit/mod.rs new file mode 100644 index 0000000..e720990 --- /dev/null +++ b/vulkan-rs/src/single_submit/mod.rs @@ -0,0 +1,73 @@ +use crate::prelude::*; +use anyhow::Result; + +use std::sync::{Arc, Mutex}; +use std::time::Duration; + +pub struct SingleSubmit<'a, F, T> +where + F: FnOnce(&mut CommandBufferRecorder<'_>) -> Result, +{ + command_buffer: &'a Arc, + queue: &'a Arc>, + f: F, + + timeout: Option, +} + +impl<'a, F, T> SingleSubmit<'a, F, T> +where + F: FnOnce(&mut CommandBufferRecorder<'_>) -> Result, +{ + pub fn builder( + command_buffer: &'a Arc, + queue: &'a Arc>, + f: F, + ) -> Self { + SingleSubmit { + command_buffer, + queue, + f, + + timeout: None, + } + } + + pub fn wait_for_timeout(mut self, timeout: Duration) -> Self { + self.timeout = Some(timeout); + + self + } + + pub fn submit(self) -> Result { + let result = { + let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new( + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + ))?; + + (self.f)(&mut buffer_recorder)? + }; + + let submit = SubmitInfo::default().add_command_buffer(self.command_buffer); + let queue_lock = self.queue.lock().unwrap(); + + match self.timeout { + Some(timeout) => { + let fence = Fence::builder().build(self.command_buffer.device().clone())?; + + queue_lock.submit(Some(&fence), &[submit])?; + + self.command_buffer + .device() + .wait_for_fences(&[&fence], true, timeout)?; + } + None => { + queue_lock.submit(None, &[submit])?; + + queue_lock.wait_idle()?; + } + } + + Ok(result) + } +}