rafx_framework/render_features/
render_objects.rs

1use crate::render_features::render_features_prelude::*;
2use rafx_base::slab::{DropSlab, GenericDropSlabKey, RawSlabKey, SlabIndexT};
3use std::cmp::Ordering;
4use std::hash::{Hash, Hasher};
5use std::marker::PhantomData;
6use std::sync::Arc;
7
8pub type RenderObjectsMap<RenderObjectStaticDataT> =
9    RenderObjectSetStorage<RenderObjectStaticDataT>;
10
11pub type RenderObjectCount = u32;
12
13type RenderObjectSetKey = GenericDropSlabKey;
14
15/// A reference to a `RenderObject` with a reference-counted pointer. When the last instance of
16/// a `RenderObjectHandle` is dropped, the referenced `RenderObject` will be freed from the
17/// `RenderObjectSet`. This is returned by `register_render_object` on the `RenderObjectSet`
18/// and may be used to query or mutate the `RenderObject` with the `get` or `get_mut` methods.
19#[derive(Clone, Debug)]
20pub struct RenderObjectHandle {
21    render_feature_index: RenderFeatureIndex,
22    render_object_set_key: RenderObjectSetKey,
23}
24
25/// A weak `RenderObjectHandle`. This is a reference to a `RenderObject` that is not used in
26/// reference-counting by the `RenderObjectSet`. Create a `RenderObjectId` with the `as_id()`
27/// method on a `RenderObjectHandle`. The `RenderObject` can be queried with the `get_id` method on
28/// the `RenderObjectSet`.
29#[derive(Copy, Eq, PartialEq, Hash, Clone, Debug)]
30pub struct RenderObjectId {
31    render_feature_index: RenderFeatureIndex,
32    render_object_set_index: SlabIndexT,
33}
34
35impl Ord for RenderObjectId {
36    fn cmp(
37        &self,
38        other: &Self,
39    ) -> Ordering {
40        self.render_feature_index
41            .cmp(&other.render_feature_index)
42            .then(
43                self.render_object_set_index
44                    .cmp(&other.render_object_set_index),
45            )
46    }
47}
48
49impl PartialOrd for RenderObjectId {
50    fn partial_cmp(
51        &self,
52        other: &Self,
53    ) -> Option<Ordering> {
54        Some(self.cmp(other))
55    }
56}
57
58impl Default for RenderObjectId {
59    fn default() -> Self {
60        Self {
61            render_feature_index: RenderFeatureIndex::MAX,
62            render_object_set_index: SlabIndexT::MAX,
63        }
64    }
65}
66
67impl Eq for RenderObjectHandle {}
68
69impl PartialEq for RenderObjectHandle {
70    fn eq(
71        &self,
72        other: &Self,
73    ) -> bool {
74        self.render_feature_index == other.render_feature_index
75            && self.render_object_set_key.index() == other.render_object_set_key.index()
76    }
77}
78
79impl Hash for RenderObjectHandle {
80    fn hash<H: Hasher>(
81        &self,
82        state: &mut H,
83    ) {
84        self.render_feature_index.hash(state);
85        self.render_object_set_key.index().hash(state);
86    }
87}
88
89impl RenderObjectHandle {
90    fn new(
91        render_feature_index: RenderFeatureIndex,
92        render_object_id: RenderObjectSetKey,
93    ) -> Self {
94        RenderObjectHandle {
95            render_feature_index,
96            render_object_set_key: render_object_id,
97        }
98    }
99
100    pub fn render_feature_index(&self) -> RenderFeatureIndex {
101        self.render_feature_index
102    }
103
104    pub fn as_id(&self) -> RenderObjectId {
105        RenderObjectId {
106            render_feature_index: self.render_feature_index,
107            render_object_set_index: self.render_object_set_key.index(),
108        }
109    }
110}
111
112impl RenderObjectId {
113    #[inline(always)]
114    pub fn render_feature_index(&self) -> RenderFeatureIndex {
115        self.render_feature_index
116    }
117}
118
119pub struct RenderObjectSet<RenderFeatureT: RenderFeature, RenderObjectStaticDataT> {
120    storage: Arc<RwLock<RenderObjectsMap<RenderObjectStaticDataT>>>,
121    _phantom: PhantomData<RenderFeatureT>,
122}
123
124impl<RenderFeatureT: RenderFeature, RenderObjectStaticDataT> Clone
125    for RenderObjectSet<RenderFeatureT, RenderObjectStaticDataT>
126{
127    fn clone(&self) -> Self {
128        Self {
129            storage: self.storage.clone(),
130            _phantom: Default::default(),
131        }
132    }
133}
134
135impl<RenderFeatureT: RenderFeature, RenderObjectStaticDataT>
136    RenderObjectSet<RenderFeatureT, RenderObjectStaticDataT>
137{
138    pub fn new() -> Self {
139        Self {
140            storage: Arc::new(RwLock::new(RenderObjectSetStorage::new())),
141            _phantom: Default::default(),
142        }
143    }
144
145    pub fn register_render_object(
146        &mut self,
147        render_object: RenderObjectStaticDataT,
148    ) -> RenderObjectHandle {
149        let render_object_handle = {
150            let mut render_objects = self.write();
151            render_objects.register_render_object(RenderFeatureT::feature_index(), render_object)
152        };
153
154        render_object_handle
155    }
156
157    pub fn read(&self) -> RwLockReadGuard<RenderObjectsMap<RenderObjectStaticDataT>> {
158        let registry = &self.storage;
159        registry.try_read().unwrap_or_else(move || {
160            log::warn!(
161                "{} is being written by another thread.",
162                std::any::type_name::<RenderObjectsMap<RenderObjectStaticDataT>>()
163            );
164
165            registry.read()
166        })
167    }
168
169    fn write(&mut self) -> RwLockWriteGuard<RenderObjectsMap<RenderObjectStaticDataT>> {
170        let registry = &self.storage;
171        registry.try_write().unwrap_or_else(move || {
172            log::warn!(
173                "{} is being read or written by another thread.",
174                std::any::type_name::<RenderObjectsMap<RenderObjectStaticDataT>>()
175            );
176
177            registry.write()
178        })
179    }
180
181    #[allow(dead_code)]
182    fn feature_index(&self) -> RenderFeatureIndex {
183        RenderFeatureT::feature_index()
184    }
185}
186
187impl<RenderFeatureT: RenderFeature, RenderObjectStaticDataT> Default
188    for RenderObjectSet<RenderFeatureT, RenderObjectStaticDataT>
189{
190    fn default() -> Self {
191        Self::new()
192    }
193}
194
195pub struct RenderObjectSetStorage<RenderObjectStaticDataT> {
196    inner: DropSlab<RenderObjectStaticDataT>,
197}
198
199impl<RenderObjectStaticDataT> RenderObjectSetStorage<RenderObjectStaticDataT> {
200    pub fn new() -> Self {
201        Self {
202            inner: Default::default(),
203        }
204    }
205
206    pub fn len(&self) -> RenderObjectCount {
207        self.inner.allocated_count() as RenderObjectCount
208    }
209
210    pub fn register_render_object(
211        &mut self,
212        feature_index: RenderFeatureIndex,
213        render_object: RenderObjectStaticDataT,
214    ) -> RenderObjectHandle {
215        self.inner.process_drops();
216
217        let drop_slab_key = self.inner.allocate(render_object);
218        RenderObjectHandle::new(feature_index, drop_slab_key.generic_drop_slab_key())
219    }
220
221    pub fn get_id(
222        &self,
223        render_object: &RenderObjectId,
224    ) -> &RenderObjectStaticDataT {
225        let raw_slab_key =
226            RawSlabKey::<RenderObjectStaticDataT>::new(render_object.render_object_set_index);
227
228        self.inner.get_raw(raw_slab_key).unwrap_or_else(|| {
229            panic!(
230                "{} did not contain id {:?}.",
231                std::any::type_name::<RenderObjectsMap<RenderObjectStaticDataT>>(),
232                render_object
233            )
234        })
235    }
236
237    pub fn get(
238        &self,
239        render_object: &RenderObjectHandle,
240    ) -> &RenderObjectStaticDataT {
241        self.inner
242            .get(&render_object.render_object_set_key.drop_slab_key())
243            .unwrap_or_else(|| {
244                panic!(
245                    "{} did not contain handle {:?}.",
246                    std::any::type_name::<RenderObjectsMap<RenderObjectStaticDataT>>(),
247                    render_object
248                )
249            })
250    }
251
252    pub fn get_mut(
253        &mut self,
254        render_object: &RenderObjectHandle,
255    ) -> &mut RenderObjectStaticDataT {
256        self.inner
257            .get_mut(&render_object.render_object_set_key.drop_slab_key())
258            .unwrap_or_else(|| {
259                panic!(
260                    "{} did not contain handle {:?}.",
261                    std::any::type_name::<RenderObjectsMap<RenderObjectStaticDataT>>(),
262                    render_object
263                )
264            })
265    }
266}
267
268impl<RenderObjectStaticDataT> Default for RenderObjectSetStorage<RenderObjectStaticDataT> {
269    fn default() -> Self {
270        Self::new()
271    }
272}