1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use {
super::{Device, DriverError, QueueFamily},
ash::vk,
log::{trace, warn},
std::{fmt::Debug, ops::Deref, sync::Arc, thread::panicking},
};
#[derive(Debug)]
pub struct CommandBuffer {
cmd_buf: vk::CommandBuffer,
pub device: Arc<Device>,
droppables: Vec<Box<dyn Debug + Send + 'static>>,
pub fence: vk::Fence,
pub pool: vk::CommandPool,
}
impl CommandBuffer {
pub fn create(device: &Arc<Device>, queue_family: QueueFamily) -> Result<Self, DriverError> {
let device = Arc::clone(device);
let cmd_pool_info = vk::CommandPoolCreateInfo::builder()
.flags(vk::CommandPoolCreateFlags::empty())
.queue_family_index(queue_family.idx);
let cmd_pool = unsafe {
device
.create_command_pool(&cmd_pool_info, None)
.map_err(|err| {
warn!("{err}");
DriverError::Unsupported
})?
};
let cmd_buf_info = vk::CommandBufferAllocateInfo::builder()
.command_buffer_count(1)
.command_pool(cmd_pool)
.level(vk::CommandBufferLevel::PRIMARY);
let cmd_buf = unsafe {
device
.allocate_command_buffers(&cmd_buf_info)
.map_err(|err| {
warn!("{err}");
DriverError::Unsupported
})?
}[0];
let fence = unsafe {
device
.create_fence(
&vk::FenceCreateInfo::builder()
.flags(vk::FenceCreateFlags::SIGNALED)
.build(),
None,
)
.map_err(|err| {
warn!("{err}");
DriverError::Unsupported
})?
};
Ok(Self {
cmd_buf,
device,
droppables: vec![],
fence,
pool: cmd_pool,
})
}
pub(crate) fn drop_fenced(this: &mut Self) {
if !this.droppables.is_empty() {
trace!("dropping {} shared references", this.droppables.len());
}
this.droppables.clear();
}
pub(crate) fn push_fenced_drop(this: &mut Self, thing_to_drop: impl Debug + Send + 'static) {
this.droppables.push(Box::new(thing_to_drop));
}
pub fn queue_family_index(this: &Self) -> u32 {
this.device.queue.family.idx
}
}
impl Deref for CommandBuffer {
type Target = vk::CommandBuffer;
fn deref(&self) -> &Self::Target {
&self.cmd_buf
}
}
impl Drop for CommandBuffer {
fn drop(&mut self) {
use std::slice::from_ref;
if panicking() {
return;
}
unsafe {
if Device::wait_for_fence(&self.device, &self.fence).is_err() {
return;
}
self.device
.free_command_buffers(self.pool, from_ref(&self.cmd_buf));
self.device.destroy_command_pool(self.pool, None);
self.device.destroy_fence(self.fence, None);
}
}
}