use crate::{command::Fence, factory::Factory};
pub type Fences<B> = smallvec::SmallVec<[Fence<B>; 8]>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(missing_copy_implementations)]
pub struct Frame {
index: u64,
}
impl Frame {
pub fn with_index(index: u64) -> Self {
Frame { index }
}
pub fn index(&self) -> u64 {
self.index
}
}
#[derive(Debug)]
#[allow(missing_copy_implementations)]
pub struct CompleteFrame {
index: u64,
}
impl CompleteFrame {
pub fn index(&self) -> u64 {
self.index
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FramesRange {
next: u64,
complete_upper_bound: u64,
}
impl FramesRange {
pub fn is_complete(&self, frame: Frame) -> bool {
self.complete_upper_bound > frame.index
}
pub fn complete(&self, frame: Frame) -> Option<CompleteFrame> {
if self.complete_upper_bound > frame.index {
Some(CompleteFrame { index: frame.index })
} else {
None
}
}
pub fn next(&self) -> Frame {
Frame { index: self.next }
}
}
#[derive(Debug)]
pub struct Frames<B: rendy_core::hal::Backend> {
pending: std::collections::VecDeque<Fences<B>>,
next: u64,
}
impl<B> Frames<B>
where
B: rendy_core::hal::Backend,
{
pub fn new() -> Self {
Frames {
pending: Default::default(),
next: 0,
}
}
pub fn next(&self) -> Frame {
Frame { index: self.next }
}
pub fn advance(&mut self, fences: Fences<B>) {
assert!(fences.iter().all(Fence::is_submitted));
self.pending.push_back(fences);
self.next += 1;
}
pub fn complete_upper_bound(&self) -> u64 {
debug_assert!(self.pending.len() as u64 <= self.next);
self.next - self.pending.len() as u64
}
pub fn is_complete(&self, frame: Frame) -> bool {
self.complete_upper_bound() > frame.index
}
pub fn complete(&self, frame: Frame) -> Option<CompleteFrame> {
if self.complete_upper_bound() > frame.index {
Some(CompleteFrame { index: frame.index })
} else {
None
}
}
pub fn wait_complete(
&mut self,
target: Frame,
factory: &Factory<B>,
free: impl FnMut(Fences<B>),
) -> CompleteFrame {
assert!(target.index <= self.next);
if let Some(complete) = self.complete(target) {
complete
} else {
let count = self.pending.len() - (self.next - target.index - 1) as usize;
let ready = factory.wait_for_fences(
self.pending.iter_mut().take(count).flatten(),
rendy_core::hal::device::WaitFor::All,
!0,
);
assert_eq!(ready, Ok(true));
self.pending.drain(..count).for_each(free);
CompleteFrame {
index: target.index,
}
}
}
pub fn dispose(mut self, factory: &mut Factory<B>) {
let ready = factory.wait_for_fences(
self.pending.iter_mut().flatten(),
rendy_core::hal::device::WaitFor::All,
!0,
);
assert_eq!(ready, Ok(true));
self.pending
.drain(..)
.flatten()
.for_each(|fence| factory.destroy_fence(fence));
}
pub fn range(&self) -> FramesRange {
FramesRange {
next: self.next,
complete_upper_bound: self.complete_upper_bound(),
}
}
}