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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use {
crate::graphics::{
vulkan_api::{raii, RenderDevice},
GraphicsError,
},
anyhow::Context,
ash::vk,
std::sync::Arc,
};
#[derive(Debug)]
pub(super) struct FrameSync {
pub(super) index: usize,
pub(super) command_pool: raii::CommandPool,
pub(super) swapchain_image_acquired_semaphore: raii::Semaphore,
pub(super) graphics_commands_completed_semaphore: raii::Semaphore,
pub(super) graphics_commands_completed_fence: raii::Fence,
render_device: Arc<RenderDevice>,
}
impl FrameSync {
pub unsafe fn new(
render_device: Arc<RenderDevice>,
index: usize,
) -> Result<Self, GraphicsError> {
let swapchain_image_acquired_semaphore = unsafe {
raii::Semaphore::new(
render_device.clone(),
&vk::SemaphoreCreateInfo::default(),
)?
};
swapchain_image_acquired_semaphore
.set_debug_name(format!("Frame {index} Swapchain Image Acquired"));
let graphics_commands_completed_semaphore = unsafe {
raii::Semaphore::new(
render_device.clone(),
&vk::SemaphoreCreateInfo::default(),
)?
};
graphics_commands_completed_semaphore.set_debug_name(format!(
"Frame {index} Graphics Commands Completed"
));
let graphics_commands_completed_fence = unsafe {
let create_info = vk::FenceCreateInfo {
flags: vk::FenceCreateFlags::SIGNALED,
..Default::default()
};
raii::Fence::new(render_device.clone(), &create_info)?
};
graphics_commands_completed_fence.set_debug_name(format!(
"Frame {index} Graphics Commands Completed"
));
let mut command_pool = unsafe {
let create_info = vk::CommandPoolCreateInfo {
flags: vk::CommandPoolCreateFlags::TRANSIENT,
..Default::default()
};
raii::CommandPool::new(render_device.clone(), &create_info)?
};
command_pool.set_debug_name(format!("Frame {index} Command Pool"));
let _ = command_pool.allocate_primary_command_buffers(1);
Ok(Self {
index,
command_pool,
swapchain_image_acquired_semaphore,
graphics_commands_completed_semaphore,
graphics_commands_completed_fence,
render_device,
})
}
pub fn wait_for_graphics_commands_to_complete(
&self,
) -> Result<(), GraphicsError> {
unsafe {
self.render_device
.device()
.wait_for_fences(
&[self.graphics_commands_completed_fence.raw()],
true,
u64::MAX,
)
.context(
"Error while waiting for graphics commands to complete",
)?
}
Ok(())
}
pub fn wait_and_restart_command_buffer(&self) -> Result<(), GraphicsError> {
self.wait_for_graphics_commands_to_complete()?;
unsafe {
self.render_device
.device()
.reset_fences(&[self.graphics_commands_completed_fence.raw()])
.with_context(|| {
format!(
"Could not reset graphics completed fence for frame {}",
self.index
)
})?;
self.render_device
.device()
.reset_command_pool(
self.command_pool.raw(),
vk::CommandPoolResetFlags::empty(),
)
.with_context(|| {
format!(
"Could not reset command pool for frame {}",
self.index
)
})?;
let begin_info = vk::CommandBufferBeginInfo {
flags: vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT,
..Default::default()
};
self.render_device
.device()
.begin_command_buffer(
self.command_pool.primary_command_buffer(0),
&begin_info,
)
.with_context(|| {
format!(
"Could not begin command buffer for frame {}",
self.index
)
})?;
}
Ok(())
}
}