Path: blob/main/crates/bevy_pbr/src/meshlet/material_shade_nodes.rs
6600 views
use super::{1material_pipeline_prepare::{2MeshletViewMaterialsDeferredGBufferPrepass, MeshletViewMaterialsMainOpaquePass,3MeshletViewMaterialsPrepass,4},5resource_manager::{MeshletViewBindGroups, MeshletViewResources},6InstanceManager,7};8use crate::{9MeshViewBindGroup, PrepassViewBindGroup, ViewEnvironmentMapUniformOffset, ViewFogUniformOffset,10ViewLightProbesUniformOffset, ViewLightsUniformOffset, ViewScreenSpaceReflectionsUniformOffset,11};12use bevy_camera::MainPassResolutionOverride;13use bevy_camera::Viewport;14use bevy_core_pipeline::prepass::{15MotionVectorPrepass, PreviousViewUniformOffset, ViewPrepassTextures,16};17use bevy_ecs::{18query::{Has, QueryItem},19world::World,20};21use bevy_render::{22camera::ExtractedCamera,23diagnostic::RecordDiagnostics,24render_graph::{NodeRunError, RenderGraphContext, ViewNode},25render_resource::{26LoadOp, Operations, PipelineCache, RenderPassDepthStencilAttachment, RenderPassDescriptor,27StoreOp,28},29renderer::RenderContext,30view::{ViewTarget, ViewUniformOffset},31};3233/// Fullscreen shading pass based on the visibility buffer generated from rasterizing meshlets.34#[derive(Default)]35pub struct MeshletMainOpaquePass3dNode;36impl ViewNode for MeshletMainOpaquePass3dNode {37type ViewQuery = (38&'static ExtractedCamera,39&'static ViewTarget,40&'static MeshViewBindGroup,41&'static ViewUniformOffset,42&'static ViewLightsUniformOffset,43&'static ViewFogUniformOffset,44&'static ViewLightProbesUniformOffset,45&'static ViewScreenSpaceReflectionsUniformOffset,46&'static ViewEnvironmentMapUniformOffset,47Option<&'static MainPassResolutionOverride>,48&'static MeshletViewMaterialsMainOpaquePass,49&'static MeshletViewBindGroups,50&'static MeshletViewResources,51);5253fn run(54&self,55_graph: &mut RenderGraphContext,56render_context: &mut RenderContext,57(58camera,59target,60mesh_view_bind_group,61view_uniform_offset,62view_lights_offset,63view_fog_offset,64view_light_probes_offset,65view_ssr_offset,66view_environment_map_offset,67resolution_override,68meshlet_view_materials,69meshlet_view_bind_groups,70meshlet_view_resources,71): QueryItem<Self::ViewQuery>,72world: &World,73) -> Result<(), NodeRunError> {74if meshlet_view_materials.is_empty() {75return Ok(());76}7778let (79Some(instance_manager),80Some(pipeline_cache),81Some(meshlet_material_depth),82Some(meshlet_material_shade_bind_group),83) = (84world.get_resource::<InstanceManager>(),85world.get_resource::<PipelineCache>(),86meshlet_view_resources.material_depth.as_ref(),87meshlet_view_bind_groups.material_shade.as_ref(),88)89else {90return Ok(());91};9293let diagnostics = render_context.diagnostic_recorder();9495let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {96label: Some("meshlet_material_opaque_3d_pass"),97color_attachments: &[Some(target.get_color_attachment())],98depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {99view: &meshlet_material_depth.default_view,100depth_ops: Some(Operations {101load: LoadOp::Load,102store: StoreOp::Store,103}),104stencil_ops: None,105}),106timestamp_writes: None,107occlusion_query_set: None,108});109let pass_span = diagnostics.pass_span(&mut render_pass, "meshlet_material_opaque_3d_pass");110if let Some(viewport) =111Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)112{113render_pass.set_camera_viewport(&viewport);114}115116render_pass.set_bind_group(1170,118&mesh_view_bind_group.main,119&[120view_uniform_offset.offset,121view_lights_offset.offset,122view_fog_offset.offset,123**view_light_probes_offset,124**view_ssr_offset,125**view_environment_map_offset,126],127);128render_pass.set_bind_group(1, &mesh_view_bind_group.binding_array, &[]);129render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);130131// 1 fullscreen triangle draw per material132for (material_id, material_pipeline_id, material_bind_group) in133meshlet_view_materials.iter()134{135if instance_manager.material_present_in_scene(material_id)136&& let Some(material_pipeline) =137pipeline_cache.get_render_pipeline(*material_pipeline_id)138{139let x = *material_id * 3;140render_pass.set_render_pipeline(material_pipeline);141render_pass.set_bind_group(3, material_bind_group, &[]);142render_pass.draw(x..(x + 3), 0..1);143}144}145146pass_span.end(&mut render_pass);147148Ok(())149}150}151152/// Fullscreen pass to generate prepass textures based on the visibility buffer generated from rasterizing meshlets.153#[derive(Default)]154pub struct MeshletPrepassNode;155impl ViewNode for MeshletPrepassNode {156type ViewQuery = (157&'static ExtractedCamera,158&'static ViewPrepassTextures,159&'static ViewUniformOffset,160&'static PreviousViewUniformOffset,161Option<&'static MainPassResolutionOverride>,162Has<MotionVectorPrepass>,163&'static MeshletViewMaterialsPrepass,164&'static MeshletViewBindGroups,165&'static MeshletViewResources,166);167168fn run(169&self,170_graph: &mut RenderGraphContext,171render_context: &mut RenderContext,172(173camera,174view_prepass_textures,175view_uniform_offset,176previous_view_uniform_offset,177resolution_override,178view_has_motion_vector_prepass,179meshlet_view_materials,180meshlet_view_bind_groups,181meshlet_view_resources,182): QueryItem<Self::ViewQuery>,183world: &World,184) -> Result<(), NodeRunError> {185if meshlet_view_materials.is_empty() {186return Ok(());187}188189let (190Some(prepass_view_bind_group),191Some(instance_manager),192Some(pipeline_cache),193Some(meshlet_material_depth),194Some(meshlet_material_shade_bind_group),195) = (196world.get_resource::<PrepassViewBindGroup>(),197world.get_resource::<InstanceManager>(),198world.get_resource::<PipelineCache>(),199meshlet_view_resources.material_depth.as_ref(),200meshlet_view_bind_groups.material_shade.as_ref(),201)202else {203return Ok(());204};205206let diagnostics = render_context.diagnostic_recorder();207208let color_attachments = vec![209view_prepass_textures210.normal211.as_ref()212.map(|normals_texture| normals_texture.get_attachment()),213view_prepass_textures214.motion_vectors215.as_ref()216.map(|motion_vectors_texture| motion_vectors_texture.get_attachment()),217// Use None in place of Deferred attachments218None,219None,220];221222let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {223label: Some("meshlet_material_prepass"),224color_attachments: &color_attachments,225depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {226view: &meshlet_material_depth.default_view,227depth_ops: Some(Operations {228load: LoadOp::Load,229store: StoreOp::Store,230}),231stencil_ops: None,232}),233timestamp_writes: None,234occlusion_query_set: None,235});236let pass_span = diagnostics.pass_span(&mut render_pass, "meshlet_material_prepass");237if let Some(viewport) =238Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)239{240render_pass.set_camera_viewport(&viewport);241}242243if view_has_motion_vector_prepass {244render_pass.set_bind_group(2450,246prepass_view_bind_group.motion_vectors.as_ref().unwrap(),247&[248view_uniform_offset.offset,249previous_view_uniform_offset.offset,250],251);252} else {253render_pass.set_bind_group(2540,255prepass_view_bind_group.no_motion_vectors.as_ref().unwrap(),256&[view_uniform_offset.offset],257);258}259260render_pass.set_bind_group(1, &prepass_view_bind_group.empty_bind_group, &[]);261render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);262263// 1 fullscreen triangle draw per material264for (material_id, material_pipeline_id, material_bind_group) in265meshlet_view_materials.iter()266{267if instance_manager.material_present_in_scene(material_id)268&& let Some(material_pipeline) =269pipeline_cache.get_render_pipeline(*material_pipeline_id)270{271let x = *material_id * 3;272render_pass.set_render_pipeline(material_pipeline);273render_pass.set_bind_group(2, material_bind_group, &[]);274render_pass.draw(x..(x + 3), 0..1);275}276}277278pass_span.end(&mut render_pass);279280Ok(())281}282}283284/// Fullscreen pass to generate a gbuffer based on the visibility buffer generated from rasterizing meshlets.285#[derive(Default)]286pub struct MeshletDeferredGBufferPrepassNode;287impl ViewNode for MeshletDeferredGBufferPrepassNode {288type ViewQuery = (289&'static ExtractedCamera,290&'static ViewPrepassTextures,291&'static ViewUniformOffset,292&'static PreviousViewUniformOffset,293Option<&'static MainPassResolutionOverride>,294Has<MotionVectorPrepass>,295&'static MeshletViewMaterialsDeferredGBufferPrepass,296&'static MeshletViewBindGroups,297&'static MeshletViewResources,298);299300fn run(301&self,302_graph: &mut RenderGraphContext,303render_context: &mut RenderContext,304(305camera,306view_prepass_textures,307view_uniform_offset,308previous_view_uniform_offset,309resolution_override,310view_has_motion_vector_prepass,311meshlet_view_materials,312meshlet_view_bind_groups,313meshlet_view_resources,314): QueryItem<Self::ViewQuery>,315world: &World,316) -> Result<(), NodeRunError> {317if meshlet_view_materials.is_empty() {318return Ok(());319}320321let (322Some(prepass_view_bind_group),323Some(instance_manager),324Some(pipeline_cache),325Some(meshlet_material_depth),326Some(meshlet_material_shade_bind_group),327) = (328world.get_resource::<PrepassViewBindGroup>(),329world.get_resource::<InstanceManager>(),330world.get_resource::<PipelineCache>(),331meshlet_view_resources.material_depth.as_ref(),332meshlet_view_bind_groups.material_shade.as_ref(),333)334else {335return Ok(());336};337338let color_attachments = vec![339view_prepass_textures340.normal341.as_ref()342.map(|normals_texture| normals_texture.get_attachment()),343view_prepass_textures344.motion_vectors345.as_ref()346.map(|motion_vectors_texture| motion_vectors_texture.get_attachment()),347view_prepass_textures348.deferred349.as_ref()350.map(|deferred_texture| deferred_texture.get_attachment()),351view_prepass_textures352.deferred_lighting_pass_id353.as_ref()354.map(|deferred_lighting_pass_id| deferred_lighting_pass_id.get_attachment()),355];356357let diagnostics = render_context.diagnostic_recorder();358359let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {360label: Some("meshlet_material_deferred_prepass"),361color_attachments: &color_attachments,362depth_stencil_attachment: Some(RenderPassDepthStencilAttachment {363view: &meshlet_material_depth.default_view,364depth_ops: Some(Operations {365load: LoadOp::Load,366store: StoreOp::Store,367}),368stencil_ops: None,369}),370timestamp_writes: None,371occlusion_query_set: None,372});373let pass_span =374diagnostics.pass_span(&mut render_pass, "meshlet_material_deferred_prepass");375if let Some(viewport) =376Viewport::from_viewport_and_override(camera.viewport.as_ref(), resolution_override)377{378render_pass.set_camera_viewport(&viewport);379}380381if view_has_motion_vector_prepass {382render_pass.set_bind_group(3830,384prepass_view_bind_group.motion_vectors.as_ref().unwrap(),385&[386view_uniform_offset.offset,387previous_view_uniform_offset.offset,388],389);390} else {391render_pass.set_bind_group(3920,393prepass_view_bind_group.no_motion_vectors.as_ref().unwrap(),394&[view_uniform_offset.offset],395);396}397398render_pass.set_bind_group(1, &prepass_view_bind_group.empty_bind_group, &[]);399render_pass.set_bind_group(2, meshlet_material_shade_bind_group, &[]);400401// 1 fullscreen triangle draw per material402for (material_id, material_pipeline_id, material_bind_group) in403meshlet_view_materials.iter()404{405if instance_manager.material_present_in_scene(material_id)406&& let Some(material_pipeline) =407pipeline_cache.get_render_pipeline(*material_pipeline_id)408{409let x = *material_id * 3;410render_pass.set_render_pipeline(material_pipeline);411render_pass.set_bind_group(2, material_bind_group, &[]);412render_pass.draw(x..(x + 3), 0..1);413}414}415416pass_span.end(&mut render_pass);417418Ok(())419}420}421422423