1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use crate::SubmitNode; use fnv::FnvHashMap; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering; use std::sync::Arc; pub type RenderFeatureIndex = u32; pub type RenderFeatureCount = u32; pub type RenderPhaseIndex = u32; pub type RenderPhaseMaskInnerType = u32; pub const MAX_RENDER_PHASE_COUNT: u32 = 32; pub trait RenderFeature { fn set_feature_index(index: RenderFeatureIndex); fn feature_index() -> RenderFeatureIndex; fn feature_debug_name() -> &'static str; } pub trait RenderPhase { fn set_render_phase_index(index: RenderPhaseIndex); fn render_phase_index() -> RenderPhaseIndex; fn sort_submit_nodes(submit_nodes: Vec<SubmitNode>) -> Vec<SubmitNode>; fn render_phase_debug_name() -> &'static str; } type SortCallback = fn(Vec<SubmitNode>) -> Vec<SubmitNode>; pub struct RegisteredPhase { sort_submit_nodes_callback: SortCallback, } impl RegisteredPhase { fn new<T: RenderPhase>() -> Self { RegisteredPhase { sort_submit_nodes_callback: T::sort_submit_nodes, } } } static RENDER_REGISTRY_FEATURE_COUNT: AtomicU32 = AtomicU32::new(0); static RENDER_REGISTRY_PHASE_COUNT: AtomicU32 = AtomicU32::new(0); #[derive(Default)] pub struct RenderRegistryBuilder { registered_phases: FnvHashMap<RenderPhaseIndex, RegisteredPhase>, phase_name_to_index: FnvHashMap<String, RenderPhaseIndex>, } impl RenderRegistryBuilder { pub fn register_feature<T>(self) -> Self where T: RenderFeature, { let feature_index = RENDER_REGISTRY_FEATURE_COUNT.fetch_add(1, Ordering::AcqRel); T::set_feature_index(feature_index); self } pub fn register_render_phase<T>( mut self, name: &str, ) -> Self where T: RenderPhase, { let render_phase_index = RENDER_REGISTRY_PHASE_COUNT.fetch_add(1, Ordering::AcqRel); assert!(render_phase_index < MAX_RENDER_PHASE_COUNT); T::set_render_phase_index(render_phase_index); let old = self .registered_phases .insert(T::render_phase_index(), RegisteredPhase::new::<T>()); assert!(old.is_none()); let old = self .phase_name_to_index .insert(name.to_string(), render_phase_index); assert!(old.is_none()); self } pub fn build(self) -> RenderRegistry { let inner = RenderRegistryInner { registered_phases: self.registered_phases, phase_name_to_index: self.phase_name_to_index, }; RenderRegistry { inner: Arc::new(inner), } } } struct RenderRegistryInner { registered_phases: FnvHashMap<RenderPhaseIndex, RegisteredPhase>, phase_name_to_index: FnvHashMap<String, RenderPhaseIndex>, } #[derive(Clone)] pub struct RenderRegistry { inner: Arc<RenderRegistryInner>, } impl RenderRegistry { pub fn registered_feature_count() -> RenderFeatureIndex { RENDER_REGISTRY_FEATURE_COUNT.load(Ordering::Acquire) } pub fn registered_render_phase_count() -> RenderPhaseIndex { RENDER_REGISTRY_PHASE_COUNT.load(Ordering::Acquire) } pub fn render_phase_index_from_name( &self, name: &str, ) -> Option<RenderPhaseIndex> { self.inner.phase_name_to_index.get(name).copied() } pub fn sort_submit_nodes( &self, render_phase_index: RenderPhaseIndex, submit_nodes: Vec<SubmitNode>, ) -> Vec<SubmitNode> { (self.inner.registered_phases[&render_phase_index].sort_submit_nodes_callback)(submit_nodes) } }