diff --git a/src/lib.rs b/src/lib.rs index f80e21b..a4d74e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,78 +1,12 @@ //! Cyborg is a high-performance, modern, experimental rendering engine written //! in Rust. -use std::collections::HashMap; use std::sync::{Arc, RwLock}; use strum::IntoEnumIterator; -#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] -pub enum PrePhase {} +pub mod phase; -#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] -pub enum ViewportPhase {} - -#[derive(Debug, Default)] -pub struct PhaseList { - pub pre: Vec, - pub viewport: Vec, -} - -impl PhaseList { - pub fn clear(&mut self) { - self.pre.clear(); - self.viewport.clear(); - } -} - -#[derive(Debug, Default)] -pub struct PhaseMultiMap { - pub pre: HashMap>, - pub viewport: HashMap>, -} - -impl PhaseMultiMap { - pub fn insert_multi(&mut self, keys: &PhaseList, val: T) { - for pre in keys.pre.iter() { - Self::insert(&mut self.pre, pre, val); - } - - for viewport in keys.viewport.iter() { - Self::insert(&mut self.viewport, viewport, val); - } - } - - pub fn iter_pre<'a>(&'a self, phase: &'a PrePhase) -> std::slice::Iter<'a, T> { - Self::iter(&self.pre, phase) - } - - pub fn iter_viewport<'a>(&'a self, phase: &'a ViewportPhase) -> std::slice::Iter<'a, T> { - Self::iter(&self.viewport, phase) - } - - fn insert(map: &mut HashMap>, key: &K, val: T) - where - K: std::hash::Hash + Eq + Copy, - { - if let Some(existing) = map.get_mut(key) { - if !existing.contains(&val) { - existing.push(val); - } - } else { - map.insert(*key, vec![val]); - } - } - - fn iter<'a, K>(map: &'a HashMap>, key: &'a K) -> std::slice::Iter<'a, T> - where - K: std::hash::Hash + Eq + Copy, - { - if let Some(vals) = map.get(key) { - vals.iter() - } else { - [].iter() - } - } -} +use phase::*; pub struct ViewportData; diff --git a/src/phase.rs b/src/phase.rs new file mode 100644 index 0000000..a985194 --- /dev/null +++ b/src/phase.rs @@ -0,0 +1,98 @@ +//! Definitions and containers for rendering phase identifiers. +//! +//! Rendering phases are organized into different groups, which represent +//! different kinds of external data becoming available as the frame progresses. +//! For example, OpenXR encourages applications to acquire its viewport poses +//! as late into the frame as possible, to maximize the accuracy of pose +//! prediction in the time before the frame is presented. +//! +//! The definitions in this module are meant to be expanded upon over time, so +//! the containers make heavy use of generics to abstract functionality across +//! different groups of phases. + +use std::collections::HashMap; + +/// The rendering pre-phase group; before viewport acquisition. +#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] +pub enum PrePhase {} + +/// The main viewport rendering phase group. +#[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] +pub enum ViewportPhase {} + +/// A container of phases of each group. +/// +/// Can be used with the [PhaseMultiMap] container to insert a value into +/// multiple phases at once. +#[derive(Debug, Default)] +pub struct PhaseList { + pre: Vec, + viewport: Vec, +} + +impl PhaseList { + /// Clears the list, removing all phases. + pub fn clear(&mut self) { + self.pre.clear(); + self.viewport.clear(); + } +} + +/// Maps phases of each group to sets of values. +/// +/// Used by the frame scheduler to organize which phases execute which render +/// passes. +#[derive(Debug, Default)] +pub struct PhaseMultiMap { + pre: HashMap>, + viewport: HashMap>, +} + +impl PhaseMultiMap { + /// Inserts a value into multiple phases at once, keyed with a [PhaseList]. + pub fn insert_multi(&mut self, keys: &PhaseList, val: T) { + for pre in keys.pre.iter() { + Self::insert(&mut self.pre, pre, val); + } + + for viewport in keys.viewport.iter() { + Self::insert(&mut self.viewport, viewport, val); + } + } + + /// Iterates over all values matching a [PrePhase]. + pub fn iter_pre<'a>(&'a self, phase: &'a PrePhase) -> std::slice::Iter<'a, T> { + Self::iter(&self.pre, phase) + } + + /// Iterates over all values matching a [ViewportPhase]. + pub fn iter_viewport<'a>(&'a self, phase: &'a ViewportPhase) -> std::slice::Iter<'a, T> { + Self::iter(&self.viewport, phase) + } + + /// Generic helper function for inserting a single value into a phase group map. + fn insert(map: &mut HashMap>, key: &K, val: T) + where + K: std::hash::Hash + Eq + Copy, + { + if let Some(existing) = map.get_mut(key) { + if !existing.contains(&val) { + existing.push(val); + } + } else { + map.insert(*key, vec![val]); + } + } + + /// Generic helper function that iterates over a group's phase, if available. + fn iter<'a, K>(map: &'a HashMap>, key: &'a K) -> std::slice::Iter<'a, T> + where + K: std::hash::Hash + Eq + Copy, + { + if let Some(vals) = map.get(key) { + vals.iter() + } else { + [].iter() + } + } +}