rafx_framework/render_features/
registry.rs

1use super::RenderFeatureSubmitNode;
2use crate::render_features::SubmitNodeSortFunction;
3use fnv::FnvHashMap;
4use std::sync::atomic::AtomicU32;
5use std::sync::atomic::Ordering;
6use std::sync::Arc;
7
8/// The `ID` of a registered `RenderFeature`.
9pub type RenderFeatureIndex = u32;
10
11/// The `ID` of a registered `RenderFeatureFlag`.
12pub type RenderFeatureFlagIndex = u32;
13
14/// The `ID` of a registered `RenderPhase`.
15pub type RenderPhaseIndex = u32;
16
17pub type RenderFeatureMaskInnerType = u64;
18pub const MAX_RENDER_FEATURE_COUNT: u32 = 64;
19
20pub type RenderFeatureFlagMaskInnerType = u128;
21pub const MAX_RENDER_FEATURE_FLAG_COUNT: u32 = 128;
22
23pub type RenderPhaseMaskInnerType = u32;
24pub const MAX_RENDER_PHASE_COUNT: u32 = 32;
25
26pub struct RenderFeatureDebugConstants {
27    pub feature_name: &'static str,
28
29    pub begin_per_frame_extract: &'static str,
30    pub extract_render_object_instance: &'static str,
31    pub extract_render_object_instance_per_view: &'static str,
32    pub end_per_view_extract: &'static str,
33    pub end_per_frame_extract: &'static str,
34
35    pub begin_per_frame_prepare: &'static str,
36    pub prepare_render_object_instance: &'static str,
37    pub prepare_render_object_instance_per_view: &'static str,
38    pub end_per_view_prepare: &'static str,
39    pub end_per_frame_prepare: &'static str,
40
41    pub on_begin_execute_graph: &'static str,
42    pub render_submit_node: &'static str,
43    pub begin_submit_node_batch: &'static str,
44}
45
46pub trait RenderFeature {
47    fn set_feature_index(index: RenderFeatureIndex);
48    fn feature_index() -> RenderFeatureIndex;
49
50    fn feature_debug_name() -> &'static str;
51    fn feature_debug_constants() -> &'static RenderFeatureDebugConstants;
52}
53
54pub trait RenderFeatureFlag {
55    fn set_feature_flag_index(index: RenderFeatureIndex);
56    fn feature_flag_index() -> RenderFeatureIndex;
57
58    fn feature_flag_debug_name() -> &'static str;
59}
60
61pub trait RenderPhase {
62    fn set_render_phase_index(index: RenderPhaseIndex);
63    fn render_phase_index() -> RenderPhaseIndex;
64
65    fn sort_submit_nodes(submit_nodes: &mut Vec<RenderFeatureSubmitNode>);
66
67    fn render_phase_debug_name() -> &'static str;
68}
69
70pub struct RegisteredPhase {
71    sort_submit_nodes_callback: SubmitNodeSortFunction,
72}
73
74impl RegisteredPhase {
75    fn new<T: RenderPhase>() -> Self {
76        RegisteredPhase {
77            sort_submit_nodes_callback: T::sort_submit_nodes,
78        }
79    }
80}
81
82static RENDER_REGISTRY_FEATURE_COUNT: AtomicU32 = AtomicU32::new(0);
83static RENDER_REGISTRY_FEATURE_FLAG_COUNT: AtomicU32 = AtomicU32::new(0);
84static RENDER_REGISTRY_PHASE_COUNT: AtomicU32 = AtomicU32::new(0);
85
86#[derive(Default)]
87pub struct RenderRegistryBuilder {
88    registered_phases: FnvHashMap<RenderPhaseIndex, RegisteredPhase>,
89    phase_name_to_index: FnvHashMap<String, RenderPhaseIndex>,
90}
91
92impl RenderRegistryBuilder {
93    pub fn register_feature<T>(self) -> Self
94    where
95        T: RenderFeature,
96    {
97        let feature_index = RENDER_REGISTRY_FEATURE_COUNT.fetch_add(1, Ordering::AcqRel);
98        T::set_feature_index(feature_index);
99        self
100    }
101
102    pub fn register_feature_flag<T>(self) -> Self
103    where
104        T: RenderFeatureFlag,
105    {
106        let feature_flag_index = RENDER_REGISTRY_FEATURE_FLAG_COUNT.fetch_add(1, Ordering::AcqRel);
107        T::set_feature_flag_index(feature_flag_index);
108        self
109    }
110
111    pub fn register_render_phase<T>(
112        mut self,
113        name: &str,
114    ) -> Self
115    where
116        T: RenderPhase,
117    {
118        let render_phase_index = RENDER_REGISTRY_PHASE_COUNT.fetch_add(1, Ordering::AcqRel);
119        assert!(render_phase_index < MAX_RENDER_PHASE_COUNT);
120        T::set_render_phase_index(render_phase_index);
121        let old = self
122            .registered_phases
123            .insert(T::render_phase_index(), RegisteredPhase::new::<T>());
124        assert!(old.is_none());
125        let old = self
126            .phase_name_to_index
127            .insert(name.to_string(), render_phase_index);
128        assert!(old.is_none());
129        self
130    }
131
132    pub fn build(self) -> RenderRegistry {
133        let inner = RenderRegistryInner {
134            registered_phases: self.registered_phases,
135            phase_name_to_index: self.phase_name_to_index,
136        };
137
138        RenderRegistry {
139            inner: Arc::new(inner),
140        }
141    }
142}
143
144struct RenderRegistryInner {
145    registered_phases: FnvHashMap<RenderPhaseIndex, RegisteredPhase>,
146    phase_name_to_index: FnvHashMap<String, RenderPhaseIndex>,
147}
148
149#[derive(Clone)]
150pub struct RenderRegistry {
151    inner: Arc<RenderRegistryInner>,
152}
153
154impl RenderRegistry {
155    pub fn registered_feature_count() -> RenderFeatureIndex {
156        RENDER_REGISTRY_FEATURE_COUNT.load(Ordering::Acquire)
157    }
158
159    pub fn registered_render_phase_count() -> RenderPhaseIndex {
160        RENDER_REGISTRY_PHASE_COUNT.load(Ordering::Acquire)
161    }
162
163    pub fn render_phase_index_from_name(
164        &self,
165        name: &str,
166    ) -> Option<RenderPhaseIndex> {
167        self.inner.phase_name_to_index.get(name).copied()
168    }
169
170    pub fn submit_node_sort_function(
171        &self,
172        render_phase_index: RenderPhaseIndex,
173    ) -> SubmitNodeSortFunction {
174        self.inner.registered_phases[&render_phase_index].sort_submit_nodes_callback
175    }
176}