rafx_framework/render_features/
registry.rs1use 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
8pub type RenderFeatureIndex = u32;
10
11pub type RenderFeatureFlagIndex = u32;
13
14pub 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}