rafx_framework/render_features/jobs/extract/
frame_packet.rs

1use crate::render_features::render_features_prelude::*;
2use crate::visibility::VisibilityObjectId;
3use fnv::{FnvHashMap, FnvHasher};
4use std::hash::{BuildHasherDefault, Hash};
5
6/// The `FramePacket` is the data that must be extracted from either the `AssetManager` or the game's
7/// `World` during the `Extract` step. After the `Extract` step has finished, there is no more access
8/// allowed to either the `AssetManager` or the game's `World`. The `FramePacket` **must** be considered
9/// immutable after the `Extract` step has finished.
10pub trait FramePacketData {
11    /// All data that is either unassociated with or shared by
12    /// any of the render objects across each `RenderView`.
13    type PerFrameData: Sync + Send;
14
15    /// All data associated with a particular `Entity` and `RenderObject`.
16    type RenderObjectInstanceData: Sync + Send;
17
18    /// All data that is associated with a particular `RenderView`.
19    /// This and a `Vec`<`RenderObjectInstancePerViewData`> define
20    /// each `ViewPacket` in the `FramePacket`.
21    type PerViewData: Sync + Send;
22
23    /// All data associated with a particular `Entity`, `RenderObject`, and `RenderView`.
24    type RenderObjectInstancePerViewData: Sync + Send;
25
26    // TODO(dvd): see issue #29661 <https://github.com/rust-lang/rust/issues/29661> for more information
27    // type FramePacket = GenericFramePacket<Self>;
28    // type ViewPacket = GenericViewPacket<Self>;
29}
30
31/// Read documentation on `FramePacketData`.
32pub struct FramePacket<FramePacketDataT: FramePacketData> {
33    feature_index: RenderFeatureIndex,
34    render_object_instance_ids: FnvHashMap<RenderObjectInstance, RenderObjectInstanceId>,
35
36    pub(crate) per_frame_data: AtomicOnceCell<FramePacketDataT::PerFrameData>,
37    pub(crate) render_object_instances: Vec<RenderObjectInstance>,
38    pub(crate) render_object_instances_data:
39        AtomicOnceCellArray<FramePacketDataT::RenderObjectInstanceData>,
40
41    views: Vec<ViewPacket<FramePacketDataT>>,
42}
43
44impl<FramePacketDataT: FramePacketData> FramePacket<FramePacketDataT> {
45    pub fn new(
46        feature_index: RenderFeatureIndex,
47        frame_packet_size: &FramePacketSize,
48    ) -> Self {
49        // TODO(dvd): 3 + 2 * N allocations here -- the vec of views, the per frame entities vec, the entity indices hash map, and two vecs * N views for objects / volumes.
50        let mut views = Vec::with_capacity(frame_packet_size.view_packet_sizes.len());
51
52        for view_packet_size in frame_packet_size.view_packet_sizes.iter() {
53            let view_frame_index = views.len() as u32;
54            view_packet_size
55                .view
56                .set_view_frame_index(feature_index, view_frame_index);
57            views.push(ViewPacket::new(view_packet_size, view_frame_index));
58        }
59
60        Self {
61            feature_index,
62            per_frame_data: AtomicOnceCell::new(),
63            render_object_instances: Vec::with_capacity(
64                frame_packet_size.num_render_object_instances,
65            ),
66            render_object_instances_data: AtomicOnceCellArray::with_capacity(
67                frame_packet_size.num_render_object_instances,
68            ),
69            render_object_instance_ids: FnvHashMap::with_capacity_and_hasher(
70                frame_packet_size.num_render_object_instances,
71                BuildHasherDefault::<FnvHasher>::default(),
72            ),
73            views,
74        }
75    }
76
77    pub fn view_packets(&self) -> &Vec<ViewPacket<FramePacketDataT>> {
78        &self.views
79    }
80
81    pub fn view_packet(
82        &self,
83        view_index: ViewFrameIndex,
84    ) -> &ViewPacket<FramePacketDataT> {
85        self.views.get(view_index as usize).unwrap_or_else(|| {
86            panic!(
87                "ViewPacket with ViewFrameIndex {} was not found in {}.",
88                view_index,
89                std::any::type_name::<FramePacketDataT>()
90            )
91        })
92    }
93
94    pub fn view_packet_mut(
95        &mut self,
96        view_index: ViewFrameIndex,
97    ) -> &mut ViewPacket<FramePacketDataT> {
98        self.views.get_mut(view_index as usize).unwrap_or_else(|| {
99            panic!(
100                "ViewPacket with ViewFrameIndex {} was not found in {}.",
101                view_index,
102                std::any::type_name::<FramePacketDataT>()
103            )
104        })
105    }
106
107    pub fn render_object_instances(&self) -> &Vec<RenderObjectInstance> {
108        &self.render_object_instances
109    }
110
111    pub fn render_object_instances_data(
112        &self
113    ) -> &AtomicOnceCellArray<FramePacketDataT::RenderObjectInstanceData> {
114        &self.render_object_instances_data
115    }
116
117    pub fn per_frame_data(&self) -> &AtomicOnceCell<FramePacketDataT::PerFrameData> {
118        &self.per_frame_data
119    }
120}
121
122impl<FramePacketDataT: 'static + Sync + Send + FramePacketData> RenderFeatureFramePacket
123    for FramePacket<FramePacketDataT>
124{
125    fn get_or_push_render_object_instance(
126        &mut self,
127        render_object_instance: RenderObjectInstance,
128    ) -> RenderObjectInstanceId {
129        return if let Some(render_object_instance_id) =
130            self.render_object_instance_ids.get(&render_object_instance)
131        {
132            *render_object_instance_id
133        } else {
134            let render_object_instance_id =
135                self.render_object_instances.len() as RenderObjectInstanceId;
136
137            self.render_object_instances.push(render_object_instance);
138            self.render_object_instance_ids
139                .insert(render_object_instance, render_object_instance_id);
140
141            render_object_instance_id
142        };
143    }
144
145    fn render_feature_view_packet(
146        &self,
147        view_index: ViewFrameIndex,
148    ) -> &dyn RenderFeatureViewPacket {
149        self.view_packet(view_index)
150    }
151
152    fn render_feature_view_packet_mut(
153        &mut self,
154        view_index: u32,
155    ) -> &mut dyn RenderFeatureViewPacket {
156        self.view_packet_mut(view_index)
157    }
158
159    fn feature_index(&self) -> RenderFeatureIndex {
160        self.feature_index
161    }
162}
163
164/// A specific `Entity` and `RenderObject` represented by the `ObjectId` and `RenderObjectId`. A
165/// `RenderObject` is associated with a particular `RenderFeature` by the `RenderFeatureIndex`.
166/// The `FramePacket` only contains unique `RenderObjectInstance`s.
167#[derive(Copy, Eq, PartialEq, Hash, Clone, Debug)]
168pub struct RenderObjectInstance {
169    pub object_id: ObjectId,
170    pub render_object_id: RenderObjectId,
171    pub visibility_object_id: VisibilityObjectId,
172}
173
174impl RenderObjectInstance {
175    pub fn new(
176        object_id: ObjectId,
177        render_object_id: RenderObjectId,
178        visibility_object_id: VisibilityObjectId,
179    ) -> Self {
180        Self {
181            object_id,
182            render_object_id,
183            visibility_object_id,
184        }
185    }
186}