screen_13/driver/
cmd_buf.rs1use {
2 super::{DriverError, device::Device},
3 ash::vk,
4 log::{error, trace, warn},
5 std::{fmt::Debug, ops::Deref, sync::Arc, thread::panicking},
6};
7
8#[derive(Debug)]
13pub struct CommandBuffer {
14 cmd_buf: vk::CommandBuffer,
15 pub(crate) device: Arc<Device>,
16 droppables: Vec<Box<dyn Debug + Send + 'static>>,
17 pub(crate) fence: vk::Fence, pub info: CommandBufferInfo,
21
22 pub(crate) pool: vk::CommandPool,
23 pub(crate) waiting: bool,
24}
25
26impl CommandBuffer {
27 #[profiling::function]
28 pub(crate) fn create(
29 device: &Arc<Device>,
30 info: CommandBufferInfo,
31 ) -> Result<Self, DriverError> {
32 let device = Arc::clone(device);
33 let cmd_pool_info = vk::CommandPoolCreateInfo::default()
34 .flags(
35 vk::CommandPoolCreateFlags::TRANSIENT
36 | vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER,
37 )
38 .queue_family_index(info.queue_family_index);
39 let pool = unsafe {
40 device
41 .create_command_pool(&cmd_pool_info, None)
42 .map_err(|err| {
43 warn!("{err}");
44
45 DriverError::Unsupported
46 })?
47 };
48 let cmd_buf_info = vk::CommandBufferAllocateInfo::default()
49 .command_buffer_count(1)
50 .command_pool(pool)
51 .level(vk::CommandBufferLevel::PRIMARY);
52 let cmd_buf = unsafe {
53 device
54 .allocate_command_buffers(&cmd_buf_info)
55 .map_err(|err| {
56 warn!("{err}");
57
58 DriverError::Unsupported
59 })?
60 }[0];
61 let fence = Device::create_fence(&device, false)?;
62
63 Ok(Self {
64 cmd_buf,
65 device,
66 droppables: vec![],
67 fence,
68 info,
69 pool,
70 waiting: false,
71 })
72 }
73
74 #[profiling::function]
76 pub(crate) fn drop_fenced(this: &mut Self) {
77 if !this.droppables.is_empty() {
78 trace!("dropping {} shared references", this.droppables.len());
79 }
80
81 this.droppables.clear();
82 }
83
84 #[profiling::function]
88 pub fn has_executed(&self) -> Result<bool, DriverError> {
89 let res = unsafe { self.device.get_fence_status(self.fence) };
90
91 match res {
92 Ok(status) => Ok(status),
93 Err(err) if err == vk::Result::ERROR_DEVICE_LOST => {
94 error!("Device lost");
95
96 Err(DriverError::InvalidData)
97 }
98 Err(err) => {
99 error!("{}", err);
102
103 Err(DriverError::InvalidData)
104 }
105 }
106 }
107
108 pub(crate) fn push_fenced_drop(this: &mut Self, thing_to_drop: impl Debug + Send + 'static) {
110 this.droppables.push(Box::new(thing_to_drop));
111 }
112
113 #[profiling::function]
118 pub fn wait_until_executed(&mut self) -> Result<(), DriverError> {
119 if !self.waiting {
120 return Ok(());
121 }
122
123 Device::wait_for_fence(&self.device, &self.fence)?;
124 self.waiting = false;
125
126 Ok(())
127 }
128}
129
130impl Deref for CommandBuffer {
131 type Target = vk::CommandBuffer;
132
133 fn deref(&self) -> &Self::Target {
134 &self.cmd_buf
135 }
136}
137
138impl Drop for CommandBuffer {
139 #[profiling::function]
140 fn drop(&mut self) {
141 use std::slice::from_ref;
142
143 if panicking() {
144 return;
145 }
146
147 unsafe {
148 if self.waiting && Device::wait_for_fence(&self.device, &self.fence).is_err() {
149 return;
150 }
151
152 Self::drop_fenced(self);
153
154 self.device
155 .free_command_buffers(self.pool, from_ref(&self.cmd_buf));
156 self.device.destroy_command_pool(self.pool, None);
157 self.device.destroy_fence(self.fence, None);
158 }
159 }
160}
161
162#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
163pub struct CommandBufferInfo {
164 pub queue_family_index: u32,
165}
166
167impl CommandBufferInfo {
168 pub fn new(queue_family_index: u32) -> Self {
169 Self { queue_family_index }
170 }
171}