rend3_routine/culling/
mod.rs1use rend3::{
4 format_sso,
5 graph::{DataHandle, RenderGraph},
6 types::Material,
7 util::bind_merge::BindGroupBuilder,
8 ProfileData, RendererProfile,
9};
10use wgpu::{BindGroup, Buffer};
11
12use crate::{
13 common::{PerMaterialArchetypeInterface, Sorting},
14 skinning::SkinningOutput,
15};
16
17mod cpu;
18mod gpu;
19
20pub use cpu::*;
21pub use gpu::*;
22
23pub struct PerMaterialArchetypeData {
25 pub inner: CulledObjectSet,
26 pub per_material: BindGroup,
27}
28
29pub struct CulledObjectSet {
32 pub calls: ProfileData<Vec<cpu::CpuDrawCall>, gpu::GpuIndirectData>,
33 pub output_buffer: Buffer,
34}
35
36#[allow(clippy::too_many_arguments)]
39pub fn add_culling_to_graph<'node, M: Material>(
40 graph: &mut RenderGraph<'node>,
41 pre_cull_data: DataHandle<Buffer>,
42 culled: DataHandle<PerMaterialArchetypeData>,
43 skinned: DataHandle<SkinningOutput>,
44 per_material: &'node PerMaterialArchetypeInterface<M>,
45 gpu_culler: &'node ProfileData<(), gpu::GpuCuller>,
46 shadow_index: Option<usize>,
47 key: u64,
48 sorting: Option<Sorting>,
49 name: &str,
50) {
51 let mut builder = graph.add_node(format_sso!("Culling {}", name));
52
53 let pre_cull_handle = gpu_culler
54 .profile()
55 .into_data(|| (), || builder.add_data_input(pre_cull_data));
56 let cull_handle = builder.add_data_output(culled);
57
58 builder.add_data_input(skinned);
60
61 builder.build(move |_pt, renderer, encoder_or_rpass, temps, ready, graph_data| {
62 let encoder = encoder_or_rpass.get_encoder();
63
64 let culling_input = pre_cull_handle.map_gpu(|handle| graph_data.get_data::<Buffer>(temps, handle).unwrap());
65
66 let count = graph_data.object_manager.get_objects::<M>(key).len();
67
68 let camera = match shadow_index {
69 Some(idx) => &ready.directional_light_cameras[idx],
70 None => graph_data.camera_manager,
71 };
72
73 let culled_objects = match gpu_culler {
74 ProfileData::Cpu(_) => {
75 cpu::cull_cpu::<M>(&renderer.device, camera, graph_data.object_manager, sorting, key)
76 }
77 ProfileData::Gpu(ref gpu_culler) => gpu_culler.cull(
78 &renderer.device,
79 encoder,
80 camera,
81 culling_input.into_gpu(),
82 count,
83 sorting,
84 ),
85 };
86
87 let mut per_material_bgb = BindGroupBuilder::new();
88 per_material_bgb.append_buffer(&culled_objects.output_buffer);
89
90 if renderer.profile == RendererProfile::GpuDriven {
91 graph_data.material_manager.add_to_bg_gpu::<M>(&mut per_material_bgb);
92 }
93
94 let per_material_bg = per_material_bgb.build(&renderer.device, None, &per_material.bgl);
95
96 graph_data.set_data(
97 cull_handle,
98 Some(PerMaterialArchetypeData {
99 inner: culled_objects,
100 per_material: per_material_bg,
101 }),
102 );
103 });
104}