Path: blob/main/crates/bevy_pbr/src/meshlet/visibility_buffer_raster_node.rs
9374 views
use super::{1pipelines::MeshletPipelines,2resource_manager::{MeshletViewBindGroups, MeshletViewResources, ResourceManager},3};4use crate::{LightEntity, ShadowView, ViewLightEntities};5use bevy_color::LinearRgba;6use bevy_core_pipeline::prepass::PreviousViewUniformOffset;7use bevy_ecs::prelude::*;8use bevy_math::UVec2;9use bevy_render::{10camera::ExtractedCamera,11diagnostic::RecordDiagnostics,12render_resource::*,13renderer::{RenderContext, ViewQuery},14view::{ViewDepthTexture, ViewUniformOffset},15};1617///18/// Rasterize meshlets into a depth buffer, and optional visibility buffer + material depth buffer for shading passes.19// TODO: Reuse compute/render passes between logical passes where possible, as they're expensive20pub fn meshlet_visibility_buffer_raster(21world: &World,22view: ViewQuery<(23&ExtractedCamera,24&ViewDepthTexture,25&ViewUniformOffset,26&PreviousViewUniformOffset,27&MeshletViewBindGroups,28&MeshletViewResources,29&ViewLightEntities,30)>,31view_light_query: Query<(32&ShadowView,33&LightEntity,34&ViewUniformOffset,35&PreviousViewUniformOffset,36&MeshletViewBindGroups,37&MeshletViewResources,38)>,39resource_manager: Res<ResourceManager>,40mut ctx: RenderContext,41) {42let (43camera,44view_depth,45view_offset,46previous_view_offset,47meshlet_view_bind_groups,48meshlet_view_resources,49lights,50) = view.into_inner();5152let Some((53clear_visibility_buffer_pipeline,54clear_visibility_buffer_shadow_view_pipeline,55first_instance_cull_pipeline,56second_instance_cull_pipeline,57first_bvh_cull_pipeline,58second_bvh_cull_pipeline,59first_meshlet_cull_pipeline,60second_meshlet_cull_pipeline,61downsample_depth_first_pipeline,62downsample_depth_second_pipeline,63downsample_depth_first_shadow_view_pipeline,64downsample_depth_second_shadow_view_pipeline,65visibility_buffer_software_raster_pipeline,66visibility_buffer_software_raster_shadow_view_pipeline,67visibility_buffer_hardware_raster_pipeline,68visibility_buffer_hardware_raster_shadow_view_pipeline,69visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline,70resolve_depth_pipeline,71resolve_depth_shadow_view_pipeline,72resolve_material_depth_pipeline,73remap_1d_to_2d_dispatch_pipeline,74fill_counts_pipeline,75)) = MeshletPipelines::get(world)76else {77return;78};7980let diagnostics = ctx.diagnostic_recorder();81let diagnostics = diagnostics.as_deref();8283ctx.command_encoder()84.push_debug_group("meshlet_visibility_buffer_raster");85let time_span =86diagnostics.time_span(ctx.command_encoder(), "meshlet_visibility_buffer_raster");8788ctx.command_encoder().clear_buffer(89&resource_manager.visibility_buffer_raster_cluster_prev_counts,900,91None,92);9394clear_visibility_buffer_pass(95&mut ctx,96&meshlet_view_bind_groups.clear_visibility_buffer,97clear_visibility_buffer_pipeline,98meshlet_view_resources.view_size,99);100101ctx.command_encoder().push_debug_group("meshlet_first_pass");102first_cull(103&mut ctx,104meshlet_view_bind_groups,105meshlet_view_resources,106view_offset,107previous_view_offset,108first_instance_cull_pipeline,109first_bvh_cull_pipeline,110first_meshlet_cull_pipeline,111remap_1d_to_2d_dispatch_pipeline,112);113raster_pass(114true,115&mut ctx,116&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,117&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,118&meshlet_view_resources.dummy_render_target.default_view,119meshlet_view_bind_groups,120view_offset,121visibility_buffer_software_raster_pipeline,122visibility_buffer_hardware_raster_pipeline,123fill_counts_pipeline,124Some(camera),125meshlet_view_resources.rightmost_slot,126);127ctx.command_encoder().pop_debug_group();128129meshlet_view_resources130.depth_pyramid131.downsample_depth_with_ctx(132"downsample_depth",133&mut ctx,134meshlet_view_resources.view_size,135&meshlet_view_bind_groups.downsample_depth,136downsample_depth_first_pipeline,137downsample_depth_second_pipeline,138);139140ctx.command_encoder()141.push_debug_group("meshlet_second_pass");142second_cull(143&mut ctx,144meshlet_view_bind_groups,145meshlet_view_resources,146view_offset,147previous_view_offset,148second_instance_cull_pipeline,149second_bvh_cull_pipeline,150second_meshlet_cull_pipeline,151remap_1d_to_2d_dispatch_pipeline,152);153raster_pass(154false,155&mut ctx,156&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,157&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,158&meshlet_view_resources.dummy_render_target.default_view,159meshlet_view_bind_groups,160view_offset,161visibility_buffer_software_raster_pipeline,162visibility_buffer_hardware_raster_pipeline,163fill_counts_pipeline,164Some(camera),165meshlet_view_resources.rightmost_slot,166);167ctx.command_encoder().pop_debug_group();168169resolve_depth(170&mut ctx,171view_depth.get_attachment(StoreOp::Store),172meshlet_view_bind_groups,173resolve_depth_pipeline,174camera,175);176resolve_material_depth(177&mut ctx,178meshlet_view_resources,179meshlet_view_bind_groups,180resolve_material_depth_pipeline,181camera,182);183meshlet_view_resources184.depth_pyramid185.downsample_depth_with_ctx(186"downsample_depth",187&mut ctx,188meshlet_view_resources.view_size,189&meshlet_view_bind_groups.downsample_depth,190downsample_depth_first_pipeline,191downsample_depth_second_pipeline,192);193ctx.command_encoder().pop_debug_group();194time_span.end(ctx.command_encoder());195196for light_entity in &lights.lights {197let Ok((198shadow_view,199light_type,200view_offset,201previous_view_offset,202meshlet_view_bind_groups,203meshlet_view_resources,204)) = view_light_query.get(*light_entity)205else {206continue;207};208209let shadow_visibility_buffer_hardware_raster_pipeline =210if let LightEntity::Directional { .. } = light_type {211visibility_buffer_hardware_raster_shadow_view_unclipped_pipeline212} else {213visibility_buffer_hardware_raster_shadow_view_pipeline214};215216ctx.command_encoder().push_debug_group(&format!(217"meshlet_visibility_buffer_raster: {}",218shadow_view.pass_name219));220let time_span_shadow =221diagnostics.time_span(ctx.command_encoder(), shadow_view.pass_name.clone());222223clear_visibility_buffer_pass(224&mut ctx,225&meshlet_view_bind_groups.clear_visibility_buffer,226clear_visibility_buffer_shadow_view_pipeline,227meshlet_view_resources.view_size,228);229230ctx.command_encoder().push_debug_group("meshlet_first_pass");231first_cull(232&mut ctx,233meshlet_view_bind_groups,234meshlet_view_resources,235view_offset,236previous_view_offset,237first_instance_cull_pipeline,238first_bvh_cull_pipeline,239first_meshlet_cull_pipeline,240remap_1d_to_2d_dispatch_pipeline,241);242raster_pass(243true,244&mut ctx,245&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,246&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,247&meshlet_view_resources.dummy_render_target.default_view,248meshlet_view_bind_groups,249view_offset,250visibility_buffer_software_raster_shadow_view_pipeline,251shadow_visibility_buffer_hardware_raster_pipeline,252fill_counts_pipeline,253None,254meshlet_view_resources.rightmost_slot,255);256ctx.command_encoder().pop_debug_group();257258meshlet_view_resources259.depth_pyramid260.downsample_depth_with_ctx(261"downsample_depth",262&mut ctx,263meshlet_view_resources.view_size,264&meshlet_view_bind_groups.downsample_depth,265downsample_depth_first_shadow_view_pipeline,266downsample_depth_second_shadow_view_pipeline,267);268269ctx.command_encoder()270.push_debug_group("meshlet_second_pass");271second_cull(272&mut ctx,273meshlet_view_bind_groups,274meshlet_view_resources,275view_offset,276previous_view_offset,277second_instance_cull_pipeline,278second_bvh_cull_pipeline,279second_meshlet_cull_pipeline,280remap_1d_to_2d_dispatch_pipeline,281);282raster_pass(283false,284&mut ctx,285&meshlet_view_resources.visibility_buffer_software_raster_indirect_args,286&meshlet_view_resources.visibility_buffer_hardware_raster_indirect_args,287&meshlet_view_resources.dummy_render_target.default_view,288meshlet_view_bind_groups,289view_offset,290visibility_buffer_software_raster_shadow_view_pipeline,291shadow_visibility_buffer_hardware_raster_pipeline,292fill_counts_pipeline,293None,294meshlet_view_resources.rightmost_slot,295);296ctx.command_encoder().pop_debug_group();297298resolve_depth(299&mut ctx,300shadow_view.depth_attachment.get_attachment(StoreOp::Store),301meshlet_view_bind_groups,302resolve_depth_shadow_view_pipeline,303camera,304);305meshlet_view_resources306.depth_pyramid307.downsample_depth_with_ctx(308"downsample_depth",309&mut ctx,310meshlet_view_resources.view_size,311&meshlet_view_bind_groups.downsample_depth,312downsample_depth_first_shadow_view_pipeline,313downsample_depth_second_shadow_view_pipeline,314);315ctx.command_encoder().pop_debug_group();316time_span_shadow.end(ctx.command_encoder());317}318}319320// TODO: Replace this with vkCmdClearColorImage once wgpu supports it321fn clear_visibility_buffer_pass(322ctx: &mut RenderContext,323clear_visibility_buffer_bind_group: &BindGroup,324clear_visibility_buffer_pipeline: &ComputePipeline,325view_size: UVec2,326) {327let command_encoder = ctx.command_encoder();328let mut clear_visibility_buffer_pass =329command_encoder.begin_compute_pass(&ComputePassDescriptor {330label: Some("clear_visibility_buffer"),331timestamp_writes: None,332});333clear_visibility_buffer_pass.set_pipeline(clear_visibility_buffer_pipeline);334clear_visibility_buffer_pass.set_immediates(0, bytemuck::bytes_of(&view_size));335clear_visibility_buffer_pass.set_bind_group(0, clear_visibility_buffer_bind_group, &[]);336clear_visibility_buffer_pass.dispatch_workgroups(337view_size.x.div_ceil(16),338view_size.y.div_ceil(16),3391,340);341}342343fn first_cull(344ctx: &mut RenderContext,345meshlet_view_bind_groups: &MeshletViewBindGroups,346meshlet_view_resources: &MeshletViewResources,347view_offset: &ViewUniformOffset,348previous_view_offset: &PreviousViewUniformOffset,349first_instance_cull_pipeline: &ComputePipeline,350first_bvh_cull_pipeline: &ComputePipeline,351first_meshlet_cull_pipeline: &ComputePipeline,352remap_1d_to_2d_pipeline: Option<&ComputePipeline>,353) {354let workgroups = meshlet_view_resources.scene_instance_count.div_ceil(128);355cull_pass(356"meshlet_first_instance_cull",357ctx,358&meshlet_view_bind_groups.first_instance_cull,359view_offset,360previous_view_offset,361first_instance_cull_pipeline,362&[meshlet_view_resources.scene_instance_count],363)364.dispatch_workgroups(workgroups, 1, 1);365366ctx.command_encoder()367.push_debug_group("meshlet_first_bvh_cull");368let mut ping = true;369for _ in 0..meshlet_view_resources.max_bvh_depth {370cull_pass(371"meshlet_first_bvh_cull_dispatch",372ctx,373if ping {374&meshlet_view_bind_groups.first_bvh_cull_ping375} else {376&meshlet_view_bind_groups.first_bvh_cull_pong377},378view_offset,379previous_view_offset,380first_bvh_cull_pipeline,381&[ping as u32, meshlet_view_resources.rightmost_slot],382)383.dispatch_workgroups_indirect(384if ping {385&meshlet_view_resources.first_bvh_cull_dispatch_front386} else {387&meshlet_view_resources.first_bvh_cull_dispatch_back388},3890,390);391ctx.command_encoder().clear_buffer(392if ping {393&meshlet_view_resources.first_bvh_cull_count_front394} else {395&meshlet_view_resources.first_bvh_cull_count_back396},3970,398Some(4),399);400ctx.command_encoder().clear_buffer(401if ping {402&meshlet_view_resources.first_bvh_cull_dispatch_front403} else {404&meshlet_view_resources.first_bvh_cull_dispatch_back405},4060,407Some(4),408);409ping = !ping;410}411ctx.command_encoder().pop_debug_group();412413let mut pass = cull_pass(414"meshlet_first_meshlet_cull",415ctx,416&meshlet_view_bind_groups.first_meshlet_cull,417view_offset,418previous_view_offset,419first_meshlet_cull_pipeline,420&[meshlet_view_resources.rightmost_slot],421);422pass.dispatch_workgroups_indirect(&meshlet_view_resources.front_meshlet_cull_dispatch, 0);423remap_1d_to_2d(424pass,425remap_1d_to_2d_pipeline,426meshlet_view_bind_groups.remap_1d_to_2d_dispatch.as_ref(),427);428}429430fn second_cull(431ctx: &mut RenderContext,432meshlet_view_bind_groups: &MeshletViewBindGroups,433meshlet_view_resources: &MeshletViewResources,434view_offset: &ViewUniformOffset,435previous_view_offset: &PreviousViewUniformOffset,436second_instance_cull_pipeline: &ComputePipeline,437second_bvh_cull_pipeline: &ComputePipeline,438second_meshlet_cull_pipeline: &ComputePipeline,439remap_1d_to_2d_pipeline: Option<&ComputePipeline>,440) {441cull_pass(442"meshlet_second_instance_cull",443ctx,444&meshlet_view_bind_groups.second_instance_cull,445view_offset,446previous_view_offset,447second_instance_cull_pipeline,448&[meshlet_view_resources.scene_instance_count],449)450.dispatch_workgroups_indirect(&meshlet_view_resources.second_pass_dispatch, 0);451452ctx.command_encoder()453.push_debug_group("meshlet_second_bvh_cull");454let mut ping = true;455for _ in 0..meshlet_view_resources.max_bvh_depth {456cull_pass(457"meshlet_second_bvh_cull_dispatch",458ctx,459if ping {460&meshlet_view_bind_groups.second_bvh_cull_ping461} else {462&meshlet_view_bind_groups.second_bvh_cull_pong463},464view_offset,465previous_view_offset,466second_bvh_cull_pipeline,467&[ping as u32, meshlet_view_resources.rightmost_slot],468)469.dispatch_workgroups_indirect(470if ping {471&meshlet_view_resources.second_bvh_cull_dispatch_front472} else {473&meshlet_view_resources.second_bvh_cull_dispatch_back474},4750,476);477ping = !ping;478}479ctx.command_encoder().pop_debug_group();480481let mut pass = cull_pass(482"meshlet_second_meshlet_cull",483ctx,484&meshlet_view_bind_groups.second_meshlet_cull,485view_offset,486previous_view_offset,487second_meshlet_cull_pipeline,488&[meshlet_view_resources.rightmost_slot],489);490pass.dispatch_workgroups_indirect(&meshlet_view_resources.back_meshlet_cull_dispatch, 0);491remap_1d_to_2d(492pass,493remap_1d_to_2d_pipeline,494meshlet_view_bind_groups.remap_1d_to_2d_dispatch.as_ref(),495);496}497498fn cull_pass<'a>(499label: &'static str,500ctx: &'a mut RenderContext,501bind_group: &'a BindGroup,502view_offset: &'a ViewUniformOffset,503previous_view_offset: &'a PreviousViewUniformOffset,504pipeline: &'a ComputePipeline,505immediates: &[u32],506) -> ComputePass<'a> {507let command_encoder = ctx.command_encoder();508let mut pass = command_encoder.begin_compute_pass(&ComputePassDescriptor {509label: Some(label),510timestamp_writes: None,511});512pass.set_pipeline(pipeline);513pass.set_bind_group(5140,515bind_group,516&[view_offset.offset, previous_view_offset.offset],517);518pass.set_immediates(0, bytemuck::cast_slice(immediates));519pass520}521522fn remap_1d_to_2d(523mut pass: ComputePass,524pipeline: Option<&ComputePipeline>,525bind_group: Option<&BindGroup>,526) {527if let (Some(pipeline), Some(bind_group)) = (pipeline, bind_group) {528pass.set_pipeline(pipeline);529pass.set_bind_group(0, bind_group, &[]);530pass.dispatch_workgroups(1, 1, 1);531}532}533534fn raster_pass(535first_pass: bool,536ctx: &mut RenderContext,537visibility_buffer_software_raster_indirect_args: &Buffer,538visibility_buffer_hardware_raster_indirect_args: &Buffer,539dummy_render_target: &TextureView,540meshlet_view_bind_groups: &MeshletViewBindGroups,541view_offset: &ViewUniformOffset,542visibility_buffer_software_raster_pipeline: &ComputePipeline,543visibility_buffer_hardware_raster_pipeline: &RenderPipeline,544fill_counts_pipeline: &ComputePipeline,545camera: Option<&ExtractedCamera>,546raster_cluster_rightmost_slot: u32,547) {548let mut software_pass = ctx549.command_encoder()550.begin_compute_pass(&ComputePassDescriptor {551label: Some(if first_pass {552"raster_software_first"553} else {554"raster_software_second"555}),556timestamp_writes: None,557});558software_pass.set_pipeline(visibility_buffer_software_raster_pipeline);559software_pass.set_bind_group(5600,561&meshlet_view_bind_groups.visibility_buffer_raster,562&[view_offset.offset],563);564software_pass.dispatch_workgroups_indirect(visibility_buffer_software_raster_indirect_args, 0);565drop(software_pass);566567let mut hardware_pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {568label: Some(if first_pass {569"raster_hardware_first"570} else {571"raster_hardware_second"572}),573color_attachments: &[Some(RenderPassColorAttachment {574view: dummy_render_target,575depth_slice: None,576resolve_target: None,577ops: Operations {578load: LoadOp::Clear(LinearRgba::BLACK.into()),579store: StoreOp::Discard,580},581})],582depth_stencil_attachment: None,583timestamp_writes: None,584occlusion_query_set: None,585multiview_mask: None,586});587if let Some(viewport) = camera.and_then(|camera| camera.viewport.as_ref()) {588hardware_pass.set_camera_viewport(viewport);589}590hardware_pass.set_render_pipeline(visibility_buffer_hardware_raster_pipeline);591hardware_pass.set_immediates(0, &raster_cluster_rightmost_slot.to_le_bytes());592hardware_pass.set_bind_group(5930,594&meshlet_view_bind_groups.visibility_buffer_raster,595&[view_offset.offset],596);597hardware_pass.draw_indirect(visibility_buffer_hardware_raster_indirect_args, 0);598drop(hardware_pass);599600let mut fill_counts_pass = ctx601.command_encoder()602.begin_compute_pass(&ComputePassDescriptor {603label: Some("fill_counts"),604timestamp_writes: None,605});606fill_counts_pass.set_pipeline(fill_counts_pipeline);607fill_counts_pass.set_bind_group(0, &meshlet_view_bind_groups.fill_counts, &[]);608fill_counts_pass.dispatch_workgroups(1, 1, 1);609}610611fn resolve_depth(612ctx: &mut RenderContext,613depth_stencil_attachment: RenderPassDepthStencilAttachment,614meshlet_view_bind_groups: &MeshletViewBindGroups,615resolve_depth_pipeline: &RenderPipeline,616camera: &ExtractedCamera,617) {618let mut resolve_pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {619label: Some("resolve_depth"),620color_attachments: &[],621depth_stencil_attachment: Some(depth_stencil_attachment),622timestamp_writes: None,623occlusion_query_set: None,624multiview_mask: None,625});626if let Some(viewport) = &camera.viewport {627resolve_pass.set_camera_viewport(viewport);628}629resolve_pass.set_render_pipeline(resolve_depth_pipeline);630resolve_pass.set_bind_group(0, &meshlet_view_bind_groups.resolve_depth, &[]);631resolve_pass.draw(0..3, 0..1);632}633634fn resolve_material_depth(635ctx: &mut RenderContext,636meshlet_view_resources: &MeshletViewResources,637meshlet_view_bind_groups: &MeshletViewBindGroups,638resolve_material_depth_pipeline: &RenderPipeline,639camera: &ExtractedCamera,640) {641if let (Some(material_depth), Some(resolve_material_depth_bind_group)) = (642meshlet_view_resources.material_depth.as_ref(),643meshlet_view_bind_groups.resolve_material_depth.as_ref(),644) {645let mut resolve_pass = ctx.begin_tracked_render_pass(RenderPassDescriptor {646label: Some("resolve_material_depth"),647color_attachments: &[],648depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {649view: &material_depth.default_view,650depth_ops: Some(Operations {651load: LoadOp::Clear(0.0),652store: StoreOp::Store,653}),654stencil_ops: None,655}),656timestamp_writes: None,657occlusion_query_set: None,658multiview_mask: None,659});660if let Some(viewport) = &camera.viewport {661resolve_pass.set_camera_viewport(viewport);662}663resolve_pass.set_render_pipeline(resolve_material_depth_pipeline);664resolve_pass.set_bind_group(0, resolve_material_depth_bind_group, &[]);665resolve_pass.draw(0..3, 0..1);666}667}668669670