Path: blob/main/crates/bevy_pbr/src/meshlet/resource_manager.rs
9441 views
use super::{instance_manager::InstanceManager, meshlet_mesh_manager::MeshletMeshManager};1use crate::ShadowView;2use bevy_camera::{visibility::RenderLayers, Camera3d};3use bevy_core_pipeline::{4mip_generation::experimental::depth::{self, ViewDepthPyramid},5prepass::{PreviousViewData, PreviousViewUniforms},6};7use bevy_ecs::{8component::Component,9entity::{Entity, EntityHashMap},10query::AnyOf,11resource::Resource,12system::{Commands, Query, Res, ResMut},13};14use bevy_image::ToExtents;15use bevy_math::{UVec2, Vec4Swizzles};16use bevy_render::{17render_resource::*,18renderer::{RenderDevice, RenderQueue},19texture::{CachedTexture, TextureCache},20view::{ExtractedView, ViewUniform, ViewUniforms},21};22use binding_types::*;23use core::iter;2425/// Manages per-view and per-cluster GPU resources for [`MeshletPlugin`](`super::MeshletPlugin`).26#[derive(Resource)]27pub struct ResourceManager {28/// Intermediate buffer of cluster IDs for use with rasterizing the visibility buffer29visibility_buffer_raster_clusters: Buffer,30/// Intermediate buffer of previous counts of clusters in rasterizer buckets31pub visibility_buffer_raster_cluster_prev_counts: Buffer,32/// Intermediate buffer of count of clusters to software rasterize33software_raster_cluster_count: Buffer,34/// BVH traversal queues35bvh_traversal_queues: [Buffer; 2],36/// Cluster cull candidate queue37cluster_cull_candidate_queue: Buffer,38/// Rightmost slot index of [`Self::visibility_buffer_raster_clusters`], [`Self::bvh_traversal_queues`], and [`Self::cluster_cull_candidate_queue`]39cull_queue_rightmost_slot: u32,4041/// Second pass instance candidates42second_pass_candidates: Option<Buffer>,43/// Sampler for a depth pyramid44depth_pyramid_sampler: Sampler,45/// Dummy texture view for binding depth pyramids with less than the maximum amount of mips46depth_pyramid_dummy_texture: TextureView,4748// TODO49previous_depth_pyramids: EntityHashMap<TextureView>,5051// Bind group layouts52pub clear_visibility_buffer_bind_group_layout: BindGroupLayoutDescriptor,53pub clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,54pub first_instance_cull_bind_group_layout: BindGroupLayoutDescriptor,55pub second_instance_cull_bind_group_layout: BindGroupLayoutDescriptor,56pub first_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor,57pub second_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor,58pub first_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor,59pub second_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor,60pub visibility_buffer_raster_bind_group_layout: BindGroupLayoutDescriptor,61pub visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,62pub downsample_depth_bind_group_layout: BindGroupLayoutDescriptor,63pub downsample_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,64pub resolve_depth_bind_group_layout: BindGroupLayoutDescriptor,65pub resolve_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor,66pub resolve_material_depth_bind_group_layout: BindGroupLayoutDescriptor,67pub material_shade_bind_group_layout: BindGroupLayoutDescriptor,68pub fill_counts_bind_group_layout: BindGroupLayoutDescriptor,69pub remap_1d_to_2d_dispatch_bind_group_layout: Option<BindGroupLayoutDescriptor>,70}7172impl ResourceManager {73pub fn new(cluster_buffer_slots: u32, render_device: &RenderDevice) -> Self {74let needs_dispatch_remap =75cluster_buffer_slots > render_device.limits().max_compute_workgroups_per_dimension;76// The IDs are a (u32, u32) of instance and index.77let cull_queue_size = 2 * cluster_buffer_slots as u64 * size_of::<u32>() as u64;7879Self {80visibility_buffer_raster_clusters: render_device.create_buffer(&BufferDescriptor {81label: Some("meshlet_visibility_buffer_raster_clusters"),82size: cull_queue_size,83usage: BufferUsages::STORAGE,84mapped_at_creation: false,85}),86visibility_buffer_raster_cluster_prev_counts: render_device.create_buffer(87&BufferDescriptor {88label: Some("meshlet_visibility_buffer_raster_cluster_prev_counts"),89size: size_of::<u32>() as u64 * 2,90usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,91mapped_at_creation: false,92},93),94software_raster_cluster_count: render_device.create_buffer(&BufferDescriptor {95label: Some("meshlet_software_raster_cluster_count"),96size: size_of::<u32>() as u64,97usage: BufferUsages::STORAGE,98mapped_at_creation: false,99}),100bvh_traversal_queues: [101render_device.create_buffer(&BufferDescriptor {102label: Some("meshlet_bvh_traversal_queue_0"),103size: cull_queue_size,104usage: BufferUsages::STORAGE,105mapped_at_creation: false,106}),107render_device.create_buffer(&BufferDescriptor {108label: Some("meshlet_bvh_traversal_queue_1"),109size: cull_queue_size,110usage: BufferUsages::STORAGE,111mapped_at_creation: false,112}),113],114cluster_cull_candidate_queue: render_device.create_buffer(&BufferDescriptor {115label: Some("meshlet_cluster_cull_candidate_queue"),116size: cull_queue_size,117usage: BufferUsages::STORAGE,118mapped_at_creation: false,119}),120cull_queue_rightmost_slot: cluster_buffer_slots - 1,121122second_pass_candidates: None,123depth_pyramid_sampler: render_device.create_sampler(&SamplerDescriptor {124label: Some("meshlet_depth_pyramid_sampler"),125..SamplerDescriptor::default()126}),127depth_pyramid_dummy_texture: depth::create_depth_pyramid_dummy_texture(128render_device,129"meshlet_depth_pyramid_dummy_texture",130"meshlet_depth_pyramid_dummy_texture_view",131),132133previous_depth_pyramids: EntityHashMap::default(),134135// TODO: Buffer min sizes136clear_visibility_buffer_bind_group_layout: BindGroupLayoutDescriptor::new(137"meshlet_clear_visibility_buffer_bind_group_layout",138&BindGroupLayoutEntries::single(139ShaderStages::COMPUTE,140texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::WriteOnly),141),142),143clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(144"meshlet_clear_visibility_buffer_shadow_view_bind_group_layout",145&BindGroupLayoutEntries::single(146ShaderStages::COMPUTE,147texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),148),149),150first_instance_cull_bind_group_layout: BindGroupLayoutDescriptor::new(151"meshlet_first_instance_culling_bind_group_layout",152&BindGroupLayoutEntries::sequential(153ShaderStages::COMPUTE,154(155texture_2d(TextureSampleType::Float { filterable: false }),156uniform_buffer::<ViewUniform>(true),157uniform_buffer::<PreviousViewData>(true),158storage_buffer_read_only_sized(false, None),159storage_buffer_read_only_sized(false, None),160storage_buffer_read_only_sized(false, None),161storage_buffer_read_only_sized(false, None),162storage_buffer_sized(false, None),163storage_buffer_sized(false, None),164storage_buffer_sized(false, None),165storage_buffer_sized(false, None),166storage_buffer_sized(false, None),167storage_buffer_sized(false, None),168),169),170),171second_instance_cull_bind_group_layout: BindGroupLayoutDescriptor::new(172"meshlet_second_instance_culling_bind_group_layout",173&BindGroupLayoutEntries::sequential(174ShaderStages::COMPUTE,175(176texture_2d(TextureSampleType::Float { filterable: false }),177uniform_buffer::<ViewUniform>(true),178uniform_buffer::<PreviousViewData>(true),179storage_buffer_read_only_sized(false, None),180storage_buffer_read_only_sized(false, None),181storage_buffer_read_only_sized(false, None),182storage_buffer_read_only_sized(false, None),183storage_buffer_sized(false, None),184storage_buffer_sized(false, None),185storage_buffer_sized(false, None),186storage_buffer_read_only_sized(false, None),187storage_buffer_read_only_sized(false, None),188),189),190),191first_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor::new(192"meshlet_first_bvh_culling_bind_group_layout",193&BindGroupLayoutEntries::sequential(194ShaderStages::COMPUTE,195(196texture_2d(TextureSampleType::Float { filterable: false }),197uniform_buffer::<ViewUniform>(true),198uniform_buffer::<PreviousViewData>(true),199storage_buffer_read_only_sized(false, None),200storage_buffer_read_only_sized(false, None),201storage_buffer_read_only_sized(false, None),202storage_buffer_sized(false, None),203storage_buffer_sized(false, None),204storage_buffer_sized(false, None),205storage_buffer_sized(false, None),206storage_buffer_sized(false, None),207storage_buffer_sized(false, None),208storage_buffer_sized(false, None),209storage_buffer_sized(false, None),210storage_buffer_sized(false, None),211storage_buffer_sized(false, None),212storage_buffer_sized(false, None),213),214),215),216second_bvh_cull_bind_group_layout: BindGroupLayoutDescriptor::new(217"meshlet_second_bvh_culling_bind_group_layout",218&BindGroupLayoutEntries::sequential(219ShaderStages::COMPUTE,220(221texture_2d(TextureSampleType::Float { filterable: false }),222uniform_buffer::<ViewUniform>(true),223uniform_buffer::<PreviousViewData>(true),224storage_buffer_read_only_sized(false, None),225storage_buffer_read_only_sized(false, None),226storage_buffer_read_only_sized(false, None),227storage_buffer_sized(false, None),228storage_buffer_sized(false, None),229storage_buffer_sized(false, None),230storage_buffer_sized(false, None),231storage_buffer_sized(false, None),232storage_buffer_sized(false, None),233storage_buffer_sized(false, None),234storage_buffer_sized(false, None),235),236),237),238first_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor::new(239"meshlet_first_meshlet_culling_bind_group_layout",240&BindGroupLayoutEntries::sequential(241ShaderStages::COMPUTE,242(243texture_2d(TextureSampleType::Float { filterable: false }),244uniform_buffer::<ViewUniform>(true),245uniform_buffer::<PreviousViewData>(true),246storage_buffer_read_only_sized(false, None),247storage_buffer_read_only_sized(false, None),248storage_buffer_sized(false, None),249storage_buffer_sized(false, None),250storage_buffer_read_only_sized(false, None),251storage_buffer_sized(false, None),252storage_buffer_read_only_sized(false, None),253storage_buffer_sized(false, None),254storage_buffer_sized(false, None),255storage_buffer_sized(false, None),256),257),258),259second_meshlet_cull_bind_group_layout: BindGroupLayoutDescriptor::new(260"meshlet_second_meshlet_culling_bind_group_layout",261&BindGroupLayoutEntries::sequential(262ShaderStages::COMPUTE,263(264texture_2d(TextureSampleType::Float { filterable: false }),265uniform_buffer::<ViewUniform>(true),266uniform_buffer::<PreviousViewData>(true),267storage_buffer_read_only_sized(false, None),268storage_buffer_read_only_sized(false, None),269storage_buffer_sized(false, None),270storage_buffer_sized(false, None),271storage_buffer_read_only_sized(false, None),272storage_buffer_sized(false, None),273storage_buffer_read_only_sized(false, None),274storage_buffer_read_only_sized(false, None),275),276),277),278downsample_depth_bind_group_layout: BindGroupLayoutDescriptor::new(279"meshlet_downsample_depth_bind_group_layout",280&BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {281let write_only_r32float = || {282texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)283};284(285texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),286write_only_r32float(),287write_only_r32float(),288write_only_r32float(),289write_only_r32float(),290write_only_r32float(),291texture_storage_2d(292TextureFormat::R32Float,293StorageTextureAccess::ReadWrite,294),295write_only_r32float(),296write_only_r32float(),297write_only_r32float(),298write_only_r32float(),299write_only_r32float(),300write_only_r32float(),301sampler(SamplerBindingType::NonFiltering),302)303}),304),305downsample_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(306"meshlet_downsample_depth_shadow_view_bind_group_layout",307&BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {308let write_only_r32float = || {309texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)310};311(312texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),313write_only_r32float(),314write_only_r32float(),315write_only_r32float(),316write_only_r32float(),317write_only_r32float(),318texture_storage_2d(319TextureFormat::R32Float,320StorageTextureAccess::ReadWrite,321),322write_only_r32float(),323write_only_r32float(),324write_only_r32float(),325write_only_r32float(),326write_only_r32float(),327write_only_r32float(),328sampler(SamplerBindingType::NonFiltering),329)330}),331),332visibility_buffer_raster_bind_group_layout: BindGroupLayoutDescriptor::new(333"meshlet_visibility_buffer_raster_bind_group_layout",334&BindGroupLayoutEntries::sequential(335ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,336(337storage_buffer_read_only_sized(false, None),338storage_buffer_read_only_sized(false, None),339storage_buffer_read_only_sized(false, None),340storage_buffer_read_only_sized(false, None),341storage_buffer_read_only_sized(false, None),342storage_buffer_read_only_sized(false, None),343storage_buffer_read_only_sized(false, None),344texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::Atomic),345uniform_buffer::<ViewUniform>(true),346),347),348),349visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(350"meshlet_visibility_buffer_raster_shadow_view_bind_group_layout",351&BindGroupLayoutEntries::sequential(352ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,353(354storage_buffer_read_only_sized(false, None),355storage_buffer_read_only_sized(false, None),356storage_buffer_read_only_sized(false, None),357storage_buffer_read_only_sized(false, None),358storage_buffer_read_only_sized(false, None),359storage_buffer_read_only_sized(false, None),360storage_buffer_read_only_sized(false, None),361texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::Atomic),362uniform_buffer::<ViewUniform>(true),363),364),365),366resolve_depth_bind_group_layout: BindGroupLayoutDescriptor::new(367"meshlet_resolve_depth_bind_group_layout",368&BindGroupLayoutEntries::single(369ShaderStages::FRAGMENT,370texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),371),372),373resolve_depth_shadow_view_bind_group_layout: BindGroupLayoutDescriptor::new(374"meshlet_resolve_depth_shadow_view_bind_group_layout",375&BindGroupLayoutEntries::single(376ShaderStages::FRAGMENT,377texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),378),379),380resolve_material_depth_bind_group_layout: BindGroupLayoutDescriptor::new(381"meshlet_resolve_material_depth_bind_group_layout",382&BindGroupLayoutEntries::sequential(383ShaderStages::FRAGMENT,384(385texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),386storage_buffer_read_only_sized(false, None),387storage_buffer_read_only_sized(false, None),388),389),390),391material_shade_bind_group_layout: BindGroupLayoutDescriptor::new(392"meshlet_mesh_material_shade_bind_group_layout",393&BindGroupLayoutEntries::sequential(394ShaderStages::FRAGMENT,395(396texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),397storage_buffer_read_only_sized(false, None),398storage_buffer_read_only_sized(false, None),399storage_buffer_read_only_sized(false, None),400storage_buffer_read_only_sized(false, None),401storage_buffer_read_only_sized(false, None),402storage_buffer_read_only_sized(false, None),403storage_buffer_read_only_sized(false, None),404),405),406),407fill_counts_bind_group_layout: if needs_dispatch_remap {408BindGroupLayoutDescriptor::new(409"meshlet_fill_counts_bind_group_layout",410&BindGroupLayoutEntries::sequential(411ShaderStages::COMPUTE,412(413storage_buffer_sized(false, None),414storage_buffer_sized(false, None),415storage_buffer_sized(false, None),416storage_buffer_sized(false, None),417),418),419)420} else {421BindGroupLayoutDescriptor::new(422"meshlet_fill_counts_bind_group_layout",423&BindGroupLayoutEntries::sequential(424ShaderStages::COMPUTE,425(426storage_buffer_sized(false, None),427storage_buffer_sized(false, None),428storage_buffer_sized(false, None),429),430),431)432},433remap_1d_to_2d_dispatch_bind_group_layout: needs_dispatch_remap.then(|| {434BindGroupLayoutDescriptor::new(435"meshlet_remap_1d_to_2d_dispatch_bind_group_layout",436&BindGroupLayoutEntries::sequential(437ShaderStages::COMPUTE,438(439storage_buffer_sized(false, None),440storage_buffer_sized(false, None),441),442),443)444}),445}446}447}448449// ------------ TODO: Everything under here needs to be rewritten and cached ------------450451#[derive(Component)]452pub struct MeshletViewResources {453pub scene_instance_count: u32,454pub rightmost_slot: u32,455pub max_bvh_depth: u32,456instance_visibility: Buffer,457pub dummy_render_target: CachedTexture,458pub visibility_buffer: CachedTexture,459pub second_pass_count: Buffer,460pub second_pass_dispatch: Buffer,461pub second_pass_candidates: Buffer,462pub first_bvh_cull_count_front: Buffer,463pub first_bvh_cull_dispatch_front: Buffer,464pub first_bvh_cull_count_back: Buffer,465pub first_bvh_cull_dispatch_back: Buffer,466pub first_bvh_cull_queue: Buffer,467pub second_bvh_cull_count_front: Buffer,468pub second_bvh_cull_dispatch_front: Buffer,469pub second_bvh_cull_count_back: Buffer,470pub second_bvh_cull_dispatch_back: Buffer,471pub second_bvh_cull_queue: Buffer,472pub front_meshlet_cull_count: Buffer,473pub front_meshlet_cull_dispatch: Buffer,474pub back_meshlet_cull_count: Buffer,475pub back_meshlet_cull_dispatch: Buffer,476pub meshlet_cull_queue: Buffer,477pub visibility_buffer_software_raster_indirect_args: Buffer,478pub visibility_buffer_hardware_raster_indirect_args: Buffer,479pub depth_pyramid: ViewDepthPyramid,480previous_depth_pyramid: TextureView,481pub material_depth: Option<CachedTexture>,482pub view_size: UVec2,483not_shadow_view: bool,484}485486#[derive(Component)]487pub struct MeshletViewBindGroups {488pub clear_visibility_buffer: BindGroup,489pub first_instance_cull: BindGroup,490pub second_instance_cull: BindGroup,491pub first_bvh_cull_ping: BindGroup,492pub first_bvh_cull_pong: BindGroup,493pub second_bvh_cull_ping: BindGroup,494pub second_bvh_cull_pong: BindGroup,495pub first_meshlet_cull: BindGroup,496pub second_meshlet_cull: BindGroup,497pub downsample_depth: BindGroup,498pub visibility_buffer_raster: BindGroup,499pub resolve_depth: BindGroup,500pub resolve_material_depth: Option<BindGroup>,501pub material_shade: Option<BindGroup>,502pub remap_1d_to_2d_dispatch: Option<BindGroup>,503pub fill_counts: BindGroup,504}505506// TODO: Cache things per-view and skip running this system / optimize this system507pub fn prepare_meshlet_per_frame_resources(508mut resource_manager: ResMut<ResourceManager>,509mut instance_manager: ResMut<InstanceManager>,510views: Query<(511Entity,512&ExtractedView,513Option<&RenderLayers>,514AnyOf<(&Camera3d, &ShadowView)>,515)>,516mut texture_cache: ResMut<TextureCache>,517render_queue: Res<RenderQueue>,518render_device: Res<RenderDevice>,519mut commands: Commands,520) {521if instance_manager.scene_instance_count == 0 {522return;523}524525let instance_manager = instance_manager.as_mut();526527// TODO: Move this and the submit to a separate system and remove pub from the fields528instance_manager529.instance_uniforms530.write_buffer(&render_device, &render_queue);531instance_manager532.instance_aabbs533.write_buffer(&render_device, &render_queue);534instance_manager535.instance_material_ids536.write_buffer(&render_device, &render_queue);537instance_manager538.instance_bvh_root_nodes539.write_buffer(&render_device, &render_queue);540541let needed_buffer_size = 4 * instance_manager.scene_instance_count as u64;542let second_pass_candidates = match &mut resource_manager.second_pass_candidates {543Some(buffer) if buffer.size() >= needed_buffer_size => buffer.clone(),544slot => {545let buffer = render_device.create_buffer(&BufferDescriptor {546label: Some("meshlet_second_pass_candidates"),547size: needed_buffer_size,548usage: BufferUsages::STORAGE,549mapped_at_creation: false,550});551*slot = Some(buffer.clone());552buffer553}554};555556for (view_entity, view, render_layers, (_, shadow_view)) in &views {557let not_shadow_view = shadow_view.is_none();558559let instance_visibility = instance_manager560.view_instance_visibility561.entry(view_entity)562.or_insert_with(|| {563let mut buffer = StorageBuffer::default();564buffer.set_label(Some("meshlet_view_instance_visibility"));565buffer566});567for (instance_index, (_, layers, not_shadow_caster)) in568instance_manager.instances.iter().enumerate()569{570// If either the layers don't match the view's layers or this is a shadow view571// and the instance is not a shadow caster, hide the instance for this view572if !render_layers573.unwrap_or(&RenderLayers::default())574.intersects(layers)575|| (shadow_view.is_some() && *not_shadow_caster)576{577let vec = instance_visibility.get_mut();578let index = instance_index / 32;579let bit = instance_index - index * 32;580if vec.len() <= index {581vec.extend(iter::repeat_n(0, index - vec.len() + 1));582}583vec[index] |= 1 << bit;584}585}586instance_visibility.write_buffer(&render_device, &render_queue);587let instance_visibility = instance_visibility.buffer().unwrap().clone();588589// TODO: Remove this once wgpu allows render passes with no attachments590let dummy_render_target = texture_cache.get(591&render_device,592TextureDescriptor {593label: Some("meshlet_dummy_render_target"),594size: view.viewport.zw().to_extents(),595mip_level_count: 1,596sample_count: 1,597dimension: TextureDimension::D2,598format: TextureFormat::R8Uint,599usage: TextureUsages::RENDER_ATTACHMENT,600view_formats: &[],601},602);603604let visibility_buffer = texture_cache.get(605&render_device,606TextureDescriptor {607label: Some("meshlet_visibility_buffer"),608size: view.viewport.zw().to_extents(),609mip_level_count: 1,610sample_count: 1,611dimension: TextureDimension::D2,612format: if not_shadow_view {613TextureFormat::R64Uint614} else {615TextureFormat::R32Uint616},617usage: TextureUsages::STORAGE_ATOMIC | TextureUsages::STORAGE_BINDING,618view_formats: &[],619},620);621622let second_pass_count = render_device.create_buffer_with_data(&BufferInitDescriptor {623label: Some("meshlet_second_pass_count"),624contents: bytemuck::bytes_of(&0u32),625usage: BufferUsages::STORAGE,626});627let second_pass_dispatch = render_device.create_buffer_with_data(&BufferInitDescriptor {628label: Some("meshlet_second_pass_dispatch"),629contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),630usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,631});632633let first_bvh_cull_count_front =634render_device.create_buffer_with_data(&BufferInitDescriptor {635label: Some("meshlet_first_bvh_cull_count_front"),636contents: bytemuck::bytes_of(&0u32),637usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,638});639let first_bvh_cull_dispatch_front =640render_device.create_buffer_with_data(&BufferInitDescriptor {641label: Some("meshlet_first_bvh_cull_dispatch_front"),642contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),643usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,644});645let first_bvh_cull_count_back =646render_device.create_buffer_with_data(&BufferInitDescriptor {647label: Some("meshlet_first_bvh_cull_count_back"),648contents: bytemuck::bytes_of(&0u32),649usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,650});651let first_bvh_cull_dispatch_back =652render_device.create_buffer_with_data(&BufferInitDescriptor {653label: Some("meshlet_first_bvh_cull_dispatch_back"),654contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),655usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,656});657658let second_bvh_cull_count_front =659render_device.create_buffer_with_data(&BufferInitDescriptor {660label: Some("meshlet_second_bvh_cull_count_front"),661contents: bytemuck::bytes_of(&0u32),662usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,663});664let second_bvh_cull_dispatch_front =665render_device.create_buffer_with_data(&BufferInitDescriptor {666label: Some("meshlet_second_bvh_cull_dispatch_front"),667contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),668usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,669});670let second_bvh_cull_count_back =671render_device.create_buffer_with_data(&BufferInitDescriptor {672label: Some("meshlet_second_bvh_cull_count_back"),673contents: bytemuck::bytes_of(&0u32),674usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,675});676let second_bvh_cull_dispatch_back =677render_device.create_buffer_with_data(&BufferInitDescriptor {678label: Some("meshlet_second_bvh_cull_dispatch_back"),679contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),680usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,681});682683let front_meshlet_cull_count =684render_device.create_buffer_with_data(&BufferInitDescriptor {685label: Some("meshlet_front_meshlet_cull_count"),686contents: bytemuck::bytes_of(&0u32),687usage: BufferUsages::STORAGE,688});689let front_meshlet_cull_dispatch =690render_device.create_buffer_with_data(&BufferInitDescriptor {691label: Some("meshlet_front_meshlet_cull_dispatch"),692contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),693usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,694});695let back_meshlet_cull_count =696render_device.create_buffer_with_data(&BufferInitDescriptor {697label: Some("meshlet_back_meshlet_cull_count"),698contents: bytemuck::bytes_of(&0u32),699usage: BufferUsages::STORAGE,700});701let back_meshlet_cull_dispatch =702render_device.create_buffer_with_data(&BufferInitDescriptor {703label: Some("meshlet_back_meshlet_cull_dispatch"),704contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),705usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,706});707708let visibility_buffer_software_raster_indirect_args = render_device709.create_buffer_with_data(&BufferInitDescriptor {710label: Some("meshlet_visibility_buffer_software_raster_indirect_args"),711contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),712usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,713});714715let visibility_buffer_hardware_raster_indirect_args = render_device716.create_buffer_with_data(&BufferInitDescriptor {717label: Some("meshlet_visibility_buffer_hardware_raster_indirect_args"),718contents: DrawIndirectArgs {719vertex_count: 128 * 3,720instance_count: 0,721first_vertex: 0,722first_instance: 0,723}724.as_bytes(),725usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,726});727728let depth_pyramid = ViewDepthPyramid::new(729&render_device,730&mut texture_cache,731&resource_manager.depth_pyramid_dummy_texture,732view.viewport.zw(),733"meshlet_depth_pyramid",734"meshlet_depth_pyramid_texture_view",735);736737let previous_depth_pyramid =738match resource_manager.previous_depth_pyramids.get(&view_entity) {739Some(texture_view) => texture_view.clone(),740None => depth_pyramid.all_mips.clone(),741};742resource_manager743.previous_depth_pyramids744.insert(view_entity, depth_pyramid.all_mips.clone());745746let material_depth = TextureDescriptor {747label: Some("meshlet_material_depth"),748size: view.viewport.zw().to_extents(),749mip_level_count: 1,750sample_count: 1,751dimension: TextureDimension::D2,752format: TextureFormat::Depth16Unorm,753usage: TextureUsages::RENDER_ATTACHMENT,754view_formats: &[],755};756757commands.entity(view_entity).insert(MeshletViewResources {758scene_instance_count: instance_manager.scene_instance_count,759rightmost_slot: resource_manager.cull_queue_rightmost_slot,760max_bvh_depth: instance_manager.max_bvh_depth,761instance_visibility,762dummy_render_target,763visibility_buffer,764second_pass_count,765second_pass_dispatch,766second_pass_candidates: second_pass_candidates.clone(),767first_bvh_cull_count_front,768first_bvh_cull_dispatch_front,769first_bvh_cull_count_back,770first_bvh_cull_dispatch_back,771first_bvh_cull_queue: resource_manager.bvh_traversal_queues[0].clone(),772second_bvh_cull_count_front,773second_bvh_cull_dispatch_front,774second_bvh_cull_count_back,775second_bvh_cull_dispatch_back,776second_bvh_cull_queue: resource_manager.bvh_traversal_queues[1].clone(),777front_meshlet_cull_count,778front_meshlet_cull_dispatch,779back_meshlet_cull_count,780back_meshlet_cull_dispatch,781meshlet_cull_queue: resource_manager.cluster_cull_candidate_queue.clone(),782visibility_buffer_software_raster_indirect_args,783visibility_buffer_hardware_raster_indirect_args,784depth_pyramid,785previous_depth_pyramid,786material_depth: not_shadow_view787.then(|| texture_cache.get(&render_device, material_depth)),788view_size: view.viewport.zw(),789not_shadow_view,790});791}792}793794pub fn prepare_meshlet_view_bind_groups(795meshlet_mesh_manager: Res<MeshletMeshManager>,796resource_manager: Res<ResourceManager>,797instance_manager: Res<InstanceManager>,798views: Query<(Entity, &MeshletViewResources)>,799view_uniforms: Res<ViewUniforms>,800previous_view_uniforms: Res<PreviousViewUniforms>,801render_device: Res<RenderDevice>,802pipeline_cache: Res<PipelineCache>,803mut commands: Commands,804) {805let (Some(view_uniforms), Some(previous_view_uniforms)) = (806view_uniforms.uniforms.binding(),807previous_view_uniforms.uniforms.binding(),808) else {809return;810};811812// TODO: Some of these bind groups can be reused across multiple views813for (view_entity, view_resources) in &views {814let clear_visibility_buffer = render_device.create_bind_group(815"meshlet_clear_visibility_buffer_bind_group",816&pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {817&resource_manager.clear_visibility_buffer_bind_group_layout818} else {819&resource_manager.clear_visibility_buffer_shadow_view_bind_group_layout820}),821&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),822);823824let first_instance_cull = render_device.create_bind_group(825"meshlet_first_instance_cull_bind_group",826&pipeline_cache827.get_bind_group_layout(&resource_manager.first_instance_cull_bind_group_layout),828&BindGroupEntries::sequential((829&view_resources.previous_depth_pyramid,830view_uniforms.clone(),831previous_view_uniforms.clone(),832instance_manager.instance_uniforms.binding().unwrap(),833view_resources.instance_visibility.as_entire_binding(),834instance_manager.instance_aabbs.binding().unwrap(),835instance_manager.instance_bvh_root_nodes.binding().unwrap(),836view_resources837.first_bvh_cull_count_front838.as_entire_binding(),839view_resources840.first_bvh_cull_dispatch_front841.as_entire_binding(),842view_resources.first_bvh_cull_queue.as_entire_binding(),843view_resources.second_pass_count.as_entire_binding(),844view_resources.second_pass_dispatch.as_entire_binding(),845view_resources.second_pass_candidates.as_entire_binding(),846)),847);848849let second_instance_cull = render_device.create_bind_group(850"meshlet_second_instance_cull_bind_group",851&pipeline_cache852.get_bind_group_layout(&resource_manager.second_instance_cull_bind_group_layout),853&BindGroupEntries::sequential((854&view_resources.previous_depth_pyramid,855view_uniforms.clone(),856previous_view_uniforms.clone(),857instance_manager.instance_uniforms.binding().unwrap(),858view_resources.instance_visibility.as_entire_binding(),859instance_manager.instance_aabbs.binding().unwrap(),860instance_manager.instance_bvh_root_nodes.binding().unwrap(),861view_resources862.second_bvh_cull_count_front863.as_entire_binding(),864view_resources865.second_bvh_cull_dispatch_front866.as_entire_binding(),867view_resources.second_bvh_cull_queue.as_entire_binding(),868view_resources.second_pass_count.as_entire_binding(),869view_resources.second_pass_candidates.as_entire_binding(),870)),871);872873let first_bvh_cull_ping = render_device.create_bind_group(874"meshlet_first_bvh_cull_ping_bind_group",875&pipeline_cache876.get_bind_group_layout(&resource_manager.first_bvh_cull_bind_group_layout),877&BindGroupEntries::sequential((878&view_resources.previous_depth_pyramid,879view_uniforms.clone(),880previous_view_uniforms.clone(),881meshlet_mesh_manager.bvh_nodes.binding(),882instance_manager.instance_uniforms.binding().unwrap(),883view_resources884.first_bvh_cull_count_front885.as_entire_binding(),886view_resources.first_bvh_cull_count_back.as_entire_binding(),887view_resources888.first_bvh_cull_dispatch_back889.as_entire_binding(),890view_resources.first_bvh_cull_queue.as_entire_binding(),891view_resources.front_meshlet_cull_count.as_entire_binding(),892view_resources.back_meshlet_cull_count.as_entire_binding(),893view_resources894.front_meshlet_cull_dispatch895.as_entire_binding(),896view_resources897.back_meshlet_cull_dispatch898.as_entire_binding(),899view_resources.meshlet_cull_queue.as_entire_binding(),900view_resources901.second_bvh_cull_count_front902.as_entire_binding(),903view_resources904.second_bvh_cull_dispatch_front905.as_entire_binding(),906view_resources.second_bvh_cull_queue.as_entire_binding(),907)),908);909910let first_bvh_cull_pong = render_device.create_bind_group(911"meshlet_first_bvh_cull_pong_bind_group",912&pipeline_cache913.get_bind_group_layout(&resource_manager.first_bvh_cull_bind_group_layout),914&BindGroupEntries::sequential((915&view_resources.previous_depth_pyramid,916view_uniforms.clone(),917previous_view_uniforms.clone(),918meshlet_mesh_manager.bvh_nodes.binding(),919instance_manager.instance_uniforms.binding().unwrap(),920view_resources.first_bvh_cull_count_back.as_entire_binding(),921view_resources922.first_bvh_cull_count_front923.as_entire_binding(),924view_resources925.first_bvh_cull_dispatch_front926.as_entire_binding(),927view_resources.first_bvh_cull_queue.as_entire_binding(),928view_resources.front_meshlet_cull_count.as_entire_binding(),929view_resources.back_meshlet_cull_count.as_entire_binding(),930view_resources931.front_meshlet_cull_dispatch932.as_entire_binding(),933view_resources934.back_meshlet_cull_dispatch935.as_entire_binding(),936view_resources.meshlet_cull_queue.as_entire_binding(),937view_resources938.second_bvh_cull_count_front939.as_entire_binding(),940view_resources941.second_bvh_cull_dispatch_front942.as_entire_binding(),943view_resources.second_bvh_cull_queue.as_entire_binding(),944)),945);946947let second_bvh_cull_ping = render_device.create_bind_group(948"meshlet_second_bvh_cull_ping_bind_group",949&pipeline_cache950.get_bind_group_layout(&resource_manager.second_bvh_cull_bind_group_layout),951&BindGroupEntries::sequential((952&view_resources.previous_depth_pyramid,953view_uniforms.clone(),954previous_view_uniforms.clone(),955meshlet_mesh_manager.bvh_nodes.binding(),956instance_manager.instance_uniforms.binding().unwrap(),957view_resources958.second_bvh_cull_count_front959.as_entire_binding(),960view_resources961.second_bvh_cull_count_back962.as_entire_binding(),963view_resources964.second_bvh_cull_dispatch_back965.as_entire_binding(),966view_resources.second_bvh_cull_queue.as_entire_binding(),967view_resources.front_meshlet_cull_count.as_entire_binding(),968view_resources.back_meshlet_cull_count.as_entire_binding(),969view_resources970.front_meshlet_cull_dispatch971.as_entire_binding(),972view_resources973.back_meshlet_cull_dispatch974.as_entire_binding(),975view_resources.meshlet_cull_queue.as_entire_binding(),976)),977);978979let second_bvh_cull_pong = render_device.create_bind_group(980"meshlet_second_bvh_cull_pong_bind_group",981&pipeline_cache982.get_bind_group_layout(&resource_manager.second_bvh_cull_bind_group_layout),983&BindGroupEntries::sequential((984&view_resources.previous_depth_pyramid,985view_uniforms.clone(),986previous_view_uniforms.clone(),987meshlet_mesh_manager.bvh_nodes.binding(),988instance_manager.instance_uniforms.binding().unwrap(),989view_resources990.second_bvh_cull_count_back991.as_entire_binding(),992view_resources993.second_bvh_cull_count_front994.as_entire_binding(),995view_resources996.second_bvh_cull_dispatch_front997.as_entire_binding(),998view_resources.second_bvh_cull_queue.as_entire_binding(),999view_resources.front_meshlet_cull_count.as_entire_binding(),1000view_resources.back_meshlet_cull_count.as_entire_binding(),1001view_resources1002.front_meshlet_cull_dispatch1003.as_entire_binding(),1004view_resources1005.back_meshlet_cull_dispatch1006.as_entire_binding(),1007view_resources.meshlet_cull_queue.as_entire_binding(),1008)),1009);10101011let first_meshlet_cull = render_device.create_bind_group(1012"meshlet_first_meshlet_cull_bind_group",1013&pipeline_cache1014.get_bind_group_layout(&resource_manager.first_meshlet_cull_bind_group_layout),1015&BindGroupEntries::sequential((1016&view_resources.previous_depth_pyramid,1017view_uniforms.clone(),1018previous_view_uniforms.clone(),1019meshlet_mesh_manager.meshlet_cull_data.binding(),1020instance_manager.instance_uniforms.binding().unwrap(),1021view_resources1022.visibility_buffer_software_raster_indirect_args1023.as_entire_binding(),1024view_resources1025.visibility_buffer_hardware_raster_indirect_args1026.as_entire_binding(),1027resource_manager1028.visibility_buffer_raster_cluster_prev_counts1029.as_entire_binding(),1030resource_manager1031.visibility_buffer_raster_clusters1032.as_entire_binding(),1033view_resources.front_meshlet_cull_count.as_entire_binding(),1034view_resources.back_meshlet_cull_count.as_entire_binding(),1035view_resources1036.back_meshlet_cull_dispatch1037.as_entire_binding(),1038view_resources.meshlet_cull_queue.as_entire_binding(),1039)),1040);10411042let second_meshlet_cull = render_device.create_bind_group(1043"meshlet_second_meshlet_cull_bind_group",1044&pipeline_cache1045.get_bind_group_layout(&resource_manager.second_meshlet_cull_bind_group_layout),1046&BindGroupEntries::sequential((1047&view_resources.previous_depth_pyramid,1048view_uniforms.clone(),1049previous_view_uniforms.clone(),1050meshlet_mesh_manager.meshlet_cull_data.binding(),1051instance_manager.instance_uniforms.binding().unwrap(),1052view_resources1053.visibility_buffer_software_raster_indirect_args1054.as_entire_binding(),1055view_resources1056.visibility_buffer_hardware_raster_indirect_args1057.as_entire_binding(),1058resource_manager1059.visibility_buffer_raster_cluster_prev_counts1060.as_entire_binding(),1061resource_manager1062.visibility_buffer_raster_clusters1063.as_entire_binding(),1064view_resources.back_meshlet_cull_count.as_entire_binding(),1065view_resources.meshlet_cull_queue.as_entire_binding(),1066)),1067);10681069let downsample_depth = view_resources.depth_pyramid.create_bind_group(1070&render_device,1071"meshlet_downsample_depth_bind_group",1072&pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {1073&resource_manager.downsample_depth_bind_group_layout1074} else {1075&resource_manager.downsample_depth_shadow_view_bind_group_layout1076}),1077&view_resources.visibility_buffer.default_view,1078&resource_manager.depth_pyramid_sampler,1079);10801081let visibility_buffer_raster = render_device.create_bind_group(1082"meshlet_visibility_raster_buffer_bind_group",1083&pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {1084&resource_manager.visibility_buffer_raster_bind_group_layout1085} else {1086&resource_manager.visibility_buffer_raster_shadow_view_bind_group_layout1087}),1088&BindGroupEntries::sequential((1089resource_manager1090.visibility_buffer_raster_clusters1091.as_entire_binding(),1092meshlet_mesh_manager.meshlets.binding(),1093meshlet_mesh_manager.indices.binding(),1094meshlet_mesh_manager.vertex_positions.binding(),1095instance_manager.instance_uniforms.binding().unwrap(),1096resource_manager1097.visibility_buffer_raster_cluster_prev_counts1098.as_entire_binding(),1099resource_manager1100.software_raster_cluster_count1101.as_entire_binding(),1102&view_resources.visibility_buffer.default_view,1103view_uniforms.clone(),1104)),1105);11061107let resolve_depth = render_device.create_bind_group(1108"meshlet_resolve_depth_bind_group",1109&pipeline_cache.get_bind_group_layout(if view_resources.not_shadow_view {1110&resource_manager.resolve_depth_bind_group_layout1111} else {1112&resource_manager.resolve_depth_shadow_view_bind_group_layout1113}),1114&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),1115);11161117let resolve_material_depth = view_resources.material_depth.as_ref().map(|_| {1118render_device.create_bind_group(1119"meshlet_resolve_material_depth_bind_group",1120&pipeline_cache.get_bind_group_layout(1121&resource_manager.resolve_material_depth_bind_group_layout,1122),1123&BindGroupEntries::sequential((1124&view_resources.visibility_buffer.default_view,1125resource_manager1126.visibility_buffer_raster_clusters1127.as_entire_binding(),1128instance_manager.instance_material_ids.binding().unwrap(),1129)),1130)1131});11321133let material_shade = view_resources.material_depth.as_ref().map(|_| {1134render_device.create_bind_group(1135"meshlet_mesh_material_shade_bind_group",1136&pipeline_cache1137.get_bind_group_layout(&resource_manager.material_shade_bind_group_layout),1138&BindGroupEntries::sequential((1139&view_resources.visibility_buffer.default_view,1140resource_manager1141.visibility_buffer_raster_clusters1142.as_entire_binding(),1143meshlet_mesh_manager.meshlets.binding(),1144meshlet_mesh_manager.indices.binding(),1145meshlet_mesh_manager.vertex_positions.binding(),1146meshlet_mesh_manager.vertex_normals.binding(),1147meshlet_mesh_manager.vertex_uvs.binding(),1148instance_manager.instance_uniforms.binding().unwrap(),1149)),1150)1151});11521153let remap_1d_to_2d_dispatch = resource_manager1154.remap_1d_to_2d_dispatch_bind_group_layout1155.as_ref()1156.map(|layout| {1157render_device.create_bind_group(1158"meshlet_remap_1d_to_2d_dispatch_bind_group",1159&pipeline_cache.get_bind_group_layout(layout),1160&BindGroupEntries::sequential((1161view_resources1162.visibility_buffer_software_raster_indirect_args1163.as_entire_binding(),1164resource_manager1165.software_raster_cluster_count1166.as_entire_binding(),1167)),1168)1169});11701171let fill_counts = if resource_manager1172.remap_1d_to_2d_dispatch_bind_group_layout1173.is_some()1174{1175render_device.create_bind_group(1176"meshlet_fill_counts_bind_group",1177&pipeline_cache1178.get_bind_group_layout(&resource_manager.fill_counts_bind_group_layout),1179&BindGroupEntries::sequential((1180view_resources1181.visibility_buffer_software_raster_indirect_args1182.as_entire_binding(),1183view_resources1184.visibility_buffer_hardware_raster_indirect_args1185.as_entire_binding(),1186resource_manager1187.visibility_buffer_raster_cluster_prev_counts1188.as_entire_binding(),1189resource_manager1190.software_raster_cluster_count1191.as_entire_binding(),1192)),1193)1194} else {1195render_device.create_bind_group(1196"meshlet_fill_counts_bind_group",1197&pipeline_cache1198.get_bind_group_layout(&resource_manager.fill_counts_bind_group_layout),1199&BindGroupEntries::sequential((1200view_resources1201.visibility_buffer_software_raster_indirect_args1202.as_entire_binding(),1203view_resources1204.visibility_buffer_hardware_raster_indirect_args1205.as_entire_binding(),1206resource_manager1207.visibility_buffer_raster_cluster_prev_counts1208.as_entire_binding(),1209)),1210)1211};12121213commands.entity(view_entity).insert(MeshletViewBindGroups {1214clear_visibility_buffer,1215first_instance_cull,1216second_instance_cull,1217first_bvh_cull_ping,1218first_bvh_cull_pong,1219second_bvh_cull_ping,1220second_bvh_cull_pong,1221first_meshlet_cull,1222second_meshlet_cull,1223downsample_depth,1224visibility_buffer_raster,1225resolve_depth,1226resolve_material_depth,1227material_shade,1228remap_1d_to_2d_dispatch,1229fill_counts,1230});1231}1232}123312341235