1use rafx_assets::AssetManager;
2use rafx_assets::AssetManagerRenderResource;
3use rafx_assets::AssetResource;
4use rafx_assets::Handle;
5use rafx_framework::render_features::render_features_prelude::*;
6use rafx_framework::visibility::{VisibilityConfig, VisibilityResource};
7use rafx_framework::{ImageViewResource, ResourceArc};
8use rafx_framework::{RenderResources, ResourceLookupSet};
9use std::sync::{Arc, Mutex};
10use std::time::Duration;
11
12use super::*;
13
14use super::{RenderFeaturePlugin, RendererPipelinePlugin, ViewportsResource};
15use crate::main_view_render_resource::PreviousMainViewInfo;
16use rafx_api::extra::upload::{RafxTransferUpload, RafxUploadError};
17use rafx_api::{
18 RafxDeviceContext, RafxError, RafxPresentableFrame, RafxQueue, RafxResourceType, RafxResult,
19 RafxSwapchainHelper,
20};
21use rafx_framework::upload::image_upload::ImageUploadParams;
22use rafx_framework::upload::{image_upload, GpuImageData, GpuImageDataColorSpace};
23
24pub struct RendererLoadContext {
29 asset_plugins: Arc<Vec<Arc<dyn RendererAssetPlugin>>>,
30}
31
32impl RendererLoadContext {
33 pub fn wait_for_asset_to_load<T>(
34 &self,
35 render_resources: &RenderResources,
36 asset_manager: &mut AssetManager,
37 asset_handle: &Handle<T>,
38 asset_resource: &mut AssetResource,
39 asset_name: &str,
40 ) -> RafxResult<()> {
41 asset_manager.wait_for_asset_to_load(
42 asset_handle,
43 asset_resource,
44 asset_name,
45 |asset_manager, asset_resource| {
46 for plugin in &*self.asset_plugins {
47 plugin.process_asset_loading(
48 asset_manager,
49 asset_resource,
50 render_resources,
51 )?;
52 }
53
54 Ok(())
55 },
56 )
57 }
58}
59
60#[derive(Default, Copy, Clone, Debug)]
61pub struct RendererConfigResource {
62 pub visibility_config: VisibilityConfig,
63}
64
65#[derive(Clone)]
66pub struct InvalidResources {
67 pub invalid_image_color: ResourceArc<ImageViewResource>,
68 pub invalid_image_depth: ResourceArc<ImageViewResource>,
69 pub invalid_cube_map_image_color: ResourceArc<ImageViewResource>,
70 pub invalid_cube_map_image_depth: ResourceArc<ImageViewResource>,
71}
72
73pub struct RendererInner {
74 pub(super) temporary_work: RenderJobExtractAllocationContext,
76 pub(super) thread_pool: Box<dyn RendererThreadPool>,
77}
78
79pub struct Renderer {
80 pub(super) inner: Arc<Mutex<RendererInner>>,
81 pub(super) render_thread: Option<RenderThread>,
82 pub(super) pipeline_plugin: Arc<dyn RendererPipelinePlugin>,
83 pub(super) asset_plugins: Arc<Vec<Arc<dyn RendererAssetPlugin>>>,
84 pub(super) feature_plugins: Arc<Vec<Arc<dyn RenderFeaturePlugin>>>,
85 pub(super) render_resources: Arc<RenderResources>,
86 pub(super) graphics_queue: RafxQueue,
87 pub(super) transfer_queue: RafxQueue,
88}
89
90impl Drop for Renderer {
91 fn drop(&mut self) {
92 for plugin in &*self.feature_plugins {
93 plugin
94 .prepare_renderer_destroy(&self.render_resources)
95 .unwrap();
96 }
97
98 for plugin in &*self.asset_plugins {
99 plugin
100 .prepare_renderer_destroy(&self.render_resources)
101 .unwrap();
102 }
103
104 self.pipeline_plugin
105 .prepare_renderer_destroy(&self.render_resources)
106 .unwrap();
107 }
108}
109
110impl Renderer {
111 pub fn new(
112 extract_resources: ExtractResources,
113 mut render_resources: RenderResources,
114 asset_resource: &mut AssetResource,
115 asset_manager: &mut AssetManager,
116 graphics_queue: &RafxQueue,
117 transfer_queue: &RafxQueue,
118 feature_plugins: Vec<Arc<dyn RenderFeaturePlugin>>,
119 asset_plugins: Vec<Arc<dyn RendererAssetPlugin>>,
120 pipeline_plugin: Arc<dyn RendererPipelinePlugin>,
121 thread_pool: Box<dyn RendererThreadPool>,
122 allow_use_render_thread: bool,
123 ) -> RafxResult<Self> {
124 let asset_plugins = Arc::new(asset_plugins);
125 let feature_plugins = Arc::new(feature_plugins);
126
127 let device_context = graphics_queue.device_context();
128
129 let mut upload = RafxTransferUpload::new(
130 &device_context,
131 asset_manager.transfer_queue(),
132 asset_manager.graphics_queue(),
133 16 * 1024 * 1024,
134 None,
135 )?;
136
137 let invalid_image_color = Self::upload_image_data(
138 &device_context,
139 &mut upload,
140 &asset_manager.resources(),
141 &GpuImageData::new_1x1_rgba8(255, 0, 255, 255, GpuImageDataColorSpace::Linear),
142 ImageUploadParams::default(),
143 )
144 .map_err(|x| Into::<RafxError>::into(x))?;
145
146 let invalid_image_depth = Self::upload_image_data(
147 &device_context,
148 &mut upload,
149 &asset_manager.resources(),
150 &GpuImageData::new_1x1_d32(0.0),
151 ImageUploadParams::default(),
152 )
153 .map_err(|x| Into::<RafxError>::into(x))?;
154
155 let invalid_cube_map_image_color = Self::upload_image_data(
156 &device_context,
157 &mut upload,
158 &asset_manager.resources(),
159 &GpuImageData::new_1x1_rgba8(255, 0, 255, 255, GpuImageDataColorSpace::Linear),
160 ImageUploadParams {
161 generate_mips: false,
162 resource_type: RafxResourceType::TEXTURE_CUBE,
163 layer_swizzle: Some(&[0, 0, 0, 0, 0, 0]),
164 },
165 )
166 .map_err(|x| Into::<RafxError>::into(x))?;
167
168 let invalid_cube_map_image_depth = Self::upload_image_data(
169 &device_context,
170 &mut upload,
171 &asset_manager.resources(),
172 &GpuImageData::new_1x1_d32(0.0),
173 ImageUploadParams {
174 generate_mips: false,
175 resource_type: RafxResourceType::TEXTURE_CUBE,
176 layer_swizzle: Some(&[0, 0, 0, 0, 0, 0]),
177 },
178 )
179 .map_err(|x| Into::<RafxError>::into(x))?;
180
181 let invalid_resources = InvalidResources {
182 invalid_image_color,
183 invalid_image_depth,
184 invalid_cube_map_image_color,
185 invalid_cube_map_image_depth,
186 };
187
188 render_resources.insert(SwapchainRenderResource::default());
189 render_resources.insert(AssetManagerRenderResource::default());
190 render_resources.insert(TimeRenderResource::default());
191 render_resources.insert(MainViewRenderResource::default());
192
193 let load_context = RendererLoadContext {
194 asset_plugins: asset_plugins.clone(),
195 };
196
197 for plugin in &*asset_plugins {
198 plugin.initialize_static_resources(
199 &load_context,
200 asset_manager,
201 asset_resource,
202 &extract_resources,
203 &mut render_resources,
204 &mut upload,
205 )?;
206 }
207
208 for plugin in &*feature_plugins {
209 plugin.initialize_static_resources(
210 &load_context,
211 asset_manager,
212 asset_resource,
213 &extract_resources,
214 &mut render_resources,
215 &mut upload,
216 )?;
217 }
218
219 pipeline_plugin.initialize_static_resources(
220 &load_context,
221 asset_manager,
222 asset_resource,
223 &extract_resources,
224 &mut render_resources,
225 &mut upload,
226 )?;
227
228 render_resources.insert(invalid_resources.clone());
229
230 upload.block_until_upload_complete()?;
231
232 let use_render_thread =
233 allow_use_render_thread && device_context.device_info().supports_multithreaded_usage;
234 let render_thread = if use_render_thread {
235 Some(RenderThread::start())
236 } else {
237 None
238 };
239
240 let num_features = RenderRegistry::registered_feature_count() as usize;
241 let renderer = RendererInner {
242 thread_pool,
243 temporary_work: RenderJobExtractAllocationContext::new(num_features),
244 };
245
246 Ok(Renderer {
247 inner: Arc::new(Mutex::new(renderer)),
248 render_thread,
249 asset_plugins,
250 feature_plugins,
251 pipeline_plugin,
252 render_resources: Arc::new(render_resources),
253 graphics_queue: graphics_queue.clone(),
254 transfer_queue: transfer_queue.clone(),
255 })
256 }
257
258 pub fn load_context(&self) -> RendererLoadContext {
259 RendererLoadContext {
260 asset_plugins: self.asset_plugins.clone(),
261 }
262 }
263
264 pub fn wait_for_asset_to_load<T>(
265 &self,
266 asset_manager: &mut AssetManager,
267 asset_handle: &Handle<T>,
268 asset_resource: &mut AssetResource,
269 asset_name: &str,
270 ) -> RafxResult<()> {
271 self.load_context().wait_for_asset_to_load(
272 &*self.render_resources,
273 asset_manager,
274 asset_handle,
275 asset_resource,
276 asset_name,
277 )
278 }
279
280 pub fn clear_temporary_work(&mut self) {
281 let mut guard = self.inner.lock().unwrap();
282 let renderer_inner = &mut *guard;
283 renderer_inner.temporary_work.clear();
284 }
285
286 pub fn wait_for_render_thread_idle(&self) {
293 if let Some(render_thread) = &self.render_thread {
294 render_thread.wait_for_render_finish();
295 }
296 }
297
298 pub fn graphics_queue(&self) -> &RafxQueue {
299 &self.graphics_queue
300 }
301
302 pub fn transfer_queue(&self) -> &RafxQueue {
303 &self.transfer_queue
304 }
305
306 fn upload_image_data(
307 device_context: &RafxDeviceContext,
308 upload: &mut RafxTransferUpload,
309 resources: &ResourceLookupSet,
310 image_data: &GpuImageData,
311 params: ImageUploadParams,
312 ) -> Result<ResourceArc<ImageViewResource>, RafxUploadError> {
313 let texture = image_upload::enqueue_load_image(device_context, upload, image_data, params)?;
314
315 let image = resources.insert_image(texture);
316 Ok(resources.get_or_create_image_view(&image, None)?)
317 }
318
319 #[profiling::function]
322 pub fn start_rendering_next_frame(
323 &self,
324 extract_resources: &mut ExtractResources,
325 previous_update_time: Duration,
326 ) -> RafxResult<()> {
327 let t0 = rafx_base::Instant::now();
331
332 let presentable_frame = {
333 let viewports_resource = extract_resources.fetch::<ViewportsResource>();
334 let mut swapchain_helper = extract_resources.fetch_mut::<RafxSwapchainHelper>();
335 let mut asset_manager = extract_resources.fetch_mut::<AssetManager>();
336 SwapchainHandler::acquire_next_image(
337 &mut *swapchain_helper,
338 &mut *asset_manager,
339 self,
340 viewports_resource.main_window_size.width,
341 viewports_resource.main_window_size.height,
342 )
343 }?;
344
345 if let Some(render_thread) = &self.render_thread {
346 render_thread.wait_for_render_finish();
347 }
348
349 let t1 = rafx_base::Instant::now();
350 log::trace!(
351 "[main] wait for previous frame present {} ms",
352 (t1 - t0).as_secs_f32() * 1000.0
353 );
354
355 Self::create_and_start_render_job(
356 self,
357 extract_resources,
358 presentable_frame,
359 previous_update_time,
360 );
361
362 Ok(())
363 }
364
365 fn create_and_start_render_job(
366 renderer: &Renderer,
367 extract_resources: &mut ExtractResources,
368 presentable_frame: RafxPresentableFrame,
369 previous_update_time: Duration,
370 ) {
371 let result = Self::try_create_render_job(
372 &renderer,
373 extract_resources,
374 &presentable_frame,
375 previous_update_time,
376 );
377
378 match result {
379 Ok(prepared_frame) => {
380 if let Some(render_thread) = &renderer.render_thread {
381 render_thread.render(prepared_frame, presentable_frame);
382 } else {
383 prepared_frame.render_async(presentable_frame);
385 }
386 }
387 Err(e) => {
388 let graphics_queue = renderer.graphics_queue();
389 presentable_frame.present_with_error(graphics_queue, e)
390 }
391 };
392 }
393
394 fn try_create_render_job(
395 renderer: &Renderer,
396 extract_resources: &mut ExtractResources,
397 presentable_frame: &RafxPresentableFrame,
398 previous_update_time: Duration,
399 ) -> RafxResult<RenderFrameJob> {
400 let mut asset_manager_fetch = extract_resources.fetch_mut::<AssetManager>();
404 let asset_manager = &mut *asset_manager_fetch;
405
406 let render_registry = asset_manager.resource_manager().render_registry().clone();
407 let device_context = asset_manager.device_context().clone();
408
409 asset_manager.on_frame_complete()?;
413
414 {
418 let mut asset_resource = extract_resources.fetch_mut::<AssetResource>();
419 for plugin in &*renderer.asset_plugins {
420 plugin.process_asset_loading(
421 asset_manager,
422 &mut *asset_resource,
423 &renderer.render_resources,
424 )?;
425 }
426 }
427
428 let resource_context = asset_manager.resource_manager().resource_context();
429
430 let mut guard = renderer.inner.lock().unwrap();
431 let renderer_inner = &mut *guard;
432 let render_resources = &renderer.render_resources;
433
434 render_resources
435 .fetch_mut::<TimeRenderResource>()
436 .update(previous_update_time);
437
438 for plugin in &*renderer.asset_plugins {
439 plugin.on_frame_complete(asset_manager, extract_resources, &*render_resources)?;
440 }
441
442 let renderer_config = extract_resources
443 .try_fetch::<RendererConfigResource>()
444 .map(|x| *x)
445 .unwrap_or_default();
446
447 let swapchain_image = {
451 let swapchain_image = presentable_frame.swapchain_texture().clone();
455
456 let swapchain_image = resource_context.resources().insert_image(swapchain_image);
457
458 resource_context
459 .resources()
460 .get_or_create_image_view(&swapchain_image, None)?
461 };
462
463 let swapchain_guard = presentable_frame.swapchain().lock().unwrap();
464 let max_color_component_value = match &*swapchain_guard {
465 #[cfg(feature = "rafx-metal")]
466 rafx_api::RafxSwapchain::Metal(swapchain) => {
467 swapchain.edr_info().max_edr_color_component_value
468 }
469 #[allow(unreachable_patterns)]
470 _ => 1.0,
471 };
472
473 render_resources
474 .fetch_mut::<SwapchainRenderResource>()
475 .set_max_color_component_value(max_color_component_value);
476
477 let render_view_set = RenderViewSet::new(presentable_frame.incrementing_frame_index());
478
479 let viewports_resource = extract_resources.fetch::<ViewportsResource>();
484 let view_meta = viewports_resource.main_view_meta.clone().unwrap();
485
486 let main_window_size = viewports_resource.main_window_size;
487
488 let main_view = render_view_set.create_view(
489 view_meta.view_frustum,
490 view_meta.eye_position,
491 view_meta.view,
492 view_meta.proj,
493 (main_window_size.width, main_window_size.height),
494 view_meta.depth_range,
495 view_meta.render_phase_mask,
496 view_meta.render_feature_mask,
497 view_meta.render_feature_flag_mask,
498 view_meta.debug_name,
499 );
500 {
501 let mut main_view_render_resource =
502 render_resources.fetch_mut::<MainViewRenderResource>();
503
504 if let Some(main_view) = &main_view_render_resource.main_view {
505 main_view_render_resource.previous_main_view_info = Some(PreviousMainViewInfo {
506 view_matrix: main_view.view_matrix(),
507 projection_matrix: main_view.projection_matrix(),
508 });
509 }
510 main_view_render_resource.main_view = Some(main_view.clone());
511 }
512
513 let mut render_views = Vec::default();
518
519 {
520 profiling::scope!("Compute Views");
521 render_views.push(main_view.clone());
522 for plugin in &*renderer.feature_plugins {
523 plugin.add_render_views(
524 extract_resources,
525 render_resources,
526 &render_view_set,
527 &mut render_views,
528 );
529 }
530 }
531
532 asset_manager.on_begin_frame()?;
537
538 unsafe {
544 render_resources
545 .fetch_mut::<AssetManagerRenderResource>()
546 .begin_extract(&asset_manager);
547 }
548
549 let frame_packets = {
550 profiling::scope!("Renderer Extract");
551
552 let extract_context = RenderJobExtractContext::new(
553 &renderer_inner.temporary_work,
554 &extract_resources,
555 &render_resources,
556 &renderer_config.visibility_config,
557 );
558
559 let visibility_results = {
560 profiling::scope!("Calculate View Visibility");
561
562 {
563 let mut visibility_resource =
564 extract_resources.fetch_mut::<VisibilityResource>();
565 visibility_resource.update();
566 }
567
568 let visibility_resource = extract_resources.fetch::<VisibilityResource>();
569 let view_visibility_jobs =
570 Renderer::create_view_visibility_jobs(&render_views, &visibility_resource);
571
572 renderer_inner.thread_pool.run_view_visibility_jobs(
573 &view_visibility_jobs,
574 &extract_context,
575 &*visibility_resource,
576 )
577 };
578
579 {
580 profiling::scope!("Determine Frame Packet Sizes");
581 renderer_inner
582 .thread_pool
583 .count_render_features_render_objects(
584 &renderer.feature_plugins,
585 &extract_context,
586 &visibility_results,
587 );
588 }
589
590 {
591 profiling::scope!("Allocate Frame Packets");
592 Renderer::create_frame_packets(&renderer.feature_plugins, &extract_context);
593 }
594
595 let extract_jobs = {
596 profiling::scope!("Create Extract Jobs");
597 renderer_inner.thread_pool.create_extract_jobs(
598 &renderer.feature_plugins,
599 &extract_context,
600 visibility_results,
601 )
602 };
603
604 {
605 let visibility_resource = extract_resources.fetch::<VisibilityResource>();
606 profiling::scope!("Run Extract Jobs");
607 renderer_inner
608 .thread_pool
609 .run_extract_jobs(&extract_jobs, &*visibility_resource);
610 }
611
612 Renderer::take_frame_packets(extract_jobs)
613 };
614
615 render_resources
616 .fetch_mut::<AssetManagerRenderResource>()
617 .end_extract();
618
619 let prepared_render_graph = renderer.pipeline_plugin.generate_render_graph(
621 asset_manager,
622 swapchain_image,
623 presentable_frame.rotating_frame_index(),
624 main_view.clone(),
625 extract_resources,
626 render_resources,
627 )?;
628
629 let graphics_queue = renderer.graphics_queue.clone();
630 let feature_plugins = renderer.feature_plugins.clone();
631 let pipeline_plugin = renderer.pipeline_plugin.clone();
632 let thread_pool = renderer_inner.thread_pool.clone_to_box();
633 let render_resources = renderer.render_resources.clone();
634
635 let prepared_frame = RenderFrameJob {
636 thread_pool,
637 render_resources,
638 prepared_render_graph,
639 resource_context,
640 frame_packets,
641 render_registry,
642 device_context,
643 graphics_queue,
644 feature_plugins,
645 pipeline_plugin,
646 render_views,
647 };
648
649 Ok(prepared_frame)
650 }
651
652 fn create_view_visibility_jobs<'visibility>(
653 render_views: &[RenderView],
654 visibility_resource: &'visibility VisibilityResource,
655 ) -> Vec<Arc<ViewVisibilityJob<'visibility>>> {
656 render_views
657 .iter()
658 .map(|view| {
659 log::trace!("Add visibility job {}", view.debug_name());
660 Arc::new(ViewVisibilityJob::new(view.clone(), visibility_resource))
661 })
662 .collect::<Vec<_>>()
663 }
664
665 pub fn run_view_visibility_job<'extract>(
666 view_visibility_job: &Arc<ViewVisibilityJob>,
667 extract_context: &RenderJobExtractContext<'extract>,
668 visibility_resource: &VisibilityResource,
669 ) -> RenderViewVisibilityQuery {
670 view_visibility_job.query_visibility(extract_context, visibility_resource)
671 }
672
673 pub fn calculate_frame_packet_size(
674 #[allow(unused_variables)] debug_constants: &'static RenderFeatureDebugConstants,
675 feature_index: RenderFeatureIndex,
676 is_relevant: impl Fn(&RenderViewVisibilityQuery) -> bool,
677 visibility_results: &Vec<RenderViewVisibilityQuery>,
678 render_object_instance_object_ids: &mut RenderObjectInstanceObjectIds,
679 frame_packet_size: &mut FramePacketSize,
680 ) {
681 profiling::scope!(debug_constants.feature_name);
682
683 for view_visibility_result in visibility_results
684 .iter()
685 .filter(|result| is_relevant(result))
686 {
687 if let Some(visible_render_objects) =
688 view_visibility_result.render_object_instances_per_view(feature_index)
689 {
690 for render_object in visible_render_objects {
691 render_object_instance_object_ids.insert(*render_object);
692 }
693
694 frame_packet_size.view_packet_sizes.push(ViewPacketSize {
695 view: view_visibility_result.view.clone(),
696 num_render_object_instances: visible_render_objects.len(),
697 num_volumes: 0, });
699 } else {
700 frame_packet_size.view_packet_sizes.push(ViewPacketSize {
701 view: view_visibility_result.view.clone(),
702 num_render_object_instances: 0,
703 num_volumes: 0, });
705 }
706 }
707 }
708
709 pub fn count_render_feature_render_objects<'extract>(
710 feature: &Arc<dyn RenderFeaturePlugin>,
711 extract_context: &RenderJobExtractContext<'extract>,
712 visibility_results: &Vec<RenderViewVisibilityQuery>,
713 ) {
714 profiling::scope!(feature.feature_debug_constants().feature_name);
715
716 let temporary_work = extract_context.allocation_context;
717
718 let mut render_object_instances = temporary_work
719 .render_object_instances
720 .get(feature.feature_index() as usize)
721 .unwrap()
722 .borrow_mut();
723 render_object_instances.clear();
724
725 let mut frame_packet_metadata = temporary_work
726 .frame_packet_metadata
727 .get(feature.feature_index() as usize)
728 .unwrap()
729 .borrow_mut();
730
731 frame_packet_metadata
732 .frame_packet_size
733 .view_packet_sizes
734 .clear();
735
736 feature.calculate_frame_packet_size(
742 extract_context,
743 visibility_results,
744 &mut *render_object_instances,
745 &mut frame_packet_metadata.frame_packet_size,
746 );
747
748 frame_packet_metadata
749 .frame_packet_size
750 .num_render_object_instances = render_object_instances.len();
751
752 let num_view_packets = frame_packet_metadata
753 .frame_packet_size
754 .view_packet_sizes
755 .len();
756
757 frame_packet_metadata.is_relevant = num_view_packets > 0;
758 }
759
760 fn create_frame_packets<'extract>(
761 features: &Vec<Arc<dyn RenderFeaturePlugin>>,
762 extract_context: &RenderJobExtractContext<'extract>,
763 ) {
764 let temporary_work = extract_context.allocation_context;
765
766 features.iter().for_each(|feature| {
767 profiling::scope!(feature.feature_debug_constants().feature_name);
768
769 let frame_packet_metadata = temporary_work
770 .frame_packet_metadata
771 .get(feature.feature_index() as usize)
772 .unwrap()
773 .borrow();
774
775 if frame_packet_metadata.is_relevant {
776 let frame_packet =
777 feature.new_frame_packet(&frame_packet_metadata.frame_packet_size);
778
779 *temporary_work
780 .frame_packets
781 .get(feature.feature_index() as usize)
782 .unwrap()
783 .borrow_mut() = Some(frame_packet);
784 }
785 });
786 }
787
788 pub fn populate_frame_packet(
789 #[allow(unused_variables)] debug_constants: &'static RenderFeatureDebugConstants,
790 feature_index: RenderFeatureIndex,
791 is_relevant: impl Fn(&RenderViewVisibilityQuery) -> bool,
792 visibility_results: &Vec<RenderViewVisibilityQuery>,
793 frame_packet: &mut Box<dyn RenderFeatureFramePacket>,
794 ) {
795 profiling::scope!(debug_constants.feature_name);
796
797 for view_visibility_result in visibility_results
798 .iter()
799 .filter(|result| is_relevant(result))
800 {
801 let view_frame_index = view_visibility_result
802 .view
803 .view_frame_index(feature_index)
804 .unwrap();
805 if let Some(visible_render_objects) =
806 view_visibility_result.render_object_instances_per_view(feature_index)
807 {
808 for render_object_instance in visible_render_objects {
809 let render_object_instance_id =
810 frame_packet.get_or_push_render_object_instance(*render_object_instance);
811
812 frame_packet.push_render_object_instance_per_view(
813 view_frame_index,
814 render_object_instance_id,
815 *render_object_instance,
816 );
817 }
818 }
819
820 }
826 }
827
828 pub fn create_extract_job<'extract>(
829 feature: &Arc<dyn RenderFeaturePlugin>,
830 extract_context: &RenderJobExtractContext<'extract>,
831 visibility_results: &Vec<RenderViewVisibilityQuery>,
832 ) -> Option<Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>> {
833 profiling::scope!(feature.feature_debug_constants().feature_name);
834
835 let temporary_work = extract_context.allocation_context;
836
837 if !temporary_work
838 .frame_packets
839 .get(feature.feature_index() as usize)
840 .map(|frame_packet| frame_packet.borrow().is_some())
841 .unwrap_or(false)
842 {
843 return None;
844 }
845
846 let frame_packet_metadata = temporary_work
847 .frame_packet_metadata
848 .get(feature.feature_index() as usize)
849 .unwrap()
850 .borrow();
851
852 let mut frame_packet = temporary_work
853 .frame_packets
854 .get(feature.feature_index() as usize)
855 .unwrap()
856 .borrow_mut()
857 .take()
858 .unwrap();
859
860 feature.populate_frame_packet(
863 extract_context,
864 visibility_results,
865 &frame_packet_metadata.frame_packet_size,
866 &mut frame_packet,
867 );
868
869 Some(feature.new_extract_job(extract_context, frame_packet))
870 }
871
872 pub fn extract_render_object_instance_chunk<'extract>(
873 extract_job: &Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>,
874 visibility_resource: &VisibilityResource,
875 chunk_index: usize,
876 chunk_size: usize,
877 ) {
878 let num_render_object_instances = extract_job.num_render_object_instances();
879 let start_id = chunk_index * chunk_size;
880 let end_id = usize::min(start_id + chunk_size, num_render_object_instances);
881 extract_job.extract_render_object_instance(visibility_resource, start_id..end_id);
882 }
883
884 pub fn extract_render_object_instance_all<'extract>(
885 extract_job: &Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>,
886 visibility_resource: &VisibilityResource,
887 ) {
888 Renderer::extract_render_object_instance_chunk(
889 extract_job,
890 visibility_resource,
891 0,
892 extract_job.num_render_object_instances(),
893 );
894 }
895
896 pub fn extract_render_object_instance_per_view_chunk<'extract>(
897 extract_job: &Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>,
898 visibility_resource: &VisibilityResource,
899 view_packet: &dyn RenderFeatureViewPacket,
900 chunk_index: usize,
901 chunk_size: usize,
902 ) {
903 let num_render_object_instances = view_packet.num_render_object_instances();
904 let start_id = chunk_index * chunk_size;
905 let end_id = usize::min(start_id + chunk_size, num_render_object_instances);
906 extract_job.extract_render_object_instance_per_view(
907 view_packet,
908 visibility_resource,
909 start_id..end_id,
910 );
911 }
912
913 pub fn extract_render_object_instance_per_view_all<'extract>(
914 extract_job: &Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>,
915 visibility_resource: &VisibilityResource,
916 view_packet: &dyn RenderFeatureViewPacket,
917 ) {
918 Renderer::extract_render_object_instance_per_view_chunk(
919 extract_job,
920 visibility_resource,
921 view_packet,
922 0,
923 view_packet.num_render_object_instances(),
924 );
925 }
926
927 fn take_frame_packet<'extract>(
928 extract_job: &mut Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>
929 ) -> Box<dyn RenderFeatureFramePacket> {
930 let extract_job = Arc::get_mut(extract_job).unwrap();
931 extract_job.take_frame_packet()
932 }
933
934 fn take_frame_packets<'extract>(
935 mut finished_extract_jobs: Vec<Arc<dyn RenderFeatureExtractJob<'extract> + 'extract>>
936 ) -> Vec<Box<dyn RenderFeatureFramePacket>> {
937 finished_extract_jobs
938 .iter_mut()
939 .map(|extract_job| Renderer::take_frame_packet(extract_job))
940 .collect()
941 }
942}