favilla/
cleanup_queue.rs

1use crate::cleanup::Cleanup;
2use ash::vk;
3
4///A queue for cleaning up resources. Deletion of resources will be delayed by N
5/// frames to avoid concurrency problems.
6/// N should be initialized with the number of frames that can be in flight at the same time.
7/// Supported resources are: ash::vk::Buffer and ash::vk::DeviceMemory.
8#[derive(Debug)]
9pub struct CleanupQueue {
10    frame_queue: Vec<QueuedFrame>,
11    current_frame_index: usize,
12}
13
14#[derive(Debug)]
15struct QueuedFrame {
16    buffers: Vec<vk::Buffer>,
17    memory: Vec<vk::DeviceMemory>,
18}
19
20impl CleanupQueue {
21    pub fn new(num_frames: usize) -> Self {
22        Self {
23            frame_queue: (0..num_frames).map(|_| QueuedFrame::new()).collect(),
24            current_frame_index: 0,
25        }
26    }
27
28    fn num_frames(&self) -> usize {
29        self.frame_queue.len()
30    }
31
32    fn get_current_frame_index(&self) -> usize {
33        (self.current_frame_index + self.num_frames() - 1) % self.num_frames()
34    }
35
36    pub fn queue_buffer(&mut self, buffer: vk::Buffer) {
37        let current_frame_index = self.get_current_frame_index();
38        self.frame_queue[current_frame_index].push_buffer(buffer)
39    }
40
41    pub fn queue_memory(&mut self, memory: vk::DeviceMemory) {
42        let current_frame_index = self.get_current_frame_index();
43        self.frame_queue[current_frame_index].push_memory(memory)
44    }
45
46    pub fn queue(&mut self, resource: impl Cleanup) {
47        resource.queue(self);
48    }
49
50    /// Ticks the Cleanup Queue and deletes all resources that have been ticked `num_frames` times,
51    /// # Safety
52    /// Resources must be OK to free.
53    pub unsafe fn tick(&mut self, device: &ash::Device) {
54        let index = self.current_frame_index;
55
56        self.frame_queue[index].destroy(device);
57
58        self.current_frame_index = (self.current_frame_index + 1) % self.num_frames()
59    }
60
61    /// Cleans up all resources immediately.
62    /// # Safety
63    /// All resources must be OK to free.
64    pub unsafe fn destroy(&mut self, device: &ash::Device) {
65        for frame in &mut self.frame_queue {
66            frame.destroy(device);
67        }
68    }
69}
70
71impl QueuedFrame {
72    fn new() -> Self {
73        Self {
74            buffers: Vec::new(),
75            memory: Vec::new(),
76        }
77    }
78
79    fn push_buffer(&mut self, buffer: vk::Buffer) {
80        self.buffers.push(buffer);
81    }
82
83    fn push_memory(&mut self, memory: vk::DeviceMemory) {
84        self.memory.push(memory);
85    }
86
87    unsafe fn destroy(&mut self, device: &ash::Device) {
88        for buffer in &self.buffers {
89            device.destroy_buffer(*buffer, None);
90        }
91        self.buffers.clear();
92
93        for memory in &self.memory {
94            device.free_memory(*memory, None);
95        }
96        self.memory.clear();
97    }
98}