Skip to main content

bevy_pbr/meshlet/
resource_manager.rs

1use super::{instance_manager::InstanceManager, meshlet_mesh_manager::MeshletMeshManager};
2use crate::ShadowView;
3use bevy_camera::{visibility::RenderLayers, Camera3d};
4use bevy_core_pipeline::{
5    experimental::mip_generation::{self, ViewDepthPyramid},
6    prepass::{PreviousViewData, PreviousViewUniforms},
7};
8use bevy_ecs::{
9    component::Component,
10    entity::{Entity, EntityHashMap},
11    query::AnyOf,
12    resource::Resource,
13    system::{Commands, Query, Res, ResMut},
14};
15use bevy_image::ToExtents;
16use bevy_math::{UVec2, Vec4Swizzles};
17use bevy_render::{
18    render_resource::*,
19    renderer::{RenderDevice, RenderQueue},
20    texture::{CachedTexture, TextureCache},
21    view::{ExtractedView, ViewUniform, ViewUniforms},
22};
23use binding_types::*;
24use core::iter;
25
26/// Manages per-view and per-cluster GPU resources for [`MeshletPlugin`](`super::MeshletPlugin`).
27#[derive(Resource)]
28pub struct ResourceManager {
29    /// Intermediate buffer of cluster IDs for use with rasterizing the visibility buffer
30    visibility_buffer_raster_clusters: Buffer,
31    /// Intermediate buffer of previous counts of clusters in rasterizer buckets
32    pub visibility_buffer_raster_cluster_prev_counts: Buffer,
33    /// Intermediate buffer of count of clusters to software rasterize
34    software_raster_cluster_count: Buffer,
35    /// BVH traversal queues
36    bvh_traversal_queues: [Buffer; 2],
37    /// Cluster cull candidate queue
38    cluster_cull_candidate_queue: Buffer,
39    /// Rightmost slot index of [`Self::visibility_buffer_raster_clusters`], [`Self::bvh_traversal_queues`], and [`Self::cluster_cull_candidate_queue`]
40    cull_queue_rightmost_slot: u32,
41
42    /// Second pass instance candidates
43    second_pass_candidates: Option<Buffer>,
44    /// Sampler for a depth pyramid
45    depth_pyramid_sampler: Sampler,
46    /// Dummy texture view for binding depth pyramids with less than the maximum amount of mips
47    depth_pyramid_dummy_texture: TextureView,
48
49    // TODO
50    previous_depth_pyramids: EntityHashMap<TextureView>,
51
52    // Bind group layouts
53    pub clear_visibility_buffer_bind_group_layout: BindGroupLayoutDescriptor,
54    pub clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,
55    pub first_instance_cull_bind_group_layout: BindGroupLayoutDescriptor,
56    pub second_instance_cull_bind_group_layout: BindGroupLayoutDescriptor,
57    pub first_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor,
58    pub second_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor,
59    pub first_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor,
60    pub second_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor,
61    pub visibility_buffer_raster_bind_group_layout: BindGroupLayoutDescriptor,
62    pub visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,
63    pub downsample_depth_bind_group_layout: BindGroupLayoutDescriptor,
64    pub downsample_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,
65    pub resolve_depth_bind_group_layout: BindGroupLayoutDescriptor,
66    pub resolve_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,
67    pub resolve_material_depth_bind_group_layout: BindGroupLayoutDescriptor,
68    pub material_shade_bind_group_layout: BindGroupLayoutDescriptor,
69    pub fill_counts_bind_group_layout: BindGroupLayoutDescriptor,
70    pub remap_1d_to_2d_dispatch_bind_group_layout: Option<BindGroupLayoutDescriptor>,
71}
72
73impl ResourceManager {
74    pub fn new(cluster_buffer_slots: u32, render_device: &RenderDevice) -> Self {
75        let needs_dispatch_remap =
76            cluster_buffer_slots > render_device.limits().max_compute_workgroups_per_dimension;
77        // The IDs are a (u32, u32) of instance and index.
78        let cull_queue_size = 2 * cluster_buffer_slots as u64 * size_of::<u32>() as u64;
79
80        Self {
81            visibility_buffer_raster_clusters: render_device.create_buffer(&BufferDescriptor {
82                label: Some("meshlet_visibility_buffer_raster_clusters"),
83                size: cull_queue_size,
84                usage: BufferUsages::STORAGE,
85                mapped_at_creation: false,
86            }),
87            visibility_buffer_raster_cluster_prev_counts: render_device.create_buffer(
88                &BufferDescriptor {
89                    label: Some("meshlet_visibility_buffer_raster_cluster_prev_counts"),
90                    size: size_of::<u32>() as u64 * 2,
91                    usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
92                    mapped_at_creation: false,
93                },
94            ),
95            software_raster_cluster_count: render_device.create_buffer(&BufferDescriptor {
96                label: Some("meshlet_software_raster_cluster_count"),
97                size: size_of::<u32>() as u64,
98                usage: BufferUsages::STORAGE,
99                mapped_at_creation: false,
100            }),
101            bvh_traversal_queues: [
102                render_device.create_buffer(&BufferDescriptor {
103                    label: Some("meshlet_bvh_traversal_queue_0"),
104                    size: cull_queue_size,
105                    usage: BufferUsages::STORAGE,
106                    mapped_at_creation: false,
107                }),
108                render_device.create_buffer(&BufferDescriptor {
109                    label: Some("meshlet_bvh_traversal_queue_1"),
110                    size: cull_queue_size,
111                    usage: BufferUsages::STORAGE,
112                    mapped_at_creation: false,
113                }),
114            ],
115            cluster_cull_candidate_queue: render_device.create_buffer(&BufferDescriptor {
116                label: Some("meshlet_cluster_cull_candidate_queue"),
117                size: cull_queue_size,
118                usage: BufferUsages::STORAGE,
119                mapped_at_creation: false,
120            }),
121            cull_queue_rightmost_slot: cluster_buffer_slots - 1,
122
123            second_pass_candidates: None,
124            depth_pyramid_sampler: render_device.create_sampler(&SamplerDescriptor {
125                label: Some("meshlet_depth_pyramid_sampler"),
126                ..SamplerDescriptor::default()
127            }),
128            depth_pyramid_dummy_texture: mip_generation::create_depth_pyramid_dummy_texture(
129                render_device,
130                "meshlet_depth_pyramid_dummy_texture",
131                "meshlet_depth_pyramid_dummy_texture_view",
132            ),
133
134            previous_depth_pyramids: EntityHashMap::default(),
135
136            // TODO: Buffer min sizes
137            clear_visibility_buffer_bind_group_layout: BindGroupLayoutDescriptor::new(
138                "meshlet_clear_visibility_buffer_bind_group_layout",
139                &BindGroupLayoutEntries::single(
140                    ShaderStages::COMPUTE,
141                    texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::WriteOnly),
142                ),
143            ),
144            clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(
145                "meshlet_clear_visibility_buffer_shadow_view_bind_group_layout",
146                &BindGroupLayoutEntries::single(
147                    ShaderStages::COMPUTE,
148                    texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),
149                ),
150            ),
151            first_instance_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
152                "meshlet_first_instance_culling_bind_group_layout",
153                &BindGroupLayoutEntries::sequential(
154                    ShaderStages::COMPUTE,
155                    (
156                        texture_2d(TextureSampleType::Float { filterable: false }),
157                        uniform_buffer::<ViewUniform>(true),
158                        uniform_buffer::<PreviousViewData>(true),
159                        storage_buffer_read_only_sized(false, None),
160                        storage_buffer_read_only_sized(false, None),
161                        storage_buffer_read_only_sized(false, None),
162                        storage_buffer_read_only_sized(false, None),
163                        storage_buffer_sized(false, None),
164                        storage_buffer_sized(false, None),
165                        storage_buffer_sized(false, None),
166                        storage_buffer_sized(false, None),
167                        storage_buffer_sized(false, None),
168                        storage_buffer_sized(false, None),
169                    ),
170                ),
171            ),
172            second_instance_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
173                "meshlet_second_instance_culling_bind_group_layout",
174                &BindGroupLayoutEntries::sequential(
175                    ShaderStages::COMPUTE,
176                    (
177                        texture_2d(TextureSampleType::Float { filterable: false }),
178                        uniform_buffer::<ViewUniform>(true),
179                        uniform_buffer::<PreviousViewData>(true),
180                        storage_buffer_read_only_sized(false, None),
181                        storage_buffer_read_only_sized(false, None),
182                        storage_buffer_read_only_sized(false, None),
183                        storage_buffer_read_only_sized(false, None),
184                        storage_buffer_sized(false, None),
185                        storage_buffer_sized(false, None),
186                        storage_buffer_sized(false, None),
187                        storage_buffer_read_only_sized(false, None),
188                        storage_buffer_read_only_sized(false, None),
189                    ),
190                ),
191            ),
192            first_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
193                "meshlet_first_bvh_culling_bind_group_layout",
194                &BindGroupLayoutEntries::sequential(
195                    ShaderStages::COMPUTE,
196                    (
197                        texture_2d(TextureSampleType::Float { filterable: false }),
198                        uniform_buffer::<ViewUniform>(true),
199                        uniform_buffer::<PreviousViewData>(true),
200                        storage_buffer_read_only_sized(false, None),
201                        storage_buffer_read_only_sized(false, None),
202                        storage_buffer_read_only_sized(false, None),
203                        storage_buffer_sized(false, None),
204                        storage_buffer_sized(false, None),
205                        storage_buffer_sized(false, None),
206                        storage_buffer_sized(false, None),
207                        storage_buffer_sized(false, None),
208                        storage_buffer_sized(false, None),
209                        storage_buffer_sized(false, None),
210                        storage_buffer_sized(false, None),
211                        storage_buffer_sized(false, None),
212                        storage_buffer_sized(false, None),
213                        storage_buffer_sized(false, None),
214                    ),
215                ),
216            ),
217            second_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
218                "meshlet_second_bvh_culling_bind_group_layout",
219                &BindGroupLayoutEntries::sequential(
220                    ShaderStages::COMPUTE,
221                    (
222                        texture_2d(TextureSampleType::Float { filterable: false }),
223                        uniform_buffer::<ViewUniform>(true),
224                        uniform_buffer::<PreviousViewData>(true),
225                        storage_buffer_read_only_sized(false, None),
226                        storage_buffer_read_only_sized(false, None),
227                        storage_buffer_read_only_sized(false, None),
228                        storage_buffer_sized(false, None),
229                        storage_buffer_sized(false, None),
230                        storage_buffer_sized(false, None),
231                        storage_buffer_sized(false, None),
232                        storage_buffer_sized(false, None),
233                        storage_buffer_sized(false, None),
234                        storage_buffer_sized(false, None),
235                        storage_buffer_sized(false, None),
236                    ),
237                ),
238            ),
239            first_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
240                "meshlet_first_meshlet_culling_bind_group_layout",
241                &BindGroupLayoutEntries::sequential(
242                    ShaderStages::COMPUTE,
243                    (
244                        texture_2d(TextureSampleType::Float { filterable: false }),
245                        uniform_buffer::<ViewUniform>(true),
246                        uniform_buffer::<PreviousViewData>(true),
247                        storage_buffer_read_only_sized(false, None),
248                        storage_buffer_read_only_sized(false, None),
249                        storage_buffer_sized(false, None),
250                        storage_buffer_sized(false, None),
251                        storage_buffer_read_only_sized(false, None),
252                        storage_buffer_sized(false, None),
253                        storage_buffer_read_only_sized(false, None),
254                        storage_buffer_sized(false, None),
255                        storage_buffer_sized(false, None),
256                        storage_buffer_sized(false, None),
257                    ),
258                ),
259            ),
260            second_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor::new(
261                "meshlet_second_meshlet_culling_bind_group_layout",
262                &BindGroupLayoutEntries::sequential(
263                    ShaderStages::COMPUTE,
264                    (
265                        texture_2d(TextureSampleType::Float { filterable: false }),
266                        uniform_buffer::<ViewUniform>(true),
267                        uniform_buffer::<PreviousViewData>(true),
268                        storage_buffer_read_only_sized(false, None),
269                        storage_buffer_read_only_sized(false, None),
270                        storage_buffer_sized(false, None),
271                        storage_buffer_sized(false, None),
272                        storage_buffer_read_only_sized(false, None),
273                        storage_buffer_sized(false, None),
274                        storage_buffer_read_only_sized(false, None),
275                        storage_buffer_read_only_sized(false, None),
276                    ),
277                ),
278            ),
279            downsample_depth_bind_group_layout: BindGroupLayoutDescriptor::new(
280                "meshlet_downsample_depth_bind_group_layout",
281                &BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {
282                    let write_only_r32float = || {
283                        texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)
284                    };
285                    (
286                        texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
287                        write_only_r32float(),
288                        write_only_r32float(),
289                        write_only_r32float(),
290                        write_only_r32float(),
291                        write_only_r32float(),
292                        texture_storage_2d(
293                            TextureFormat::R32Float,
294                            StorageTextureAccess::ReadWrite,
295                        ),
296                        write_only_r32float(),
297                        write_only_r32float(),
298                        write_only_r32float(),
299                        write_only_r32float(),
300                        write_only_r32float(),
301                        write_only_r32float(),
302                        sampler(SamplerBindingType::NonFiltering),
303                    )
304                }),
305            ),
306            downsample_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(
307                "meshlet_downsample_depth_shadow_view_bind_group_layout",
308                &BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {
309                    let write_only_r32float = || {
310                        texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)
311                    };
312                    (
313                        texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),
314                        write_only_r32float(),
315                        write_only_r32float(),
316                        write_only_r32float(),
317                        write_only_r32float(),
318                        write_only_r32float(),
319                        texture_storage_2d(
320                            TextureFormat::R32Float,
321                            StorageTextureAccess::ReadWrite,
322                        ),
323                        write_only_r32float(),
324                        write_only_r32float(),
325                        write_only_r32float(),
326                        write_only_r32float(),
327                        write_only_r32float(),
328                        write_only_r32float(),
329                        sampler(SamplerBindingType::NonFiltering),
330                    )
331                }),
332            ),
333            visibility_buffer_raster_bind_group_layout: BindGroupLayoutDescriptor::new(
334                "meshlet_visibility_buffer_raster_bind_group_layout",
335                &BindGroupLayoutEntries::sequential(
336                    ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
337                    (
338                        storage_buffer_read_only_sized(false, None),
339                        storage_buffer_read_only_sized(false, None),
340                        storage_buffer_read_only_sized(false, None),
341                        storage_buffer_read_only_sized(false, None),
342                        storage_buffer_read_only_sized(false, None),
343                        storage_buffer_read_only_sized(false, None),
344                        storage_buffer_read_only_sized(false, None),
345                        texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::Atomic),
346                        uniform_buffer::<ViewUniform>(true),
347                    ),
348                ),
349            ),
350            visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(
351                "meshlet_visibility_buffer_raster_shadow_view_bind_group_layout",
352                &BindGroupLayoutEntries::sequential(
353                    ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,
354                    (
355                        storage_buffer_read_only_sized(false, None),
356                        storage_buffer_read_only_sized(false, None),
357                        storage_buffer_read_only_sized(false, None),
358                        storage_buffer_read_only_sized(false, None),
359                        storage_buffer_read_only_sized(false, None),
360                        storage_buffer_read_only_sized(false, None),
361                        storage_buffer_read_only_sized(false, None),
362                        texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::Atomic),
363                        uniform_buffer::<ViewUniform>(true),
364                    ),
365                ),
366            ),
367            resolve_depth_bind_group_layout: BindGroupLayoutDescriptor::new(
368                "meshlet_resolve_depth_bind_group_layout",
369                &BindGroupLayoutEntries::single(
370                    ShaderStages::FRAGMENT,
371                    texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
372                ),
373            ),
374            resolve_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(
375                "meshlet_resolve_depth_shadow_view_bind_group_layout",
376                &BindGroupLayoutEntries::single(
377                    ShaderStages::FRAGMENT,
378                    texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),
379                ),
380            ),
381            resolve_material_depth_bind_group_layout: BindGroupLayoutDescriptor::new(
382                "meshlet_resolve_material_depth_bind_group_layout",
383                &BindGroupLayoutEntries::sequential(
384                    ShaderStages::FRAGMENT,
385                    (
386                        texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
387                        storage_buffer_read_only_sized(false, None),
388                        storage_buffer_read_only_sized(false, None),
389                    ),
390                ),
391            ),
392            material_shade_bind_group_layout: BindGroupLayoutDescriptor::new(
393                "meshlet_mesh_material_shade_bind_group_layout",
394                &BindGroupLayoutEntries::sequential(
395                    ShaderStages::FRAGMENT,
396                    (
397                        texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),
398                        storage_buffer_read_only_sized(false, None),
399                        storage_buffer_read_only_sized(false, None),
400                        storage_buffer_read_only_sized(false, None),
401                        storage_buffer_read_only_sized(false, None),
402                        storage_buffer_read_only_sized(false, None),
403                        storage_buffer_read_only_sized(false, None),
404                        storage_buffer_read_only_sized(false, None),
405                    ),
406                ),
407            ),
408            fill_counts_bind_group_layout: if needs_dispatch_remap {
409                BindGroupLayoutDescriptor::new(
410                    "meshlet_fill_counts_bind_group_layout",
411                    &BindGroupLayoutEntries::sequential(
412                        ShaderStages::COMPUTE,
413                        (
414                            storage_buffer_sized(false, None),
415                            storage_buffer_sized(false, None),
416                            storage_buffer_sized(false, None),
417                            storage_buffer_sized(false, None),
418                        ),
419                    ),
420                )
421            } else {
422                BindGroupLayoutDescriptor::new(
423                    "meshlet_fill_counts_bind_group_layout",
424                    &BindGroupLayoutEntries::sequential(
425                        ShaderStages::COMPUTE,
426                        (
427                            storage_buffer_sized(false, None),
428                            storage_buffer_sized(false, None),
429                            storage_buffer_sized(false, None),
430                        ),
431                    ),
432                )
433            },
434            remap_1d_to_2d_dispatch_bind_group_layout: needs_dispatch_remap.then(|| {
435                BindGroupLayoutDescriptor::new(
436                    "meshlet_remap_1d_to_2d_dispatch_bind_group_layout",
437                    &BindGroupLayoutEntries::sequential(
438                        ShaderStages::COMPUTE,
439                        (
440                            storage_buffer_sized(false, None),
441                            storage_buffer_sized(false, None),
442                        ),
443                    ),
444                )
445            }),
446        }
447    }
448}
449
450// ------------ TODO: Everything under here needs to be rewritten and cached ------------
451
452#[derive(Component)]
453pub struct MeshletViewResources {
454    pub scene_instance_count: u32,
455    pub rightmost_slot: u32,
456    pub max_bvh_depth: u32,
457    instance_visibility: Buffer,
458    pub dummy_render_target: CachedTexture,
459    pub visibility_buffer: CachedTexture,
460    pub second_pass_count: Buffer,
461    pub second_pass_dispatch: Buffer,
462    pub second_pass_candidates: Buffer,
463    pub first_bvh_cull_count_front: Buffer,
464    pub first_bvh_cull_dispatch_front: Buffer,
465    pub first_bvh_cull_count_back: Buffer,
466    pub first_bvh_cull_dispatch_back: Buffer,
467    pub first_bvh_cull_queue: Buffer,
468    pub second_bvh_cull_count_front: Buffer,
469    pub second_bvh_cull_dispatch_front: Buffer,
470    pub second_bvh_cull_count_back: Buffer,
471    pub second_bvh_cull_dispatch_back: Buffer,
472    pub second_bvh_cull_queue: Buffer,
473    pub front_meshlet_cull_count: Buffer,
474    pub front_meshlet_cull_dispatch: Buffer,
475    pub back_meshlet_cull_count: Buffer,
476    pub back_meshlet_cull_dispatch: Buffer,
477    pub meshlet_cull_queue: Buffer,
478    pub visibility_buffer_software_raster_indirect_args: Buffer,
479    pub visibility_buffer_hardware_raster_indirect_args: Buffer,
480    pub depth_pyramid: ViewDepthPyramid,
481    previous_depth_pyramid: TextureView,
482    pub material_depth: Option<CachedTexture>,
483    pub view_size: UVec2,
484    not_shadow_view: bool,
485}
486
487#[derive(Component)]
488pub struct MeshletViewBindGroups {
489    pub clear_visibility_buffer: BindGroup,
490    pub first_instance_cull: BindGroup,
491    pub second_instance_cull: BindGroup,
492    pub first_bvh_cull_ping: BindGroup,
493    pub first_bvh_cull_pong: BindGroup,
494    pub second_bvh_cull_ping: BindGroup,
495    pub second_bvh_cull_pong: BindGroup,
496    pub first_meshlet_cull: BindGroup,
497    pub second_meshlet_cull: BindGroup,
498    pub downsample_depth: BindGroup,
499    pub visibility_buffer_raster: BindGroup,
500    pub resolve_depth: BindGroup,
501    pub resolve_material_depth: Option<BindGroup>,
502    pub material_shade: Option<BindGroup>,
503    pub remap_1d_to_2d_dispatch: Option<BindGroup>,
504    pub fill_counts: BindGroup,
505}
506
507// TODO: Cache things per-view and skip running this system / optimize this system
508pub fn prepare_meshlet_per_frame_resources(
509    mut resource_manager: ResMut<ResourceManager>,
510    mut instance_manager: ResMut<InstanceManager>,
511    views: Query<(
512        Entity,
513        &ExtractedView,
514        Option<&RenderLayers>,
515        AnyOf<(&Camera3d, &ShadowView)>,
516    )>,
517    mut texture_cache: ResMut<TextureCache>,
518    render_queue: Res<RenderQueue>,
519    render_device: Res<RenderDevice>,
520    mut commands: Commands,
521) {
522    if instance_manager.scene_instance_count == 0 {
523        return;
524    }
525
526    let instance_manager = instance_manager.as_mut();
527
528    // TODO: Move this and the submit to a separate system and remove pub from the fields
529    instance_manager
530        .instance_uniforms
531        .write_buffer(&render_device, &render_queue);
532    instance_manager
533        .instance_aabbs
534        .write_buffer(&render_device, &render_queue);
535    instance_manager
536        .instance_material_ids
537        .write_buffer(&render_device, &render_queue);
538    instance_manager
539        .instance_bvh_root_nodes
540        .write_buffer(&render_device, &render_queue);
541
542    let needed_buffer_size = 4 * instance_manager.scene_instance_count as u64;
543    let second_pass_candidates = match &mut resource_manager.second_pass_candidates {
544        Some(buffer) if buffer.size() >= needed_buffer_size => buffer.clone(),
545        slot => {
546            let buffer = render_device.create_buffer(&BufferDescriptor {
547                label: Some("meshlet_second_pass_candidates"),
548                size: needed_buffer_size,
549                usage: BufferUsages::STORAGE,
550                mapped_at_creation: false,
551            });
552            *slot = Some(buffer.clone());
553            buffer
554        }
555    };
556
557    for (view_entity, view, render_layers, (_, shadow_view)) in &views {
558        let not_shadow_view = shadow_view.is_none();
559
560        let instance_visibility = instance_manager
561            .view_instance_visibility
562            .entry(view_entity)
563            .or_insert_with(|| {
564                let mut buffer = StorageBuffer::default();
565                buffer.set_label(Some("meshlet_view_instance_visibility"));
566                buffer
567            });
568        for (instance_index, (_, layers, not_shadow_caster)) in
569            instance_manager.instances.iter().enumerate()
570        {
571            // If either the layers don't match the view's layers or this is a shadow view
572            // and the instance is not a shadow caster, hide the instance for this view
573            if !render_layers
574                .unwrap_or(&RenderLayers::default())
575                .intersects(layers)
576                || (shadow_view.is_some() && *not_shadow_caster)
577            {
578                let vec = instance_visibility.get_mut();
579                let index = instance_index / 32;
580                let bit = instance_index - index * 32;
581                if vec.len() <= index {
582                    vec.extend(iter::repeat_n(0, index - vec.len() + 1));
583                }
584                vec[index] |= 1 << bit;
585            }
586        }
587        instance_visibility.write_buffer(&render_device, &render_queue);
588        let instance_visibility = instance_visibility.buffer().unwrap().clone();
589
590        // TODO: Remove this once wgpu allows render passes with no attachments
591        let dummy_render_target = texture_cache.get(
592            &render_device,
593            TextureDescriptor {
594                label: Some("meshlet_dummy_render_target"),
595                size: view.viewport.zw().to_extents(),
596                mip_level_count: 1,
597                sample_count: 1,
598                dimension: TextureDimension::D2,
599                format: TextureFormat::R8Uint,
600                usage: TextureUsages::RENDER_ATTACHMENT,
601                view_formats: &[],
602            },
603        );
604
605        let visibility_buffer = texture_cache.get(
606            &render_device,
607            TextureDescriptor {
608                label: Some("meshlet_visibility_buffer"),
609                size: view.viewport.zw().to_extents(),
610                mip_level_count: 1,
611                sample_count: 1,
612                dimension: TextureDimension::D2,
613                format: if not_shadow_view {
614                    TextureFormat::R64Uint
615                } else {
616                    TextureFormat::R32Uint
617                },
618                usage: TextureUsages::STORAGE_ATOMIC | TextureUsages::STORAGE_BINDING,
619                view_formats: &[],
620            },
621        );
622
623        let second_pass_count = render_device.create_buffer_with_data(&BufferInitDescriptor {
624            label: Some("meshlet_second_pass_count"),
625            contents: bytemuck::bytes_of(&0u32),
626            usage: BufferUsages::STORAGE,
627        });
628        let second_pass_dispatch = render_device.create_buffer_with_data(&BufferInitDescriptor {
629            label: Some("meshlet_second_pass_dispatch"),
630            contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
631            usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,
632        });
633
634        let first_bvh_cull_count_front =
635            render_device.create_buffer_with_data(&BufferInitDescriptor {
636                label: Some("meshlet_first_bvh_cull_count_front"),
637                contents: bytemuck::bytes_of(&0u32),
638                usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
639            });
640        let first_bvh_cull_dispatch_front =
641            render_device.create_buffer_with_data(&BufferInitDescriptor {
642                label: Some("meshlet_first_bvh_cull_dispatch_front"),
643                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
644                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,
645            });
646        let first_bvh_cull_count_back =
647            render_device.create_buffer_with_data(&BufferInitDescriptor {
648                label: Some("meshlet_first_bvh_cull_count_back"),
649                contents: bytemuck::bytes_of(&0u32),
650                usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
651            });
652        let first_bvh_cull_dispatch_back =
653            render_device.create_buffer_with_data(&BufferInitDescriptor {
654                label: Some("meshlet_first_bvh_cull_dispatch_back"),
655                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
656                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,
657            });
658
659        let second_bvh_cull_count_front =
660            render_device.create_buffer_with_data(&BufferInitDescriptor {
661                label: Some("meshlet_second_bvh_cull_count_front"),
662                contents: bytemuck::bytes_of(&0u32),
663                usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
664            });
665        let second_bvh_cull_dispatch_front =
666            render_device.create_buffer_with_data(&BufferInitDescriptor {
667                label: Some("meshlet_second_bvh_cull_dispatch_front"),
668                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
669                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,
670            });
671        let second_bvh_cull_count_back =
672            render_device.create_buffer_with_data(&BufferInitDescriptor {
673                label: Some("meshlet_second_bvh_cull_count_back"),
674                contents: bytemuck::bytes_of(&0u32),
675                usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,
676            });
677        let second_bvh_cull_dispatch_back =
678            render_device.create_buffer_with_data(&BufferInitDescriptor {
679                label: Some("meshlet_second_bvh_cull_dispatch_back"),
680                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
681                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,
682            });
683
684        let front_meshlet_cull_count =
685            render_device.create_buffer_with_data(&BufferInitDescriptor {
686                label: Some("meshlet_front_meshlet_cull_count"),
687                contents: bytemuck::bytes_of(&0u32),
688                usage: BufferUsages::STORAGE,
689            });
690        let front_meshlet_cull_dispatch =
691            render_device.create_buffer_with_data(&BufferInitDescriptor {
692                label: Some("meshlet_front_meshlet_cull_dispatch"),
693                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
694                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,
695            });
696        let back_meshlet_cull_count =
697            render_device.create_buffer_with_data(&BufferInitDescriptor {
698                label: Some("meshlet_back_meshlet_cull_count"),
699                contents: bytemuck::bytes_of(&0u32),
700                usage: BufferUsages::STORAGE,
701            });
702        let back_meshlet_cull_dispatch =
703            render_device.create_buffer_with_data(&BufferInitDescriptor {
704                label: Some("meshlet_back_meshlet_cull_dispatch"),
705                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
706                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,
707            });
708
709        let visibility_buffer_software_raster_indirect_args = render_device
710            .create_buffer_with_data(&BufferInitDescriptor {
711                label: Some("meshlet_visibility_buffer_software_raster_indirect_args"),
712                contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),
713                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,
714            });
715
716        let visibility_buffer_hardware_raster_indirect_args = render_device
717            .create_buffer_with_data(&BufferInitDescriptor {
718                label: Some("meshlet_visibility_buffer_hardware_raster_indirect_args"),
719                contents: DrawIndirectArgs {
720                    vertex_count: 128 * 3,
721                    instance_count: 0,
722                    first_vertex: 0,
723                    first_instance: 0,
724                }
725                .as_bytes(),
726                usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,
727            });
728
729        let depth_pyramid = ViewDepthPyramid::new(
730            &render_device,
731            &mut texture_cache,
732            &resource_manager.depth_pyramid_dummy_texture,
733            view.viewport.zw(),
734            "meshlet_depth_pyramid",
735            "meshlet_depth_pyramid_texture_view",
736        );
737
738        let previous_depth_pyramid =
739            match resource_manager.previous_depth_pyramids.get(&view_entity) {
740                Some(texture_view) => texture_view.clone(),
741                None => depth_pyramid.all_mips.clone(),
742            };
743        resource_manager
744            .previous_depth_pyramids
745            .insert(view_entity, depth_pyramid.all_mips.clone());
746
747        let material_depth = TextureDescriptor {
748            label: Some("meshlet_material_depth"),
749            size: view.viewport.zw().to_extents(),
750            mip_level_count: 1,
751            sample_count: 1,
752            dimension: TextureDimension::D2,
753            format: TextureFormat::Depth16Unorm,
754            usage: TextureUsages::RENDER_ATTACHMENT,
755            view_formats: &[],
756        };
757
758        commands.entity(view_entity).insert(MeshletViewResources {
759            scene_instance_count: instance_manager.scene_instance_count,
760            rightmost_slot: resource_manager.cull_queue_rightmost_slot,
761            max_bvh_depth: instance_manager.max_bvh_depth,
762            instance_visibility,
763            dummy_render_target,
764            visibility_buffer,
765            second_pass_count,
766            second_pass_dispatch,
767            second_pass_candidates: second_pass_candidates.clone(),
768            first_bvh_cull_count_front,
769            first_bvh_cull_dispatch_front,
770            first_bvh_cull_count_back,
771            first_bvh_cull_dispatch_back,
772            first_bvh_cull_queue: resource_manager.bvh_traversal_queues[0].clone(),
773            second_bvh_cull_count_front,
774            second_bvh_cull_dispatch_front,
775            second_bvh_cull_count_back,
776            second_bvh_cull_dispatch_back,
777            second_bvh_cull_queue: resource_manager.bvh_traversal_queues[1].clone(),
778            front_meshlet_cull_count,
779            front_meshlet_cull_dispatch,
780            back_meshlet_cull_count,
781            back_meshlet_cull_dispatch,
782            meshlet_cull_queue: resource_manager.cluster_cull_candidate_queue.clone(),
783            visibility_buffer_software_raster_indirect_args,
784            visibility_buffer_hardware_raster_indirect_args,
785            depth_pyramid,
786            previous_depth_pyramid,
787            material_depth: not_shadow_view
788                .then(|| texture_cache.get(&render_device, material_depth)),
789            view_size: view.viewport.zw(),
790            not_shadow_view,
791        });
792    }
793}
794
795pub fn prepare_meshlet_view_bind_groups(
796    meshlet_mesh_manager: Res<MeshletMeshManager>,
797    resource_manager: Res<ResourceManager>,
798    instance_manager: Res<InstanceManager>,
799    views: Query<(Entity, &MeshletViewResources)>,
800    view_uniforms: Res<ViewUniforms>,
801    previous_view_uniforms: Res<PreviousViewUniforms>,
802    render_device: Res<RenderDevice>,
803    pipeline_cache: Res<PipelineCache>,
804    mut commands: Commands,
805) {
806    let (Some(view_uniforms), Some(previous_view_uniforms)) = (
807        view_uniforms.uniforms.binding(),
808        previous_view_uniforms.uniforms.binding(),
809    ) else {
810        return;
811    };
812
813    // TODO: Some of these bind groups can be reused across multiple views
814    for (view_entity, view_resources) in &views {
815        let clear_visibility_buffer = render_device.create_bind_group(
816            "meshlet_clear_visibility_buffer_bind_group",
817            &pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {
818                &resource_manager.clear_visibility_buffer_bind_group_layout
819            } else {
820                &resource_manager.clear_visibility_buffer_shadow_view_bind_group_layout
821            }),
822            &BindGroupEntries::single(&view_resources.visibility_buffer.default_view),
823        );
824
825        let first_instance_cull = render_device.create_bind_group(
826            "meshlet_first_instance_cull_bind_group",
827            &pipeline_cache
828                .get_bind_group_layout(&resource_manager.first_instance_cull_bind_group_layout),
829            &BindGroupEntries::sequential((
830                &view_resources.previous_depth_pyramid,
831                view_uniforms.clone(),
832                previous_view_uniforms.clone(),
833                instance_manager.instance_uniforms.binding().unwrap(),
834                view_resources.instance_visibility.as_entire_binding(),
835                instance_manager.instance_aabbs.binding().unwrap(),
836                instance_manager.instance_bvh_root_nodes.binding().unwrap(),
837                view_resources
838                    .first_bvh_cull_count_front
839                    .as_entire_binding(),
840                view_resources
841                    .first_bvh_cull_dispatch_front
842                    .as_entire_binding(),
843                view_resources.first_bvh_cull_queue.as_entire_binding(),
844                view_resources.second_pass_count.as_entire_binding(),
845                view_resources.second_pass_dispatch.as_entire_binding(),
846                view_resources.second_pass_candidates.as_entire_binding(),
847            )),
848        );
849
850        let second_instance_cull = render_device.create_bind_group(
851            "meshlet_second_instance_cull_bind_group",
852            &pipeline_cache
853                .get_bind_group_layout(&resource_manager.second_instance_cull_bind_group_layout),
854            &BindGroupEntries::sequential((
855                &view_resources.previous_depth_pyramid,
856                view_uniforms.clone(),
857                previous_view_uniforms.clone(),
858                instance_manager.instance_uniforms.binding().unwrap(),
859                view_resources.instance_visibility.as_entire_binding(),
860                instance_manager.instance_aabbs.binding().unwrap(),
861                instance_manager.instance_bvh_root_nodes.binding().unwrap(),
862                view_resources
863                    .second_bvh_cull_count_front
864                    .as_entire_binding(),
865                view_resources
866                    .second_bvh_cull_dispatch_front
867                    .as_entire_binding(),
868                view_resources.second_bvh_cull_queue.as_entire_binding(),
869                view_resources.second_pass_count.as_entire_binding(),
870                view_resources.second_pass_candidates.as_entire_binding(),
871            )),
872        );
873
874        let first_bvh_cull_ping = render_device.create_bind_group(
875            "meshlet_first_bvh_cull_ping_bind_group",
876            &pipeline_cache
877                .get_bind_group_layout(&resource_manager.first_bvh_cull_bind_group_layout),
878            &BindGroupEntries::sequential((
879                &view_resources.previous_depth_pyramid,
880                view_uniforms.clone(),
881                previous_view_uniforms.clone(),
882                meshlet_mesh_manager.bvh_nodes.binding(),
883                instance_manager.instance_uniforms.binding().unwrap(),
884                view_resources
885                    .first_bvh_cull_count_front
886                    .as_entire_binding(),
887                view_resources.first_bvh_cull_count_back.as_entire_binding(),
888                view_resources
889                    .first_bvh_cull_dispatch_back
890                    .as_entire_binding(),
891                view_resources.first_bvh_cull_queue.as_entire_binding(),
892                view_resources.front_meshlet_cull_count.as_entire_binding(),
893                view_resources.back_meshlet_cull_count.as_entire_binding(),
894                view_resources
895                    .front_meshlet_cull_dispatch
896                    .as_entire_binding(),
897                view_resources
898                    .back_meshlet_cull_dispatch
899                    .as_entire_binding(),
900                view_resources.meshlet_cull_queue.as_entire_binding(),
901                view_resources
902                    .second_bvh_cull_count_front
903                    .as_entire_binding(),
904                view_resources
905                    .second_bvh_cull_dispatch_front
906                    .as_entire_binding(),
907                view_resources.second_bvh_cull_queue.as_entire_binding(),
908            )),
909        );
910
911        let first_bvh_cull_pong = render_device.create_bind_group(
912            "meshlet_first_bvh_cull_pong_bind_group",
913            &pipeline_cache
914                .get_bind_group_layout(&resource_manager.first_bvh_cull_bind_group_layout),
915            &BindGroupEntries::sequential((
916                &view_resources.previous_depth_pyramid,
917                view_uniforms.clone(),
918                previous_view_uniforms.clone(),
919                meshlet_mesh_manager.bvh_nodes.binding(),
920                instance_manager.instance_uniforms.binding().unwrap(),
921                view_resources.first_bvh_cull_count_back.as_entire_binding(),
922                view_resources
923                    .first_bvh_cull_count_front
924                    .as_entire_binding(),
925                view_resources
926                    .first_bvh_cull_dispatch_front
927                    .as_entire_binding(),
928                view_resources.first_bvh_cull_queue.as_entire_binding(),
929                view_resources.front_meshlet_cull_count.as_entire_binding(),
930                view_resources.back_meshlet_cull_count.as_entire_binding(),
931                view_resources
932                    .front_meshlet_cull_dispatch
933                    .as_entire_binding(),
934                view_resources
935                    .back_meshlet_cull_dispatch
936                    .as_entire_binding(),
937                view_resources.meshlet_cull_queue.as_entire_binding(),
938                view_resources
939                    .second_bvh_cull_count_front
940                    .as_entire_binding(),
941                view_resources
942                    .second_bvh_cull_dispatch_front
943                    .as_entire_binding(),
944                view_resources.second_bvh_cull_queue.as_entire_binding(),
945            )),
946        );
947
948        let second_bvh_cull_ping = render_device.create_bind_group(
949            "meshlet_second_bvh_cull_ping_bind_group",
950            &pipeline_cache
951                .get_bind_group_layout(&resource_manager.second_bvh_cull_bind_group_layout),
952            &BindGroupEntries::sequential((
953                &view_resources.previous_depth_pyramid,
954                view_uniforms.clone(),
955                previous_view_uniforms.clone(),
956                meshlet_mesh_manager.bvh_nodes.binding(),
957                instance_manager.instance_uniforms.binding().unwrap(),
958                view_resources
959                    .second_bvh_cull_count_front
960                    .as_entire_binding(),
961                view_resources
962                    .second_bvh_cull_count_back
963                    .as_entire_binding(),
964                view_resources
965                    .second_bvh_cull_dispatch_back
966                    .as_entire_binding(),
967                view_resources.second_bvh_cull_queue.as_entire_binding(),
968                view_resources.front_meshlet_cull_count.as_entire_binding(),
969                view_resources.back_meshlet_cull_count.as_entire_binding(),
970                view_resources
971                    .front_meshlet_cull_dispatch
972                    .as_entire_binding(),
973                view_resources
974                    .back_meshlet_cull_dispatch
975                    .as_entire_binding(),
976                view_resources.meshlet_cull_queue.as_entire_binding(),
977            )),
978        );
979
980        let second_bvh_cull_pong = render_device.create_bind_group(
981            "meshlet_second_bvh_cull_pong_bind_group",
982            &pipeline_cache
983                .get_bind_group_layout(&resource_manager.second_bvh_cull_bind_group_layout),
984            &BindGroupEntries::sequential((
985                &view_resources.previous_depth_pyramid,
986                view_uniforms.clone(),
987                previous_view_uniforms.clone(),
988                meshlet_mesh_manager.bvh_nodes.binding(),
989                instance_manager.instance_uniforms.binding().unwrap(),
990                view_resources
991                    .second_bvh_cull_count_back
992                    .as_entire_binding(),
993                view_resources
994                    .second_bvh_cull_count_front
995                    .as_entire_binding(),
996                view_resources
997                    .second_bvh_cull_dispatch_front
998                    .as_entire_binding(),
999                view_resources.second_bvh_cull_queue.as_entire_binding(),
1000                view_resources.front_meshlet_cull_count.as_entire_binding(),
1001                view_resources.back_meshlet_cull_count.as_entire_binding(),
1002                view_resources
1003                    .front_meshlet_cull_dispatch
1004                    .as_entire_binding(),
1005                view_resources
1006                    .back_meshlet_cull_dispatch
1007                    .as_entire_binding(),
1008                view_resources.meshlet_cull_queue.as_entire_binding(),
1009            )),
1010        );
1011
1012        let first_meshlet_cull = render_device.create_bind_group(
1013            "meshlet_first_meshlet_cull_bind_group",
1014            &pipeline_cache
1015                .get_bind_group_layout(&resource_manager.first_meshlet_cull_bind_group_layout),
1016            &BindGroupEntries::sequential((
1017                &view_resources.previous_depth_pyramid,
1018                view_uniforms.clone(),
1019                previous_view_uniforms.clone(),
1020                meshlet_mesh_manager.meshlet_cull_data.binding(),
1021                instance_manager.instance_uniforms.binding().unwrap(),
1022                view_resources
1023                    .visibility_buffer_software_raster_indirect_args
1024                    .as_entire_binding(),
1025                view_resources
1026                    .visibility_buffer_hardware_raster_indirect_args
1027                    .as_entire_binding(),
1028                resource_manager
1029                    .visibility_buffer_raster_cluster_prev_counts
1030                    .as_entire_binding(),
1031                resource_manager
1032                    .visibility_buffer_raster_clusters
1033                    .as_entire_binding(),
1034                view_resources.front_meshlet_cull_count.as_entire_binding(),
1035                view_resources.back_meshlet_cull_count.as_entire_binding(),
1036                view_resources
1037                    .back_meshlet_cull_dispatch
1038                    .as_entire_binding(),
1039                view_resources.meshlet_cull_queue.as_entire_binding(),
1040            )),
1041        );
1042
1043        let second_meshlet_cull = render_device.create_bind_group(
1044            "meshlet_second_meshlet_cull_bind_group",
1045            &pipeline_cache
1046                .get_bind_group_layout(&resource_manager.second_meshlet_cull_bind_group_layout),
1047            &BindGroupEntries::sequential((
1048                &view_resources.previous_depth_pyramid,
1049                view_uniforms.clone(),
1050                previous_view_uniforms.clone(),
1051                meshlet_mesh_manager.meshlet_cull_data.binding(),
1052                instance_manager.instance_uniforms.binding().unwrap(),
1053                view_resources
1054                    .visibility_buffer_software_raster_indirect_args
1055                    .as_entire_binding(),
1056                view_resources
1057                    .visibility_buffer_hardware_raster_indirect_args
1058                    .as_entire_binding(),
1059                resource_manager
1060                    .visibility_buffer_raster_cluster_prev_counts
1061                    .as_entire_binding(),
1062                resource_manager
1063                    .visibility_buffer_raster_clusters
1064                    .as_entire_binding(),
1065                view_resources.back_meshlet_cull_count.as_entire_binding(),
1066                view_resources.meshlet_cull_queue.as_entire_binding(),
1067            )),
1068        );
1069
1070        let downsample_depth = view_resources.depth_pyramid.create_bind_group(
1071            &render_device,
1072            "meshlet_downsample_depth_bind_group",
1073            &pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {
1074                &resource_manager.downsample_depth_bind_group_layout
1075            } else {
1076                &resource_manager.downsample_depth_shadow_view_bind_group_layout
1077            }),
1078            &view_resources.visibility_buffer.default_view,
1079            &resource_manager.depth_pyramid_sampler,
1080        );
1081
1082        let visibility_buffer_raster = render_device.create_bind_group(
1083            "meshlet_visibility_raster_buffer_bind_group",
1084            &pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {
1085                &resource_manager.visibility_buffer_raster_bind_group_layout
1086            } else {
1087                &resource_manager.visibility_buffer_raster_shadow_view_bind_group_layout
1088            }),
1089            &BindGroupEntries::sequential((
1090                resource_manager
1091                    .visibility_buffer_raster_clusters
1092                    .as_entire_binding(),
1093                meshlet_mesh_manager.meshlets.binding(),
1094                meshlet_mesh_manager.indices.binding(),
1095                meshlet_mesh_manager.vertex_positions.binding(),
1096                instance_manager.instance_uniforms.binding().unwrap(),
1097                resource_manager
1098                    .visibility_buffer_raster_cluster_prev_counts
1099                    .as_entire_binding(),
1100                resource_manager
1101                    .software_raster_cluster_count
1102                    .as_entire_binding(),
1103                &view_resources.visibility_buffer.default_view,
1104                view_uniforms.clone(),
1105            )),
1106        );
1107
1108        let resolve_depth = render_device.create_bind_group(
1109            "meshlet_resolve_depth_bind_group",
1110            &pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {
1111                &resource_manager.resolve_depth_bind_group_layout
1112            } else {
1113                &resource_manager.resolve_depth_shadow_view_bind_group_layout
1114            }),
1115            &BindGroupEntries::single(&view_resources.visibility_buffer.default_view),
1116        );
1117
1118        let resolve_material_depth = view_resources.material_depth.as_ref().map(|_| {
1119            render_device.create_bind_group(
1120                "meshlet_resolve_material_depth_bind_group",
1121                &pipeline_cache.get_bind_group_layout(
1122                    &resource_manager.resolve_material_depth_bind_group_layout,
1123                ),
1124                &BindGroupEntries::sequential((
1125                    &view_resources.visibility_buffer.default_view,
1126                    resource_manager
1127                        .visibility_buffer_raster_clusters
1128                        .as_entire_binding(),
1129                    instance_manager.instance_material_ids.binding().unwrap(),
1130                )),
1131            )
1132        });
1133
1134        let material_shade = view_resources.material_depth.as_ref().map(|_| {
1135            render_device.create_bind_group(
1136                "meshlet_mesh_material_shade_bind_group",
1137                &pipeline_cache
1138                    .get_bind_group_layout(&resource_manager.material_shade_bind_group_layout),
1139                &BindGroupEntries::sequential((
1140                    &view_resources.visibility_buffer.default_view,
1141                    resource_manager
1142                        .visibility_buffer_raster_clusters
1143                        .as_entire_binding(),
1144                    meshlet_mesh_manager.meshlets.binding(),
1145                    meshlet_mesh_manager.indices.binding(),
1146                    meshlet_mesh_manager.vertex_positions.binding(),
1147                    meshlet_mesh_manager.vertex_normals.binding(),
1148                    meshlet_mesh_manager.vertex_uvs.binding(),
1149                    instance_manager.instance_uniforms.binding().unwrap(),
1150                )),
1151            )
1152        });
1153
1154        let remap_1d_to_2d_dispatch = resource_manager
1155            .remap_1d_to_2d_dispatch_bind_group_layout
1156            .as_ref()
1157            .map(|layout| {
1158                render_device.create_bind_group(
1159                    "meshlet_remap_1d_to_2d_dispatch_bind_group",
1160                    &pipeline_cache.get_bind_group_layout(layout),
1161                    &BindGroupEntries::sequential((
1162                        view_resources
1163                            .visibility_buffer_software_raster_indirect_args
1164                            .as_entire_binding(),
1165                        resource_manager
1166                            .software_raster_cluster_count
1167                            .as_entire_binding(),
1168                    )),
1169                )
1170            });
1171
1172        let fill_counts = if resource_manager
1173            .remap_1d_to_2d_dispatch_bind_group_layout
1174            .is_some()
1175        {
1176            render_device.create_bind_group(
1177                "meshlet_fill_counts_bind_group",
1178                &pipeline_cache
1179                    .get_bind_group_layout(&resource_manager.fill_counts_bind_group_layout),
1180                &BindGroupEntries::sequential((
1181                    view_resources
1182                        .visibility_buffer_software_raster_indirect_args
1183                        .as_entire_binding(),
1184                    view_resources
1185                        .visibility_buffer_hardware_raster_indirect_args
1186                        .as_entire_binding(),
1187                    resource_manager
1188                        .visibility_buffer_raster_cluster_prev_counts
1189                        .as_entire_binding(),
1190                    resource_manager
1191                        .software_raster_cluster_count
1192                        .as_entire_binding(),
1193                )),
1194            )
1195        } else {
1196            render_device.create_bind_group(
1197                "meshlet_fill_counts_bind_group",
1198                &pipeline_cache
1199                    .get_bind_group_layout(&resource_manager.fill_counts_bind_group_layout),
1200                &BindGroupEntries::sequential((
1201                    view_resources
1202                        .visibility_buffer_software_raster_indirect_args
1203                        .as_entire_binding(),
1204                    view_resources
1205                        .visibility_buffer_hardware_raster_indirect_args
1206                        .as_entire_binding(),
1207                    resource_manager
1208                        .visibility_buffer_raster_cluster_prev_counts
1209                        .as_entire_binding(),
1210                )),
1211            )
1212        };
1213
1214        commands.entity(view_entity).insert(MeshletViewBindGroups {
1215            clear_visibility_buffer,
1216            first_instance_cull,
1217            second_instance_cull,
1218            first_bvh_cull_ping,
1219            first_bvh_cull_pong,
1220            second_bvh_cull_ping,
1221            second_bvh_cull_pong,
1222            first_meshlet_cull,
1223            second_meshlet_cull,
1224            downsample_depth,
1225            visibility_buffer_raster,
1226            resolve_depth,
1227            resolve_material_depth,
1228            material_shade,
1229            remap_1d_to_2d_dispatch,
1230            fill_counts,
1231        });
1232    }
1233}