Path: blob/main/crates/bevy_pbr/src/meshlet/resource_manager.rs
6600 views
use super::{instance_manager::InstanceManager, meshlet_mesh_manager::MeshletMeshManager};1use crate::ShadowView;2use bevy_camera::{visibility::RenderLayers, Camera3d};3use bevy_core_pipeline::{4experimental::mip_generation::{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 [`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: BindGroupLayout,53pub clear_visibility_buffer_shadow_view_bind_group_layout: BindGroupLayout,54pub first_instance_cull_bind_group_layout: BindGroupLayout,55pub second_instance_cull_bind_group_layout: BindGroupLayout,56pub first_bvh_cull_bind_group_layout: BindGroupLayout,57pub second_bvh_cull_bind_group_layout: BindGroupLayout,58pub first_meshlet_cull_bind_group_layout: BindGroupLayout,59pub second_meshlet_cull_bind_group_layout: BindGroupLayout,60pub visibility_buffer_raster_bind_group_layout: BindGroupLayout,61pub visibility_buffer_raster_shadow_view_bind_group_layout: BindGroupLayout,62pub downsample_depth_bind_group_layout: BindGroupLayout,63pub downsample_depth_shadow_view_bind_group_layout: BindGroupLayout,64pub resolve_depth_bind_group_layout: BindGroupLayout,65pub resolve_depth_shadow_view_bind_group_layout: BindGroupLayout,66pub resolve_material_depth_bind_group_layout: BindGroupLayout,67pub material_shade_bind_group_layout: BindGroupLayout,68pub fill_counts_bind_group_layout: BindGroupLayout,69pub remap_1d_to_2d_dispatch_bind_group_layout: Option<BindGroupLayout>,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: mip_generation::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: render_device.create_bind_group_layout(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: render_device144.create_bind_group_layout(145"meshlet_clear_visibility_buffer_shadow_view_bind_group_layout",146&BindGroupLayoutEntries::single(147ShaderStages::COMPUTE,148texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::WriteOnly),149),150),151first_instance_cull_bind_group_layout: render_device.create_bind_group_layout(152"meshlet_first_instance_culling_bind_group_layout",153&BindGroupLayoutEntries::sequential(154ShaderStages::COMPUTE,155(156texture_2d(TextureSampleType::Float { filterable: false }),157uniform_buffer::<ViewUniform>(true),158uniform_buffer::<PreviousViewData>(true),159storage_buffer_read_only_sized(false, None),160storage_buffer_read_only_sized(false, None),161storage_buffer_read_only_sized(false, None),162storage_buffer_read_only_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),168storage_buffer_sized(false, None),169),170),171),172second_instance_cull_bind_group_layout: render_device.create_bind_group_layout(173"meshlet_second_instance_culling_bind_group_layout",174&BindGroupLayoutEntries::sequential(175ShaderStages::COMPUTE,176(177texture_2d(TextureSampleType::Float { filterable: false }),178uniform_buffer::<ViewUniform>(true),179uniform_buffer::<PreviousViewData>(true),180storage_buffer_read_only_sized(false, None),181storage_buffer_read_only_sized(false, None),182storage_buffer_read_only_sized(false, None),183storage_buffer_read_only_sized(false, None),184storage_buffer_sized(false, None),185storage_buffer_sized(false, None),186storage_buffer_sized(false, None),187storage_buffer_read_only_sized(false, None),188storage_buffer_read_only_sized(false, None),189),190),191),192first_bvh_cull_bind_group_layout: render_device.create_bind_group_layout(193"meshlet_first_bvh_culling_bind_group_layout",194&BindGroupLayoutEntries::sequential(195ShaderStages::COMPUTE,196(197texture_2d(TextureSampleType::Float { filterable: false }),198uniform_buffer::<ViewUniform>(true),199uniform_buffer::<PreviousViewData>(true),200storage_buffer_read_only_sized(false, None),201storage_buffer_read_only_sized(false, None),202storage_buffer_read_only_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),213storage_buffer_sized(false, None),214),215),216),217second_bvh_cull_bind_group_layout: render_device.create_bind_group_layout(218"meshlet_second_bvh_culling_bind_group_layout",219&BindGroupLayoutEntries::sequential(220ShaderStages::COMPUTE,221(222texture_2d(TextureSampleType::Float { filterable: false }),223uniform_buffer::<ViewUniform>(true),224uniform_buffer::<PreviousViewData>(true),225storage_buffer_read_only_sized(false, None),226storage_buffer_read_only_sized(false, None),227storage_buffer_read_only_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),235storage_buffer_sized(false, None),236),237),238),239first_meshlet_cull_bind_group_layout: render_device.create_bind_group_layout(240"meshlet_first_meshlet_culling_bind_group_layout",241&BindGroupLayoutEntries::sequential(242ShaderStages::COMPUTE,243(244texture_2d(TextureSampleType::Float { filterable: false }),245uniform_buffer::<ViewUniform>(true),246uniform_buffer::<PreviousViewData>(true),247storage_buffer_read_only_sized(false, None),248storage_buffer_read_only_sized(false, None),249storage_buffer_sized(false, None),250storage_buffer_sized(false, None),251storage_buffer_read_only_sized(false, None),252storage_buffer_sized(false, None),253storage_buffer_read_only_sized(false, None),254storage_buffer_sized(false, None),255storage_buffer_sized(false, None),256storage_buffer_sized(false, None),257),258),259),260second_meshlet_cull_bind_group_layout: render_device.create_bind_group_layout(261"meshlet_second_meshlet_culling_bind_group_layout",262&BindGroupLayoutEntries::sequential(263ShaderStages::COMPUTE,264(265texture_2d(TextureSampleType::Float { filterable: false }),266uniform_buffer::<ViewUniform>(true),267uniform_buffer::<PreviousViewData>(true),268storage_buffer_read_only_sized(false, None),269storage_buffer_read_only_sized(false, None),270storage_buffer_sized(false, None),271storage_buffer_sized(false, None),272storage_buffer_read_only_sized(false, None),273storage_buffer_sized(false, None),274storage_buffer_read_only_sized(false, None),275storage_buffer_read_only_sized(false, None),276),277),278),279downsample_depth_bind_group_layout: render_device.create_bind_group_layout(280"meshlet_downsample_depth_bind_group_layout",281&BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {282let write_only_r32float = || {283texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)284};285(286texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),287write_only_r32float(),288write_only_r32float(),289write_only_r32float(),290write_only_r32float(),291write_only_r32float(),292texture_storage_2d(293TextureFormat::R32Float,294StorageTextureAccess::ReadWrite,295),296write_only_r32float(),297write_only_r32float(),298write_only_r32float(),299write_only_r32float(),300write_only_r32float(),301write_only_r32float(),302sampler(SamplerBindingType::NonFiltering),303)304}),305),306downsample_depth_shadow_view_bind_group_layout: render_device.create_bind_group_layout(307"meshlet_downsample_depth_shadow_view_bind_group_layout",308&BindGroupLayoutEntries::sequential(ShaderStages::COMPUTE, {309let write_only_r32float = || {310texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly)311};312(313texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),314write_only_r32float(),315write_only_r32float(),316write_only_r32float(),317write_only_r32float(),318write_only_r32float(),319texture_storage_2d(320TextureFormat::R32Float,321StorageTextureAccess::ReadWrite,322),323write_only_r32float(),324write_only_r32float(),325write_only_r32float(),326write_only_r32float(),327write_only_r32float(),328write_only_r32float(),329sampler(SamplerBindingType::NonFiltering),330)331}),332),333visibility_buffer_raster_bind_group_layout: render_device.create_bind_group_layout(334"meshlet_visibility_buffer_raster_bind_group_layout",335&BindGroupLayoutEntries::sequential(336ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,337(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),344storage_buffer_read_only_sized(false, None),345texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::Atomic),346uniform_buffer::<ViewUniform>(true),347),348),349),350visibility_buffer_raster_shadow_view_bind_group_layout: render_device351.create_bind_group_layout(352"meshlet_visibility_buffer_raster_shadow_view_bind_group_layout",353&BindGroupLayoutEntries::sequential(354ShaderStages::FRAGMENT | ShaderStages::VERTEX | ShaderStages::COMPUTE,355(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),361storage_buffer_read_only_sized(false, None),362storage_buffer_read_only_sized(false, None),363texture_storage_2d(364TextureFormat::R32Uint,365StorageTextureAccess::Atomic,366),367uniform_buffer::<ViewUniform>(true),368),369),370),371resolve_depth_bind_group_layout: render_device.create_bind_group_layout(372"meshlet_resolve_depth_bind_group_layout",373&BindGroupLayoutEntries::single(374ShaderStages::FRAGMENT,375texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),376),377),378resolve_depth_shadow_view_bind_group_layout: render_device.create_bind_group_layout(379"meshlet_resolve_depth_shadow_view_bind_group_layout",380&BindGroupLayoutEntries::single(381ShaderStages::FRAGMENT,382texture_storage_2d(TextureFormat::R32Uint, StorageTextureAccess::ReadOnly),383),384),385resolve_material_depth_bind_group_layout: render_device.create_bind_group_layout(386"meshlet_resolve_material_depth_bind_group_layout",387&BindGroupLayoutEntries::sequential(388ShaderStages::FRAGMENT,389(390texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),391storage_buffer_read_only_sized(false, None),392storage_buffer_read_only_sized(false, None),393),394),395),396material_shade_bind_group_layout: render_device.create_bind_group_layout(397"meshlet_mesh_material_shade_bind_group_layout",398&BindGroupLayoutEntries::sequential(399ShaderStages::FRAGMENT,400(401texture_storage_2d(TextureFormat::R64Uint, StorageTextureAccess::ReadOnly),402storage_buffer_read_only_sized(false, None),403storage_buffer_read_only_sized(false, None),404storage_buffer_read_only_sized(false, None),405storage_buffer_read_only_sized(false, None),406storage_buffer_read_only_sized(false, None),407storage_buffer_read_only_sized(false, None),408storage_buffer_read_only_sized(false, None),409),410),411),412fill_counts_bind_group_layout: if needs_dispatch_remap {413render_device.create_bind_group_layout(414"meshlet_fill_counts_bind_group_layout",415&BindGroupLayoutEntries::sequential(416ShaderStages::COMPUTE,417(418storage_buffer_sized(false, None),419storage_buffer_sized(false, None),420storage_buffer_sized(false, None),421storage_buffer_sized(false, None),422),423),424)425} else {426render_device.create_bind_group_layout(427"meshlet_fill_counts_bind_group_layout",428&BindGroupLayoutEntries::sequential(429ShaderStages::COMPUTE,430(431storage_buffer_sized(false, None),432storage_buffer_sized(false, None),433storage_buffer_sized(false, None),434),435),436)437},438remap_1d_to_2d_dispatch_bind_group_layout: needs_dispatch_remap.then(|| {439render_device.create_bind_group_layout(440"meshlet_remap_1d_to_2d_dispatch_bind_group_layout",441&BindGroupLayoutEntries::sequential(442ShaderStages::COMPUTE,443(444storage_buffer_sized(false, None),445storage_buffer_sized(false, None),446),447),448)449}),450}451}452}453454// ------------ TODO: Everything under here needs to be rewritten and cached ------------455456#[derive(Component)]457pub struct MeshletViewResources {458pub scene_instance_count: u32,459pub rightmost_slot: u32,460pub max_bvh_depth: u32,461instance_visibility: Buffer,462pub dummy_render_target: CachedTexture,463pub visibility_buffer: CachedTexture,464pub second_pass_count: Buffer,465pub second_pass_dispatch: Buffer,466pub second_pass_candidates: Buffer,467pub first_bvh_cull_count_front: Buffer,468pub first_bvh_cull_dispatch_front: Buffer,469pub first_bvh_cull_count_back: Buffer,470pub first_bvh_cull_dispatch_back: Buffer,471pub first_bvh_cull_queue: Buffer,472pub second_bvh_cull_count_front: Buffer,473pub second_bvh_cull_dispatch_front: Buffer,474pub second_bvh_cull_count_back: Buffer,475pub second_bvh_cull_dispatch_back: Buffer,476pub second_bvh_cull_queue: Buffer,477pub front_meshlet_cull_count: Buffer,478pub front_meshlet_cull_dispatch: Buffer,479pub back_meshlet_cull_count: Buffer,480pub back_meshlet_cull_dispatch: Buffer,481pub meshlet_cull_queue: Buffer,482pub visibility_buffer_software_raster_indirect_args: Buffer,483pub visibility_buffer_hardware_raster_indirect_args: Buffer,484pub depth_pyramid: ViewDepthPyramid,485previous_depth_pyramid: TextureView,486pub material_depth: Option<CachedTexture>,487pub view_size: UVec2,488not_shadow_view: bool,489}490491#[derive(Component)]492pub struct MeshletViewBindGroups {493pub clear_visibility_buffer: BindGroup,494pub first_instance_cull: BindGroup,495pub second_instance_cull: BindGroup,496pub first_bvh_cull_ping: BindGroup,497pub first_bvh_cull_pong: BindGroup,498pub second_bvh_cull_ping: BindGroup,499pub second_bvh_cull_pong: BindGroup,500pub first_meshlet_cull: BindGroup,501pub second_meshlet_cull: BindGroup,502pub downsample_depth: BindGroup,503pub visibility_buffer_raster: BindGroup,504pub resolve_depth: BindGroup,505pub resolve_material_depth: Option<BindGroup>,506pub material_shade: Option<BindGroup>,507pub remap_1d_to_2d_dispatch: Option<BindGroup>,508pub fill_counts: BindGroup,509}510511// TODO: Cache things per-view and skip running this system / optimize this system512pub fn prepare_meshlet_per_frame_resources(513mut resource_manager: ResMut<ResourceManager>,514mut instance_manager: ResMut<InstanceManager>,515views: Query<(516Entity,517&ExtractedView,518Option<&RenderLayers>,519AnyOf<(&Camera3d, &ShadowView)>,520)>,521mut texture_cache: ResMut<TextureCache>,522render_queue: Res<RenderQueue>,523render_device: Res<RenderDevice>,524mut commands: Commands,525) {526if instance_manager.scene_instance_count == 0 {527return;528}529530let instance_manager = instance_manager.as_mut();531532// TODO: Move this and the submit to a separate system and remove pub from the fields533instance_manager534.instance_uniforms535.write_buffer(&render_device, &render_queue);536instance_manager537.instance_aabbs538.write_buffer(&render_device, &render_queue);539instance_manager540.instance_material_ids541.write_buffer(&render_device, &render_queue);542instance_manager543.instance_bvh_root_nodes544.write_buffer(&render_device, &render_queue);545546let needed_buffer_size = 4 * instance_manager.scene_instance_count as u64;547let second_pass_candidates = match &mut resource_manager.second_pass_candidates {548Some(buffer) if buffer.size() >= needed_buffer_size => buffer.clone(),549slot => {550let buffer = render_device.create_buffer(&BufferDescriptor {551label: Some("meshlet_second_pass_candidates"),552size: needed_buffer_size,553usage: BufferUsages::STORAGE,554mapped_at_creation: false,555});556*slot = Some(buffer.clone());557buffer558}559};560561for (view_entity, view, render_layers, (_, shadow_view)) in &views {562let not_shadow_view = shadow_view.is_none();563564let instance_visibility = instance_manager565.view_instance_visibility566.entry(view_entity)567.or_insert_with(|| {568let mut buffer = StorageBuffer::default();569buffer.set_label(Some("meshlet_view_instance_visibility"));570buffer571});572for (instance_index, (_, layers, not_shadow_caster)) in573instance_manager.instances.iter().enumerate()574{575// If either the layers don't match the view's layers or this is a shadow view576// and the instance is not a shadow caster, hide the instance for this view577if !render_layers578.unwrap_or(&RenderLayers::default())579.intersects(layers)580|| (shadow_view.is_some() && *not_shadow_caster)581{582let vec = instance_visibility.get_mut();583let index = instance_index / 32;584let bit = instance_index - index * 32;585if vec.len() <= index {586vec.extend(iter::repeat_n(0, index - vec.len() + 1));587}588vec[index] |= 1 << bit;589}590}591instance_visibility.write_buffer(&render_device, &render_queue);592let instance_visibility = instance_visibility.buffer().unwrap().clone();593594// TODO: Remove this once wgpu allows render passes with no attachments595let dummy_render_target = texture_cache.get(596&render_device,597TextureDescriptor {598label: Some("meshlet_dummy_render_target"),599size: view.viewport.zw().to_extents(),600mip_level_count: 1,601sample_count: 1,602dimension: TextureDimension::D2,603format: TextureFormat::R8Uint,604usage: TextureUsages::RENDER_ATTACHMENT,605view_formats: &[],606},607);608609let visibility_buffer = texture_cache.get(610&render_device,611TextureDescriptor {612label: Some("meshlet_visibility_buffer"),613size: view.viewport.zw().to_extents(),614mip_level_count: 1,615sample_count: 1,616dimension: TextureDimension::D2,617format: if not_shadow_view {618TextureFormat::R64Uint619} else {620TextureFormat::R32Uint621},622usage: TextureUsages::STORAGE_ATOMIC | TextureUsages::STORAGE_BINDING,623view_formats: &[],624},625);626627let second_pass_count = render_device.create_buffer_with_data(&BufferInitDescriptor {628label: Some("meshlet_second_pass_count"),629contents: bytemuck::bytes_of(&0u32),630usage: BufferUsages::STORAGE,631});632let second_pass_dispatch = render_device.create_buffer_with_data(&BufferInitDescriptor {633label: Some("meshlet_second_pass_dispatch"),634contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),635usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,636});637638let first_bvh_cull_count_front =639render_device.create_buffer_with_data(&BufferInitDescriptor {640label: Some("meshlet_first_bvh_cull_count_front"),641contents: bytemuck::bytes_of(&0u32),642usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,643});644let first_bvh_cull_dispatch_front =645render_device.create_buffer_with_data(&BufferInitDescriptor {646label: Some("meshlet_first_bvh_cull_dispatch_front"),647contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),648usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,649});650let first_bvh_cull_count_back =651render_device.create_buffer_with_data(&BufferInitDescriptor {652label: Some("meshlet_first_bvh_cull_count_back"),653contents: bytemuck::bytes_of(&0u32),654usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,655});656let first_bvh_cull_dispatch_back =657render_device.create_buffer_with_data(&BufferInitDescriptor {658label: Some("meshlet_first_bvh_cull_dispatch_back"),659contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),660usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,661});662663let second_bvh_cull_count_front =664render_device.create_buffer_with_data(&BufferInitDescriptor {665label: Some("meshlet_second_bvh_cull_count_front"),666contents: bytemuck::bytes_of(&0u32),667usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,668});669let second_bvh_cull_dispatch_front =670render_device.create_buffer_with_data(&BufferInitDescriptor {671label: Some("meshlet_second_bvh_cull_dispatch_front"),672contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),673usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,674});675let second_bvh_cull_count_back =676render_device.create_buffer_with_data(&BufferInitDescriptor {677label: Some("meshlet_second_bvh_cull_count_back"),678contents: bytemuck::bytes_of(&0u32),679usage: BufferUsages::STORAGE | BufferUsages::COPY_DST,680});681let second_bvh_cull_dispatch_back =682render_device.create_buffer_with_data(&BufferInitDescriptor {683label: Some("meshlet_second_bvh_cull_dispatch_back"),684contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),685usage: BufferUsages::STORAGE | BufferUsages::INDIRECT | BufferUsages::COPY_DST,686});687688let front_meshlet_cull_count =689render_device.create_buffer_with_data(&BufferInitDescriptor {690label: Some("meshlet_front_meshlet_cull_count"),691contents: bytemuck::bytes_of(&0u32),692usage: BufferUsages::STORAGE,693});694let front_meshlet_cull_dispatch =695render_device.create_buffer_with_data(&BufferInitDescriptor {696label: Some("meshlet_front_meshlet_cull_dispatch"),697contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),698usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,699});700let back_meshlet_cull_count =701render_device.create_buffer_with_data(&BufferInitDescriptor {702label: Some("meshlet_back_meshlet_cull_count"),703contents: bytemuck::bytes_of(&0u32),704usage: BufferUsages::STORAGE,705});706let back_meshlet_cull_dispatch =707render_device.create_buffer_with_data(&BufferInitDescriptor {708label: Some("meshlet_back_meshlet_cull_dispatch"),709contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),710usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,711});712713let visibility_buffer_software_raster_indirect_args = render_device714.create_buffer_with_data(&BufferInitDescriptor {715label: Some("meshlet_visibility_buffer_software_raster_indirect_args"),716contents: DispatchIndirectArgs { x: 0, y: 1, z: 1 }.as_bytes(),717usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,718});719720let visibility_buffer_hardware_raster_indirect_args = render_device721.create_buffer_with_data(&BufferInitDescriptor {722label: Some("meshlet_visibility_buffer_hardware_raster_indirect_args"),723contents: DrawIndirectArgs {724vertex_count: 128 * 3,725instance_count: 0,726first_vertex: 0,727first_instance: 0,728}729.as_bytes(),730usage: BufferUsages::STORAGE | BufferUsages::INDIRECT,731});732733let depth_pyramid = ViewDepthPyramid::new(734&render_device,735&mut texture_cache,736&resource_manager.depth_pyramid_dummy_texture,737view.viewport.zw(),738"meshlet_depth_pyramid",739"meshlet_depth_pyramid_texture_view",740);741742let previous_depth_pyramid =743match resource_manager.previous_depth_pyramids.get(&view_entity) {744Some(texture_view) => texture_view.clone(),745None => depth_pyramid.all_mips.clone(),746};747resource_manager748.previous_depth_pyramids749.insert(view_entity, depth_pyramid.all_mips.clone());750751let material_depth = TextureDescriptor {752label: Some("meshlet_material_depth"),753size: view.viewport.zw().to_extents(),754mip_level_count: 1,755sample_count: 1,756dimension: TextureDimension::D2,757format: TextureFormat::Depth16Unorm,758usage: TextureUsages::RENDER_ATTACHMENT,759view_formats: &[],760};761762commands.entity(view_entity).insert(MeshletViewResources {763scene_instance_count: instance_manager.scene_instance_count,764rightmost_slot: resource_manager.cull_queue_rightmost_slot,765max_bvh_depth: instance_manager.max_bvh_depth,766instance_visibility,767dummy_render_target,768visibility_buffer,769second_pass_count,770second_pass_dispatch,771second_pass_candidates: second_pass_candidates.clone(),772first_bvh_cull_count_front,773first_bvh_cull_dispatch_front,774first_bvh_cull_count_back,775first_bvh_cull_dispatch_back,776first_bvh_cull_queue: resource_manager.bvh_traversal_queues[0].clone(),777second_bvh_cull_count_front,778second_bvh_cull_dispatch_front,779second_bvh_cull_count_back,780second_bvh_cull_dispatch_back,781second_bvh_cull_queue: resource_manager.bvh_traversal_queues[1].clone(),782front_meshlet_cull_count,783front_meshlet_cull_dispatch,784back_meshlet_cull_count,785back_meshlet_cull_dispatch,786meshlet_cull_queue: resource_manager.cluster_cull_candidate_queue.clone(),787visibility_buffer_software_raster_indirect_args,788visibility_buffer_hardware_raster_indirect_args,789depth_pyramid,790previous_depth_pyramid,791material_depth: not_shadow_view792.then(|| texture_cache.get(&render_device, material_depth)),793view_size: view.viewport.zw(),794not_shadow_view,795});796}797}798799pub fn prepare_meshlet_view_bind_groups(800meshlet_mesh_manager: Res<MeshletMeshManager>,801resource_manager: Res<ResourceManager>,802instance_manager: Res<InstanceManager>,803views: Query<(Entity, &MeshletViewResources)>,804view_uniforms: Res<ViewUniforms>,805previous_view_uniforms: Res<PreviousViewUniforms>,806render_device: Res<RenderDevice>,807mut commands: Commands,808) {809let (Some(view_uniforms), Some(previous_view_uniforms)) = (810view_uniforms.uniforms.binding(),811previous_view_uniforms.uniforms.binding(),812) else {813return;814};815816// TODO: Some of these bind groups can be reused across multiple views817for (view_entity, view_resources) in &views {818let clear_visibility_buffer = render_device.create_bind_group(819"meshlet_clear_visibility_buffer_bind_group",820if view_resources.not_shadow_view {821&resource_manager.clear_visibility_buffer_bind_group_layout822} else {823&resource_manager.clear_visibility_buffer_shadow_view_bind_group_layout824},825&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),826);827828let first_instance_cull = render_device.create_bind_group(829"meshlet_first_instance_cull_bind_group",830&resource_manager.first_instance_cull_bind_group_layout,831&BindGroupEntries::sequential((832&view_resources.previous_depth_pyramid,833view_uniforms.clone(),834previous_view_uniforms.clone(),835instance_manager.instance_uniforms.binding().unwrap(),836view_resources.instance_visibility.as_entire_binding(),837instance_manager.instance_aabbs.binding().unwrap(),838instance_manager.instance_bvh_root_nodes.binding().unwrap(),839view_resources840.first_bvh_cull_count_front841.as_entire_binding(),842view_resources843.first_bvh_cull_dispatch_front844.as_entire_binding(),845view_resources.first_bvh_cull_queue.as_entire_binding(),846view_resources.second_pass_count.as_entire_binding(),847view_resources.second_pass_dispatch.as_entire_binding(),848view_resources.second_pass_candidates.as_entire_binding(),849)),850);851852let second_instance_cull = render_device.create_bind_group(853"meshlet_second_instance_cull_bind_group",854&resource_manager.second_instance_cull_bind_group_layout,855&BindGroupEntries::sequential((856&view_resources.previous_depth_pyramid,857view_uniforms.clone(),858previous_view_uniforms.clone(),859instance_manager.instance_uniforms.binding().unwrap(),860view_resources.instance_visibility.as_entire_binding(),861instance_manager.instance_aabbs.binding().unwrap(),862instance_manager.instance_bvh_root_nodes.binding().unwrap(),863view_resources864.second_bvh_cull_count_front865.as_entire_binding(),866view_resources867.second_bvh_cull_dispatch_front868.as_entire_binding(),869view_resources.second_bvh_cull_queue.as_entire_binding(),870view_resources.second_pass_count.as_entire_binding(),871view_resources.second_pass_candidates.as_entire_binding(),872)),873);874875let first_bvh_cull_ping = render_device.create_bind_group(876"meshlet_first_bvh_cull_ping_bind_group",877&resource_manager.first_bvh_cull_bind_group_layout,878&BindGroupEntries::sequential((879&view_resources.previous_depth_pyramid,880view_uniforms.clone(),881previous_view_uniforms.clone(),882meshlet_mesh_manager.bvh_nodes.binding(),883instance_manager.instance_uniforms.binding().unwrap(),884view_resources885.first_bvh_cull_count_front886.as_entire_binding(),887view_resources.first_bvh_cull_count_back.as_entire_binding(),888view_resources889.first_bvh_cull_dispatch_back890.as_entire_binding(),891view_resources.first_bvh_cull_queue.as_entire_binding(),892view_resources.front_meshlet_cull_count.as_entire_binding(),893view_resources.back_meshlet_cull_count.as_entire_binding(),894view_resources895.front_meshlet_cull_dispatch896.as_entire_binding(),897view_resources898.back_meshlet_cull_dispatch899.as_entire_binding(),900view_resources.meshlet_cull_queue.as_entire_binding(),901view_resources902.second_bvh_cull_count_front903.as_entire_binding(),904view_resources905.second_bvh_cull_dispatch_front906.as_entire_binding(),907view_resources.second_bvh_cull_queue.as_entire_binding(),908)),909);910911let first_bvh_cull_pong = render_device.create_bind_group(912"meshlet_first_bvh_cull_pong_bind_group",913&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&resource_manager.second_bvh_cull_bind_group_layout,950&BindGroupEntries::sequential((951&view_resources.previous_depth_pyramid,952view_uniforms.clone(),953previous_view_uniforms.clone(),954meshlet_mesh_manager.bvh_nodes.binding(),955instance_manager.instance_uniforms.binding().unwrap(),956view_resources957.second_bvh_cull_count_front958.as_entire_binding(),959view_resources960.second_bvh_cull_count_back961.as_entire_binding(),962view_resources963.second_bvh_cull_dispatch_back964.as_entire_binding(),965view_resources.second_bvh_cull_queue.as_entire_binding(),966view_resources.front_meshlet_cull_count.as_entire_binding(),967view_resources.back_meshlet_cull_count.as_entire_binding(),968view_resources969.front_meshlet_cull_dispatch970.as_entire_binding(),971view_resources972.back_meshlet_cull_dispatch973.as_entire_binding(),974view_resources.meshlet_cull_queue.as_entire_binding(),975)),976);977978let second_bvh_cull_pong = render_device.create_bind_group(979"meshlet_second_bvh_cull_pong_bind_group",980&resource_manager.second_bvh_cull_bind_group_layout,981&BindGroupEntries::sequential((982&view_resources.previous_depth_pyramid,983view_uniforms.clone(),984previous_view_uniforms.clone(),985meshlet_mesh_manager.bvh_nodes.binding(),986instance_manager.instance_uniforms.binding().unwrap(),987view_resources988.second_bvh_cull_count_back989.as_entire_binding(),990view_resources991.second_bvh_cull_count_front992.as_entire_binding(),993view_resources994.second_bvh_cull_dispatch_front995.as_entire_binding(),996view_resources.second_bvh_cull_queue.as_entire_binding(),997view_resources.front_meshlet_cull_count.as_entire_binding(),998view_resources.back_meshlet_cull_count.as_entire_binding(),999view_resources1000.front_meshlet_cull_dispatch1001.as_entire_binding(),1002view_resources1003.back_meshlet_cull_dispatch1004.as_entire_binding(),1005view_resources.meshlet_cull_queue.as_entire_binding(),1006)),1007);10081009let first_meshlet_cull = render_device.create_bind_group(1010"meshlet_first_meshlet_cull_bind_group",1011&resource_manager.first_meshlet_cull_bind_group_layout,1012&BindGroupEntries::sequential((1013&view_resources.previous_depth_pyramid,1014view_uniforms.clone(),1015previous_view_uniforms.clone(),1016meshlet_mesh_manager.meshlet_cull_data.binding(),1017instance_manager.instance_uniforms.binding().unwrap(),1018view_resources1019.visibility_buffer_software_raster_indirect_args1020.as_entire_binding(),1021view_resources1022.visibility_buffer_hardware_raster_indirect_args1023.as_entire_binding(),1024resource_manager1025.visibility_buffer_raster_cluster_prev_counts1026.as_entire_binding(),1027resource_manager1028.visibility_buffer_raster_clusters1029.as_entire_binding(),1030view_resources.front_meshlet_cull_count.as_entire_binding(),1031view_resources.back_meshlet_cull_count.as_entire_binding(),1032view_resources1033.back_meshlet_cull_dispatch1034.as_entire_binding(),1035view_resources.meshlet_cull_queue.as_entire_binding(),1036)),1037);10381039let second_meshlet_cull = render_device.create_bind_group(1040"meshlet_second_meshlet_cull_bind_group",1041&resource_manager.second_meshlet_cull_bind_group_layout,1042&BindGroupEntries::sequential((1043&view_resources.previous_depth_pyramid,1044view_uniforms.clone(),1045previous_view_uniforms.clone(),1046meshlet_mesh_manager.meshlet_cull_data.binding(),1047instance_manager.instance_uniforms.binding().unwrap(),1048view_resources1049.visibility_buffer_software_raster_indirect_args1050.as_entire_binding(),1051view_resources1052.visibility_buffer_hardware_raster_indirect_args1053.as_entire_binding(),1054resource_manager1055.visibility_buffer_raster_cluster_prev_counts1056.as_entire_binding(),1057resource_manager1058.visibility_buffer_raster_clusters1059.as_entire_binding(),1060view_resources.back_meshlet_cull_count.as_entire_binding(),1061view_resources.meshlet_cull_queue.as_entire_binding(),1062)),1063);10641065let downsample_depth = view_resources.depth_pyramid.create_bind_group(1066&render_device,1067"meshlet_downsample_depth_bind_group",1068if view_resources.not_shadow_view {1069&resource_manager.downsample_depth_bind_group_layout1070} else {1071&resource_manager.downsample_depth_shadow_view_bind_group_layout1072},1073&view_resources.visibility_buffer.default_view,1074&resource_manager.depth_pyramid_sampler,1075);10761077let visibility_buffer_raster = render_device.create_bind_group(1078"meshlet_visibility_raster_buffer_bind_group",1079if view_resources.not_shadow_view {1080&resource_manager.visibility_buffer_raster_bind_group_layout1081} else {1082&resource_manager.visibility_buffer_raster_shadow_view_bind_group_layout1083},1084&BindGroupEntries::sequential((1085resource_manager1086.visibility_buffer_raster_clusters1087.as_entire_binding(),1088meshlet_mesh_manager.meshlets.binding(),1089meshlet_mesh_manager.indices.binding(),1090meshlet_mesh_manager.vertex_positions.binding(),1091instance_manager.instance_uniforms.binding().unwrap(),1092resource_manager1093.visibility_buffer_raster_cluster_prev_counts1094.as_entire_binding(),1095resource_manager1096.software_raster_cluster_count1097.as_entire_binding(),1098&view_resources.visibility_buffer.default_view,1099view_uniforms.clone(),1100)),1101);11021103let resolve_depth = render_device.create_bind_group(1104"meshlet_resolve_depth_bind_group",1105if view_resources.not_shadow_view {1106&resource_manager.resolve_depth_bind_group_layout1107} else {1108&resource_manager.resolve_depth_shadow_view_bind_group_layout1109},1110&BindGroupEntries::single(&view_resources.visibility_buffer.default_view),1111);11121113let resolve_material_depth = view_resources.material_depth.as_ref().map(|_| {1114render_device.create_bind_group(1115"meshlet_resolve_material_depth_bind_group",1116&resource_manager.resolve_material_depth_bind_group_layout,1117&BindGroupEntries::sequential((1118&view_resources.visibility_buffer.default_view,1119resource_manager1120.visibility_buffer_raster_clusters1121.as_entire_binding(),1122instance_manager.instance_material_ids.binding().unwrap(),1123)),1124)1125});11261127let material_shade = view_resources.material_depth.as_ref().map(|_| {1128render_device.create_bind_group(1129"meshlet_mesh_material_shade_bind_group",1130&resource_manager.material_shade_bind_group_layout,1131&BindGroupEntries::sequential((1132&view_resources.visibility_buffer.default_view,1133resource_manager1134.visibility_buffer_raster_clusters1135.as_entire_binding(),1136meshlet_mesh_manager.meshlets.binding(),1137meshlet_mesh_manager.indices.binding(),1138meshlet_mesh_manager.vertex_positions.binding(),1139meshlet_mesh_manager.vertex_normals.binding(),1140meshlet_mesh_manager.vertex_uvs.binding(),1141instance_manager.instance_uniforms.binding().unwrap(),1142)),1143)1144});11451146let remap_1d_to_2d_dispatch = resource_manager1147.remap_1d_to_2d_dispatch_bind_group_layout1148.as_ref()1149.map(|layout| {1150render_device.create_bind_group(1151"meshlet_remap_1d_to_2d_dispatch_bind_group",1152layout,1153&BindGroupEntries::sequential((1154view_resources1155.visibility_buffer_software_raster_indirect_args1156.as_entire_binding(),1157resource_manager1158.software_raster_cluster_count1159.as_entire_binding(),1160)),1161)1162});11631164let fill_counts = if resource_manager1165.remap_1d_to_2d_dispatch_bind_group_layout1166.is_some()1167{1168render_device.create_bind_group(1169"meshlet_fill_counts_bind_group",1170&resource_manager.fill_counts_bind_group_layout,1171&BindGroupEntries::sequential((1172view_resources1173.visibility_buffer_software_raster_indirect_args1174.as_entire_binding(),1175view_resources1176.visibility_buffer_hardware_raster_indirect_args1177.as_entire_binding(),1178resource_manager1179.visibility_buffer_raster_cluster_prev_counts1180.as_entire_binding(),1181resource_manager1182.software_raster_cluster_count1183.as_entire_binding(),1184)),1185)1186} else {1187render_device.create_bind_group(1188"meshlet_fill_counts_bind_group",1189&resource_manager.fill_counts_bind_group_layout,1190&BindGroupEntries::sequential((1191view_resources1192.visibility_buffer_software_raster_indirect_args1193.as_entire_binding(),1194view_resources1195.visibility_buffer_hardware_raster_indirect_args1196.as_entire_binding(),1197resource_manager1198.visibility_buffer_raster_cluster_prev_counts1199.as_entire_binding(),1200)),1201)1202};12031204commands.entity(view_entity).insert(MeshletViewBindGroups {1205clear_visibility_buffer,1206first_instance_cull,1207second_instance_cull,1208first_bvh_cull_ping,1209first_bvh_cull_pong,1210second_bvh_cull_ping,1211second_bvh_cull_pong,1212first_meshlet_cull,1213second_meshlet_cull,1214downsample_depth,1215visibility_buffer_raster,1216resolve_depth,1217resolve_material_depth,1218material_shade,1219remap_1d_to_2d_dispatch,1220fill_counts,1221});1222}1223}122412251226