vulkayes_core/command/buffer/
mod.rs1use std::{fmt::Debug, ops::Deref};
2
3use ash::{version::DeviceV1_0, vk};
4
5use crate::{
6 command::pool::CommandPool,
7 prelude::{HasSynchronizedHandle, Vrc},
8 util::sync::Vutex
9};
10
11use super::error::CommandBufferError;
12
13pub mod recording;
14pub struct CommandBuffer {
20 pool: Vrc<CommandPool>,
21 command_buffer: Vutex<vk::CommandBuffer>
22}
23impl CommandBuffer {
24 pub fn new(pool: Vrc<CommandPool>, primary: bool) -> Result<Vrc<Self>, CommandBufferError> {
25 let level = match primary {
26 true => vk::CommandBufferLevel::PRIMARY,
27 false => vk::CommandBufferLevel::SECONDARY
28 };
29 let [raw] = unsafe { pool.allocate_command_buffer(level)? };
30
31 Ok(Vrc::new(unsafe { Self::from_existing(pool, raw) }))
32 }
33
34 pub fn new_multiple(
35 pool: Vrc<CommandPool>,
36 primary: bool,
37 count: std::num::NonZeroU32
38 ) -> Result<Vec<Vrc<Self>>, CommandBufferError> {
39 let level = match primary {
40 true => vk::CommandBufferLevel::PRIMARY,
41 false => vk::CommandBufferLevel::SECONDARY
42 };
43 let raw = unsafe { pool.allocate_command_buffers(level, count)? };
44
45 let buffers: Vec<_> = raw
46 .into_iter()
47 .map(|command_buffer| {
48 Vrc::new(unsafe { Self::from_existing(pool.clone(), command_buffer) })
49 })
50 .collect();
51
52 Ok(buffers)
53 }
54
55 pub unsafe fn from_existing(pool: Vrc<CommandPool>, command_buffer: vk::CommandBuffer) -> Self {
61 log_trace_common!(
62 "Creating CommandBuffer from existing handle:",
63 pool,
64 crate::util::fmt::format_handle(command_buffer)
65 );
66
67 Self {
68 pool,
69 command_buffer: Vutex::new(command_buffer)
70 }
71 }
72
73 pub fn reset(&self, release_resource: bool) -> Result<(), CommandBufferError> {
77 let handle = self.lock_handle();
78
79 let flags = if release_resource {
80 vk::CommandBufferResetFlags::RELEASE_RESOURCES
81 } else {
82 vk::CommandBufferResetFlags::empty()
83 };
84
85 log_trace_common!(
86 "Resetting command buffer:",
87 crate::util::fmt::format_handle(*handle),
88 flags
89 );
90 unsafe {
91 self.pool()
92 .device()
93 .reset_command_buffer(*handle, flags)
94 .map_err(CommandBufferError::from)
95 }
96 }
97
98 pub fn begin_recording(
104 &self,
105 info: recording::CommandBufferBeginInfo
106 ) -> Result<recording::CommandBufferRecordingLockOutsideRenderPass, CommandBufferError> {
107 let lock = recording::common::CommandBufferRecordingLockCommon::new(self);
108
109 recording::CommandBufferRecordingLockOutsideRenderPass::new(lock, info)
110 }
111
112 pub const fn pool(&self) -> &Vrc<CommandPool> {
113 &self.pool
114 }
115}
116impl_common_handle_traits! {
117 impl HasSynchronizedHandle<vk::CommandBuffer>, Deref, Borrow, Eq, Hash, Ord for CommandBuffer {
118 target = { command_buffer }
119 }
120}
121impl Drop for CommandBuffer {
122 fn drop(&mut self) {
123 let lock = self.command_buffer.lock().expect("vutex poisoned");
124 log_trace_common!("Dropping", self, lock);
125
126 unsafe { self.pool.free_command_buffers([*lock]) }
127 }
128}
129impl Debug for CommandBuffer {
130 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
131 f.debug_struct("CommandBuffer")
132 .field("pool", &self.pool)
133 .field("command_buffer", &self.command_buffer)
134 .finish()
135 }
136}