From 6b837dd2976df486dcace1dc870612479f72692a Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Thu, 13 Feb 2025 22:43:35 -0800 Subject: [PATCH] Remove prepasses from the render world when they're removed from the main world. (#17565) This makes switching rendering modes in `deferred_rendering` work again. Closes #16679. --- crates/bevy_core_pipeline/src/core_3d/mod.rs | 35 +++++++++++--- crates/bevy_pbr/src/deferred/mod.rs | 48 +++++++++++--------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 7572d80b3944e..d09f6a55250bf 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -718,13 +718,35 @@ pub fn extract_camera_prepass_phase( } live_entities.insert(retained_view_entity); - commands + // Add or remove prepasses as appropriate. + + let mut camera_commands = commands .get_entity(entity) - .expect("Camera entity wasn't synced.") - .insert_if(DepthPrepass, || depth_prepass) - .insert_if(NormalPrepass, || normal_prepass) - .insert_if(MotionVectorPrepass, || motion_vector_prepass) - .insert_if(DeferredPrepass, || deferred_prepass); + .expect("Camera entity wasn't synced."); + + if depth_prepass { + camera_commands.insert(DepthPrepass); + } else { + camera_commands.remove::(); + } + + if normal_prepass { + camera_commands.insert(NormalPrepass); + } else { + camera_commands.remove::(); + } + + if motion_vector_prepass { + camera_commands.insert(MotionVectorPrepass); + } else { + camera_commands.remove::(); + } + + if deferred_prepass { + camera_commands.insert(DeferredPrepass); + } else { + camera_commands.remove::(); + } } opaque_3d_prepass_phases.retain(|view_entity, _| live_entities.contains(view_entity)); @@ -986,6 +1008,7 @@ pub fn prepare_prepass_textures( && !opaque_3d_deferred_phases.contains_key(&view.retained_view_entity) && !alpha_mask_3d_deferred_phases.contains_key(&view.retained_view_entity) { + commands.entity(entity).remove::(); continue; }; diff --git a/crates/bevy_pbr/src/deferred/mod.rs b/crates/bevy_pbr/src/deferred/mod.rs index 5738cdd25dacf..c7d7e04636150 100644 --- a/crates/bevy_pbr/src/deferred/mod.rs +++ b/crates/bevy_pbr/src/deferred/mod.rs @@ -432,28 +432,26 @@ pub fn prepare_deferred_lighting_pipelines( pipeline_cache: Res, mut pipelines: ResMut>, deferred_lighting_layout: Res, - views: Query< + views: Query<( + Entity, + &ExtractedView, + Option<&Tonemapping>, + Option<&DebandDither>, + Option<&ShadowFilteringMethod>, ( - Entity, - &ExtractedView, - Option<&Tonemapping>, - Option<&DebandDither>, - Option<&ShadowFilteringMethod>, - ( - Has, - Has, - Has, - ), - ( - Has, - Has, - Has, - ), - Has>, - Has>, + Has, + Has, + Has, + ), + ( + Has, + Has, + Has, + Has, ), - With, - >, + Has>, + Has>, + )>, ) { for ( entity, @@ -462,11 +460,19 @@ pub fn prepare_deferred_lighting_pipelines( dither, shadow_filter_method, (ssao, ssr, distance_fog), - (normal_prepass, depth_prepass, motion_vector_prepass), + (normal_prepass, depth_prepass, motion_vector_prepass, deferred_prepass), has_environment_maps, has_irradiance_volumes, ) in &views { + // If there is no deferred prepass, remove the old pipeline if there was + // one. This handles the case in which a view using deferred stops using + // it. + if !deferred_prepass { + commands.entity(entity).remove::(); + continue; + } + let mut view_key = MeshPipelineKey::from_hdr(view.hdr); if normal_prepass {