rendy_frame/
frame.rs

1//! Frame module docs.
2
3use crate::{command::Fence, factory::Factory};
4
5/// Fences collection.
6pub type Fences<B> = smallvec::SmallVec<[Fence<B>; 8]>;
7
8/// Single frame rendering task.
9/// Command buffers can be submitted as part of the `Frame`.
10#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
11#[allow(missing_copy_implementations)]
12pub struct Frame {
13    index: u64,
14}
15
16impl Frame {
17    /// Create frame with specific index.
18    pub fn with_index(index: u64) -> Self {
19        Frame { index }
20    }
21
22    /// Get frame index.
23    pub fn index(&self) -> u64 {
24        self.index
25    }
26}
27
28/// Proof that frame is complete.
29#[derive(Debug)]
30#[allow(missing_copy_implementations)]
31pub struct CompleteFrame {
32    index: u64,
33}
34
35impl CompleteFrame {
36    /// Get frame index.
37    pub fn index(&self) -> u64 {
38        self.index
39    }
40}
41
42/// Complete - next frame range.
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub struct FramesRange {
45    next: u64,
46    complete_upper_bound: u64,
47}
48
49impl FramesRange {
50    /// Check if given frame is.
51    pub fn is_complete(&self, frame: Frame) -> bool {
52        self.complete_upper_bound > frame.index
53    }
54
55    /// Check if given frame is.
56    pub fn complete(&self, frame: Frame) -> Option<CompleteFrame> {
57        if self.complete_upper_bound > frame.index {
58            Some(CompleteFrame { index: frame.index })
59        } else {
60            None
61        }
62    }
63
64    /// Get next frame
65    pub fn next(&self) -> Frame {
66        Frame { index: self.next }
67    }
68}
69
70/// Timeline of frames, complete, pending and next.
71#[derive(Debug)]
72pub struct Frames<B: rendy_core::hal::Backend> {
73    pending: std::collections::VecDeque<Fences<B>>,
74    next: u64,
75}
76
77impl<B> Frames<B>
78where
79    B: rendy_core::hal::Backend,
80{
81    /// Create new `Frames` instance.
82    pub fn new() -> Self {
83        Frames {
84            pending: Default::default(),
85            next: 0,
86        }
87    }
88
89    /// Get next frame reference.
90    pub fn next(&self) -> Frame {
91        Frame { index: self.next }
92    }
93
94    /// Advance to the next frame.
95    /// All fences of the next frame must be queued.
96    pub fn advance(&mut self, fences: Fences<B>) {
97        assert!(fences.iter().all(Fence::is_submitted));
98        self.pending.push_back(fences);
99        self.next += 1;
100    }
101
102    /// Get upper bound of complete frames.
103    /// All frames with index less than result of this function are complete.
104    pub fn complete_upper_bound(&self) -> u64 {
105        debug_assert!(self.pending.len() as u64 <= self.next);
106        self.next - self.pending.len() as u64
107    }
108
109    /// Check if given frame is.
110    pub fn is_complete(&self, frame: Frame) -> bool {
111        self.complete_upper_bound() > frame.index
112    }
113
114    /// Check if frame with specified index is complete.
115    pub fn complete(&self, frame: Frame) -> Option<CompleteFrame> {
116        if self.complete_upper_bound() > frame.index {
117            Some(CompleteFrame { index: frame.index })
118        } else {
119            None
120        }
121    }
122
123    /// Wait for completion of the frames until specified (inclusive)
124    /// Returns proof.
125    ///
126    /// # Parameters
127    ///
128    /// `target` - frame that must complete.
129    /// `factory` - The factory.
130    ///
131    /// # Panics
132    ///
133    /// This function will panic if `target` is greater than or equal to next frame.
134    pub fn wait_complete(
135        &mut self,
136        target: Frame,
137        factory: &Factory<B>,
138        free: impl FnMut(Fences<B>),
139    ) -> CompleteFrame {
140        assert!(target.index <= self.next);
141        if let Some(complete) = self.complete(target) {
142            complete
143        } else {
144            // n - p <= t
145            // p - n + t + 1 >= 1
146            // count >= 1
147            let count = self.pending.len() - (self.next - target.index - 1) as usize;
148            let ready = factory.wait_for_fences(
149                self.pending.iter_mut().take(count).flatten(),
150                rendy_core::hal::device::WaitFor::All,
151                !0,
152            );
153            assert_eq!(ready, Ok(true));
154            self.pending.drain(..count).for_each(free);
155            CompleteFrame {
156                index: target.index,
157            }
158        }
159    }
160
161    /// Dispose of the `Frames`
162    pub fn dispose(mut self, factory: &mut Factory<B>) {
163        let ready = factory.wait_for_fences(
164            self.pending.iter_mut().flatten(),
165            rendy_core::hal::device::WaitFor::All,
166            !0,
167        );
168        assert_eq!(ready, Ok(true));
169
170        self.pending
171            .drain(..)
172            .flatten()
173            .for_each(|fence| factory.destroy_fence(fence));
174    }
175
176    /// Get range of frame indices in this form:
177    /// `upper bound of finished frames .. next frame`.
178    pub fn range(&self) -> FramesRange {
179        FramesRange {
180            next: self.next,
181            complete_upper_bound: self.complete_upper_bound(),
182        }
183    }
184}