rafx_framework/render_features/jobs/prepare/
prepare_job.rs

1use crate::render_features::render_features_prelude::*;
2use std::marker::PhantomData;
3use std::ops::Range;
4
5/// A `PrepareJob` implements the `RenderFeaturePrepareJob` trait by wrapping an instance
6/// of an `PrepareJobEntryPoints` type defined at compile-time. The `PrepareJob` contains
7/// the frame & submit packets and presents the correct context (like `PreparePerFrameContext`)
8/// to each entry point defined in `RenderFeaturePrepareJob`.
9pub struct PrepareJob<'prepare, PrepareJobEntryPointsT: PrepareJobEntryPoints<'prepare>> {
10    inner: PrepareJobEntryPointsT,
11    prepare_context: RenderJobPrepareContext<'prepare>,
12    frame_packet: Option<Box<FramePacket<PrepareJobEntryPointsT::FramePacketDataT>>>,
13    submit_packet: Option<Box<SubmitPacket<PrepareJobEntryPointsT::SubmitPacketDataT>>>,
14    #[allow(dead_code)]
15    debug_constants: &'static RenderFeatureDebugConstants,
16    _phantom: (PhantomData<&'prepare ()>,),
17}
18
19impl<'prepare, PrepareJobEntryPointsT: 'prepare + PrepareJobEntryPoints<'prepare>>
20    PrepareJob<'prepare, PrepareJobEntryPointsT>
21{
22    pub fn new(
23        inner: PrepareJobEntryPointsT,
24        prepare_context: &RenderJobPrepareContext<'prepare>,
25        frame_packet: Box<FramePacket<PrepareJobEntryPointsT::FramePacketDataT>>,
26        submit_packet: Box<SubmitPacket<PrepareJobEntryPointsT::SubmitPacketDataT>>,
27    ) -> Self {
28        let debug_constants = inner.feature_debug_constants();
29        Self {
30            inner,
31            prepare_context: prepare_context.clone(),
32            frame_packet: Some(frame_packet),
33            submit_packet: Some(submit_packet),
34            debug_constants,
35            _phantom: Default::default(),
36        }
37    }
38
39    fn frame_packet(&self) -> &Option<Box<FramePacket<PrepareJobEntryPointsT::FramePacketDataT>>> {
40        &self.frame_packet
41    }
42
43    fn view_packets(&self) -> &Vec<ViewPacket<PrepareJobEntryPointsT::FramePacketDataT>> {
44        &self.frame_packet.as_ref().unwrap().view_packets()
45    }
46
47    fn render_object_instances(&self) -> &Vec<RenderObjectInstance> {
48        &self.frame_packet.as_ref().unwrap().render_object_instances
49    }
50
51    fn submit_packet(
52        &self
53    ) -> &Option<Box<SubmitPacket<PrepareJobEntryPointsT::SubmitPacketDataT>>> {
54        &self.submit_packet
55    }
56
57    fn force_to_prepare_lifetime(
58        &self,
59        inner: &PrepareJobEntryPointsT,
60    ) -> &'prepare PrepareJobEntryPointsT {
61        unsafe {
62            // SAFETY: The 'prepare lifetime added here is already required by the PrepareJobEntryPointsT.
63            // This transmute is just avoiding the need to proliferate even _more_ 'prepare lifetimes through
64            // _every single function_.
65            std::mem::transmute::<_, &'prepare PrepareJobEntryPointsT>(inner)
66        }
67    }
68}
69
70impl<'prepare, PrepareJobEntryPointsT: 'prepare + PrepareJobEntryPoints<'prepare>>
71    RenderFeaturePrepareJob<'prepare> for PrepareJob<'prepare, PrepareJobEntryPointsT>
72{
73    fn begin_per_frame_prepare(&self) {
74        profiling::scope!(self.debug_constants.begin_per_frame_prepare);
75
76        let context = PreparePerFrameContext::new(
77            &self.prepare_context,
78            self.frame_packet.as_ref().unwrap(),
79            self.submit_packet.as_ref().unwrap(),
80        );
81        self.inner.begin_per_frame_prepare(&context);
82    }
83
84    fn prepare_render_object_instance(
85        &self,
86        range: Range<usize>,
87    ) {
88        if range.is_empty() {
89            return;
90        }
91
92        let mut job_context = {
93            let inner = self.force_to_prepare_lifetime(&self.inner);
94            inner.new_render_object_instance_job_context()
95        };
96
97        if job_context.is_none() {
98            return;
99        }
100
101        profiling::scope!(self.debug_constants.prepare_render_object_instance);
102
103        let job_context = job_context.as_mut().unwrap();
104        let frame_packet = self.frame_packet.as_ref().unwrap();
105        let submit_packet = self.submit_packet.as_ref().unwrap();
106        for id in range {
107            let context = PrepareRenderObjectInstanceContext::new(
108                &self.prepare_context,
109                frame_packet,
110                submit_packet,
111                id,
112            );
113            self.inner
114                .prepare_render_object_instance(job_context, &context);
115        }
116    }
117
118    fn view_packet(
119        &self,
120        view_index: ViewFrameIndex,
121    ) -> &dyn RenderFeatureViewPacket {
122        self.frame_packet()
123            .as_ref()
124            .unwrap()
125            .render_feature_view_packet(view_index)
126    }
127
128    fn view_submit_packet(
129        &self,
130        view_index: ViewFrameIndex,
131    ) -> &dyn RenderFeatureViewSubmitPacket {
132        self.submit_packet()
133            .as_ref()
134            .unwrap()
135            .render_feature_view_submit_packet(view_index)
136    }
137
138    fn prepare_render_object_instance_per_view(
139        &self,
140        view_packet: &dyn RenderFeatureViewPacket,
141        view_submit_packet: &dyn RenderFeatureViewSubmitPacket,
142        range: Range<usize>,
143    ) {
144        if range.is_empty() {
145            return;
146        }
147
148        let mut job_context = {
149            let inner = self.force_to_prepare_lifetime(&self.inner);
150            inner.new_render_object_instance_per_view_job_context()
151        };
152
153        if job_context.is_none() {
154            return;
155        }
156
157        profiling::scope!(self.debug_constants.prepare_render_object_instance_per_view);
158
159        let job_context = job_context.as_mut().unwrap();
160        let frame_packet = self.frame_packet.as_ref().unwrap();
161        let submit_packet = self.submit_packet.as_ref().unwrap();
162
163        let view_packet: &ViewPacket<PrepareJobEntryPointsT::FramePacketDataT> =
164            view_packet.as_concrete();
165
166        let view_submit_packet: &ViewSubmitPacket<PrepareJobEntryPointsT::SubmitPacketDataT> =
167            view_submit_packet.as_concrete();
168
169        for id in range {
170            let context = PrepareRenderObjectInstancePerViewContext::new(
171                &self.prepare_context,
172                frame_packet,
173                submit_packet,
174                view_packet,
175                view_submit_packet,
176                id,
177            );
178            self.inner
179                .prepare_render_object_instance_per_view(job_context, &context);
180        }
181    }
182
183    fn end_per_view_prepare(
184        &self,
185        view_packet: &dyn RenderFeatureViewPacket,
186        view_submit_packet: &dyn RenderFeatureViewSubmitPacket,
187    ) {
188        profiling::scope!(self.debug_constants.end_per_view_prepare);
189
190        let view_packet: &ViewPacket<PrepareJobEntryPointsT::FramePacketDataT> =
191            view_packet.as_concrete();
192
193        let view_submit_packet: &ViewSubmitPacket<PrepareJobEntryPointsT::SubmitPacketDataT> =
194            view_submit_packet.as_concrete();
195
196        let context = PreparePerViewContext::new(
197            &self.prepare_context,
198            self.frame_packet.as_ref().unwrap(),
199            self.submit_packet.as_ref().unwrap(),
200            view_packet,
201            view_submit_packet,
202        );
203
204        self.inner.end_per_view_prepare(&context);
205    }
206
207    fn end_per_frame_prepare(&self) {
208        profiling::scope!(self.debug_constants.end_per_frame_prepare);
209
210        let context = PreparePerFrameContext::new(
211            &self.prepare_context,
212            self.frame_packet.as_ref().unwrap(),
213            self.submit_packet.as_ref().unwrap(),
214        );
215        self.inner.end_per_frame_prepare(&context);
216    }
217
218    fn num_views(&self) -> usize {
219        self.view_packets().len()
220    }
221
222    fn num_render_object_instances(&self) -> usize {
223        self.render_object_instances().len()
224    }
225
226    fn take_frame_packet(&mut self) -> Box<dyn RenderFeatureFramePacket> {
227        std::mem::take(&mut self.frame_packet).unwrap()
228    }
229
230    fn take_submit_packet(&mut self) -> Box<dyn RenderFeatureSubmitPacket> {
231        std::mem::take(&mut self.submit_packet).unwrap()
232    }
233
234    fn feature_debug_constants(&self) -> &'static RenderFeatureDebugConstants {
235        self.inner.feature_debug_constants()
236    }
237
238    fn feature_index(&self) -> RenderFeatureIndex {
239        self.inner.feature_index()
240    }
241}