//! Definitions and containers for render 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. /// /// These variants are temporary and for testing purposes. #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] pub enum PrePhase { VertexSkinning, } /// The main viewport rendering phase group. /// /// These variants are temporary and for testing purposes. #[derive(Copy, Clone, Debug, Hash, Eq, Ord, PartialEq, PartialOrd, strum::EnumIter)] pub enum ViewportPhase { CullLights, CullPolys, ShadowRendering, Depth, DepthMips, AO, Opaque, Transparent, Bloom, Overlay, Composite, } /// 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(); } /// Inserts a [PrePhase]. pub fn insert_pre(&mut self, phase: PrePhase) { self.pre.push(phase); } /// Inserts a [ViewportPhase]. pub fn insert_viewport(&mut self, phase: ViewportPhase) { self.viewport.push(phase); } } /// 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() } } }