From 64cc9e71b5b030b22ca42a954f1b422cd39b45c7 Mon Sep 17 00:00:00 2001 From: CodingDaniel1 Date: Sun, 13 Sep 2026 14:52:43 +0800 Subject: [PATCH 1/4] fix the issue --- crates/bevy_pbr/src/render/light.rs | 37 +++-- crates/bevy_pbr/src/render/mesh.rs | 130 +++++++++++++----- crates/bevy_render/src/camera.rs | 21 +-- crates/bevy_render/src/view/visibility/mod.rs | 12 ++ 4 files changed, 148 insertions(+), 52 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index d7187be5be754..af7899aeb05e4 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -48,8 +48,8 @@ use bevy_render::occlusion_culling::{ }; use bevy_render::sync_world::{MainEntity, MainEntityHashMap, MainEntityHashSet, RenderEntity}; use bevy_render::view::{ - RenderExtractedShadowMapVisibleEntities, RenderShadowLodOrigin, RenderShadowMapVisibleEntities, - RenderVisibleEntities, VisibilityExtractionSystemParam, + ExtractedRenderLayersMeta, RenderExtractedShadowMapVisibleEntities, RenderShadowLodOrigin, + RenderShadowMapVisibleEntities, RenderVisibleEntities, VisibilityExtractionSystemParam, }; use bevy_render::{ batching::gpu_preprocessing::{GpuPreprocessingMode, GpuPreprocessingSupport}, @@ -344,7 +344,7 @@ pub fn extract_lights( &GlobalTransform, &ViewVisibility, &CubemapFrusta, - Option<&RenderLayers>, + Option>, Option<&VolumetricLight>, ), Or<( @@ -368,7 +368,7 @@ pub fn extract_lights( &GlobalTransform, &ViewVisibility, &Frustum, - Option<&RenderLayers>, + Option>, Option<&VolumetricLight>, ), Or<( @@ -394,7 +394,7 @@ pub fn extract_lights( &CascadesFrusta, &GlobalTransform, &ViewVisibility, - Option<&RenderLayers>, + Option>, Option<&VolumetricLight>, Has, Option<&SunDisk>, @@ -595,7 +595,14 @@ pub fn extract_lights( extracted_point_light, (*frusta).clone(), MainEntity::from(main_entity), - maybe_render_layers.unwrap_or_default().clone(), + maybe_render_layers.map_or_default(|render_layers| { + ( + (*render_layers).clone(), + ExtractedRenderLayersMeta { + changed: render_layers.is_changed(), + }, + ) + }), )); } @@ -734,7 +741,14 @@ pub fn extract_lights( extracted_spot_light, *frustum, MainEntity::from(main_entity), - maybe_render_layers.unwrap_or_default().clone(), + maybe_render_layers.map_or_default(|render_layers| { + ( + (*render_layers).clone(), + ExtractedRenderLayersMeta { + changed: render_layers.is_changed(), + }, + ) + }), )); } @@ -892,7 +906,14 @@ pub fn extract_lights( entity_commands.insert(( extracted_directional_light, MainEntity::from(main_entity), - maybe_render_layers.unwrap_or_default().clone(), + maybe_render_layers.map_or_default(|render_layers| { + ( + (*render_layers).clone(), + ExtractedRenderLayersMeta { + changed: render_layers.is_changed(), + }, + ) + }), )); } diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 05c268f4fbc6a..72afefb5dcf81 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -103,7 +103,7 @@ use bevy_render::camera::{DirtySpecializations, ExtractedCamera, TemporalJitter} use bevy_render::prelude::Msaa; use bevy_render::sync_world::{MainEntity, MainEntityHashMap}; use bevy_render::view::{ - texture_format_from_code, texture_format_to_code, ExtractedView, + texture_format_from_code, texture_format_to_code, ExtractedRenderLayersMeta, ExtractedView, RenderShadowMapVisibleEntities, RenderVisibleEntities, }; use bevy_render::RenderSystems::PrepareAssets; @@ -2285,34 +2285,57 @@ impl<'a> Iterator for AtomicU64ZeroBitIter<'a> { /// Each view must maintain a separate list of GPU-culled entities because the /// views and entities might belong to different render layers. pub fn collect_gpu_culled_meshes( - mut cameras: Query<(Option<&RenderLayers>, &mut RenderVisibleEntities), With>, - mut lights: Query<(Option<&RenderLayers>, &mut RenderShadowMapVisibleEntities)>, + mut cameras: Query< + ( + Option<&RenderLayers>, + Option<&ExtractedRenderLayersMeta>, + &mut RenderVisibleEntities, + ), + With, + >, + mut lights: Query<( + Option<&RenderLayers>, + Option<&ExtractedRenderLayersMeta>, + &mut RenderShadowMapVisibleEntities, + )>, render_gpu_culled_entities: Res, ) { let default_render_layers = RenderLayers::default(); // Collect cameras. - for (maybe_render_layers, mut render_visible_entities) in &mut cameras { + for (maybe_render_layers, maybe_extracted_render_layers_meta, mut render_visible_entities) in + &mut cameras + { let just_added_render_visible_entities = render_visible_entities.is_added(); collect_gpu_culled_meshes_for_subview( maybe_render_layers.unwrap_or(&default_render_layers), &mut render_visible_entities, + maybe_extracted_render_layers_meta + .is_some_and(|extracted_render_layers_meta| extracted_render_layers_meta.changed), just_added_render_visible_entities, &render_gpu_culled_entities, ); } // Collect shadow maps. - for (maybe_render_layers, mut render_shadow_map_visible_entities) in &mut lights { + for ( + maybe_render_layers, + maybe_extracted_render_layers_meta, + mut render_shadow_map_visible_entities, + ) in &mut lights + { let last_run = render_shadow_map_visible_entities.last_run(); let this_run = render_shadow_map_visible_entities.this_run(); + let view_render_layers_changed = maybe_extracted_render_layers_meta + .is_some_and(|extracted_render_layers_meta| extracted_render_layers_meta.changed); for (render_visible_entities_added_tick, render_visible_entities) in render_shadow_map_visible_entities.subviews.values_mut() { collect_gpu_culled_meshes_for_subview( maybe_render_layers.unwrap_or(&default_render_layers), render_visible_entities, + view_render_layers_changed, render_visible_entities_added_tick.is_newer_than(last_run, this_run), &render_gpu_culled_entities, ); @@ -2329,6 +2352,7 @@ pub fn collect_gpu_culled_meshes( fn collect_gpu_culled_meshes_for_subview( view_render_layers: &RenderLayers, render_visible_entities: &mut RenderVisibleEntities, + view_render_layers_changed: bool, just_added_render_visible_entities: bool, render_mesh_instance_gpu_queues: &RenderGpuCulledEntities, ) { @@ -2392,39 +2416,73 @@ fn collect_gpu_culled_meshes_for_subview( } // Process entities that changed layers. - for main_entity in &render_mesh_instance_gpu_queues.changed_layers { - let Some(render_layers) = render_mesh_instance_gpu_queues.entities.get(main_entity) - else { - continue; - }; + if view_render_layers_changed { + for (main_entity, render_layers) in render_mesh_instance_gpu_queues.entities.iter() { + let entity_is_relevant = is_entity_relevant(render_layers); + let entity_was_relevant = render_view_visible_mesh_entities + .entities_gpu_culling + .contains_key(main_entity); - // This is either treated as no change, as an addition, or as a removal. - let entity_was_relevant = render_view_visible_mesh_entities - .entities_gpu_culling - .contains_key(main_entity); - let entity_is_relevant = is_entity_relevant(render_layers); - match (entity_was_relevant, entity_is_relevant) { - (false, false) | (true, true) => { - // No change; do nothing. - } - (false, true) => { - // The entity became visible. This is an addition. - render_view_visible_mesh_entities - .entities_gpu_culling - .insert(*main_entity, Entity::PLACEHOLDER); - render_view_visible_mesh_entities - .added_entities - .push((Entity::PLACEHOLDER, *main_entity)); - any_added = true; + match (entity_was_relevant, entity_is_relevant) { + (false, false) | (true, true) => { + // No change; do nothing. + } + (false, true) => { + // The entity became visible. This is an addition. + render_view_visible_mesh_entities + .entities_gpu_culling + .insert(*main_entity, Entity::PLACEHOLDER); + render_view_visible_mesh_entities + .added_entities + .push((Entity::PLACEHOLDER, *main_entity)); + any_added = true; + } + (true, false) => { + // The entity became invisible. This is a removal. + render_view_visible_mesh_entities + .entities_gpu_culling + .remove(main_entity); + render_view_visible_mesh_entities + .removed_entities + .push((Entity::PLACEHOLDER, *main_entity)); + } } - (true, false) => { - // The entity became invisible. This is a removal. - render_view_visible_mesh_entities - .entities_gpu_culling - .remove(main_entity); - render_view_visible_mesh_entities - .removed_entities - .push((Entity::PLACEHOLDER, *main_entity)); + } + } else { + for main_entity in &render_mesh_instance_gpu_queues.changed_layers { + let Some(render_layers) = render_mesh_instance_gpu_queues.entities.get(main_entity) + else { + continue; + }; + + // This is either treated as no change, as an addition, or as a removal. + let entity_was_relevant = render_view_visible_mesh_entities + .entities_gpu_culling + .contains_key(main_entity); + let entity_is_relevant = is_entity_relevant(render_layers); + match (entity_was_relevant, entity_is_relevant) { + (false, false) | (true, true) => { + // No change; do nothing. + } + (false, true) => { + // The entity became visible. This is an addition. + render_view_visible_mesh_entities + .entities_gpu_culling + .insert(*main_entity, Entity::PLACEHOLDER); + render_view_visible_mesh_entities + .added_entities + .push((Entity::PLACEHOLDER, *main_entity)); + any_added = true; + } + (true, false) => { + // The entity became invisible. This is a removal. + render_view_visible_mesh_entities + .entities_gpu_culling + .remove(main_entity); + render_view_visible_mesh_entities + .removed_entities + .push((Entity::PLACEHOLDER, *main_entity)); + } } } } diff --git a/crates/bevy_render/src/camera.rs b/crates/bevy_render/src/camera.rs index 848005cc0d46f..52a471b6d74cc 100644 --- a/crates/bevy_render/src/camera.rs +++ b/crates/bevy_render/src/camera.rs @@ -10,10 +10,10 @@ use crate::{ sync_world::{MainEntity, MainEntityHashSet, RenderEntity, SyncToRenderWorld}, texture::{GpuImage, ManualTextureViews}, view::{ - ColorGrading, ExtractedView, ExtractedWindow, Msaa, NoIndirectDrawing, - RenderExtractedVisibleEntities, RenderVisibleEntities, RenderVisibleEntitiesClass, - ResolvedCompositingSpace, RetainedViewEntity, ViewUniformOffset, - VisibilityExtractionSystemParam, + ColorGrading, ExtractedRenderLayersMeta, ExtractedView, ExtractedWindow, Msaa, + NoIndirectDrawing, RenderExtractedVisibleEntities, RenderVisibleEntities, + RenderVisibleEntitiesClass, ResolvedCompositingSpace, RetainedViewEntity, + ViewUniformOffset, VisibilityExtractionSystemParam, }, Extract, ExtractSchedule, Render, RenderApp, RenderSystems, }; @@ -41,7 +41,7 @@ use bevy_ecs::{ resource::Resource, schedule::{InternedScheduleLabel, IntoScheduleConfigs, ScheduleLabel, SystemSet}, system::{Commands, Query, Res, ResMut}, - world::DeferredWorld, + world::{DeferredWorld, Ref}, }; use bevy_image::Image; use bevy_log::warn; @@ -490,7 +490,7 @@ pub fn extract_cameras( Option<&Exposure>, Option<&TemporalJitter>, Option<&MipBias>, - Option<&RenderLayers>, + Option>, Option<&Projection>, Has, ), @@ -677,9 +677,14 @@ pub fn extract_cameras( } if let Some(render_layers) = render_layers { - commands.insert(render_layers.clone()); + commands.insert(( + (*render_layers).clone(), + ExtractedRenderLayersMeta { + changed: render_layers.is_changed(), + }, + )); } else { - commands.remove::(); + commands.remove::<(RenderLayers, ExtractedRenderLayersMeta)>(); } if let Some(projection) = projection { diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index aa4e8d78c3c60..c441a6818cd21 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -27,6 +27,18 @@ mod range; use bevy_camera::visibility::*; pub use range::*; +/// Extracted metadata about [`RenderLayers`]. +/// +/// Presented on every [`ExtractedView`](crate::view::ExtractedView) with [`RenderLayers`]. E.g. extracted camera, extracted light shadow map views. +/// +/// Currently this is used for detecting render layers changes on the view for gpu culling entities. +/// Since cpu culling entities is not retained, thus does not care about render layers metadata +#[derive(Debug, Clone, Copy, PartialEq, Eq, Component, Default)] +pub struct ExtractedRenderLayersMeta { + /// Did render layers change in this extracted frame + pub changed: bool, +} + /// Stores a list of all entities that are visible from a single view or /// subview, as well as the change lists. /// From fc7bc3c78fa945b8cc009b8859166dd19966d06c Mon Sep 17 00:00:00 2001 From: CodingDaniel1 Date: Sun, 13 Sep 2026 15:51:22 +0800 Subject: [PATCH 2/4] fix msrv --- crates/bevy_pbr/src/render/light.rs | 6 ++-- examples/3d/3d_scene.rs | 49 ++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index af7899aeb05e4..210ff3fdddd22 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -595,7 +595,7 @@ pub fn extract_lights( extracted_point_light, (*frusta).clone(), MainEntity::from(main_entity), - maybe_render_layers.map_or_default(|render_layers| { + maybe_render_layers.map_or_else(default, |render_layers| { ( (*render_layers).clone(), ExtractedRenderLayersMeta { @@ -741,7 +741,7 @@ pub fn extract_lights( extracted_spot_light, *frustum, MainEntity::from(main_entity), - maybe_render_layers.map_or_default(|render_layers| { + maybe_render_layers.map_or_else(default, |render_layers| { ( (*render_layers).clone(), ExtractedRenderLayersMeta { @@ -906,7 +906,7 @@ pub fn extract_lights( entity_commands.insert(( extracted_directional_light, MainEntity::from(main_entity), - maybe_render_layers.map_or_default(|render_layers| { + maybe_render_layers.map_or_else(default, |render_layers| { ( (*render_layers).clone(), ExtractedRenderLayersMeta { diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index 7665d907756d8..cebecc2624974 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -1,11 +1,16 @@ //! A simple 3D scene with light shining over a cube sitting on a plane. -use bevy::prelude::*; +use bevy::{ + camera::visibility::{NoCpuCulling, RenderLayers}, + prelude::*, +}; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, scene.spawn()) + .add_systems(Update, (change_layers, change_light_layers)) + .add_observer(add_ncl) .run(); } @@ -31,3 +36,45 @@ fn scene() -> impl SceneList { Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y) } } + +fn add_ncl(add: On>, mut commands: Commands) { + commands.entity(add.entity).insert(NoCpuCulling); +} + +fn change_layers( + keyboard: Res>, + query: Query>, + mut commands: Commands, + mut state: Local, +) { + if keyboard.just_pressed(KeyCode::KeyP) { + let layers = if *state { + RenderLayers::layer(0) + } else { + RenderLayers::layer(1) + }; + *state = !*state; + for entity in query { + commands.entity(entity).insert(layers.clone()); + } + } +} + +fn change_light_layers( + keyboard: Res>, + query: Query, With, With)>>, + mut commands: Commands, + mut state: Local, +) { + if keyboard.just_pressed(KeyCode::KeyL) { + let layers = if *state { + RenderLayers::layer(0) + } else { + RenderLayers::layer(1) + }; + *state = !*state; + for entity in query { + commands.entity(entity).insert(layers.clone()); + } + } +} From 6bb3cfb5cd8cf6771192fc823d9ccca8d12cc818 Mon Sep 17 00:00:00 2001 From: CodingDaniel1 Date: Sun, 13 Sep 2026 16:01:24 +0800 Subject: [PATCH 3/4] fix accidently commited 3d_scene example change --- examples/3d/3d_scene.rs | 49 +---------------------------------------- 1 file changed, 1 insertion(+), 48 deletions(-) diff --git a/examples/3d/3d_scene.rs b/examples/3d/3d_scene.rs index cebecc2624974..7665d907756d8 100644 --- a/examples/3d/3d_scene.rs +++ b/examples/3d/3d_scene.rs @@ -1,16 +1,11 @@ //! A simple 3D scene with light shining over a cube sitting on a plane. -use bevy::{ - camera::visibility::{NoCpuCulling, RenderLayers}, - prelude::*, -}; +use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, scene.spawn()) - .add_systems(Update, (change_layers, change_light_layers)) - .add_observer(add_ncl) .run(); } @@ -36,45 +31,3 @@ fn scene() -> impl SceneList { Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y) } } - -fn add_ncl(add: On>, mut commands: Commands) { - commands.entity(add.entity).insert(NoCpuCulling); -} - -fn change_layers( - keyboard: Res>, - query: Query>, - mut commands: Commands, - mut state: Local, -) { - if keyboard.just_pressed(KeyCode::KeyP) { - let layers = if *state { - RenderLayers::layer(0) - } else { - RenderLayers::layer(1) - }; - *state = !*state; - for entity in query { - commands.entity(entity).insert(layers.clone()); - } - } -} - -fn change_light_layers( - keyboard: Res>, - query: Query, With, With)>>, - mut commands: Commands, - mut state: Local, -) { - if keyboard.just_pressed(KeyCode::KeyL) { - let layers = if *state { - RenderLayers::layer(0) - } else { - RenderLayers::layer(1) - }; - *state = !*state; - for entity in query { - commands.entity(entity).insert(layers.clone()); - } - } -} From 2597c97998ceb7c42d4d8d40fec83eef594a7620 Mon Sep 17 00:00:00 2001 From: CodingDaniel1 Date: Thu, 17 Sep 2026 16:33:22 +0800 Subject: [PATCH 4/4] fix extract light shadowmap view incorrectly. deduplicate code. --- crates/bevy_pbr/src/lib.rs | 1 + crates/bevy_pbr/src/render/light.rs | 64 +++++++++++--------- crates/bevy_pbr/src/render/mesh.rs | 93 +++++++++++------------------ 3 files changed, 72 insertions(+), 86 deletions(-) diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 433fd5d14a683..8d7656f3012c0 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -376,6 +376,7 @@ impl Plugin for PbrPlugin { ExtractSchedule, ( extract_lights, + extract_lights_render_layers_meta, extract_ambient_light_resource, extract_ambient_light, extract_shadow_filtering_method, diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 210ff3fdddd22..71ae086236271 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -344,7 +344,7 @@ pub fn extract_lights( &GlobalTransform, &ViewVisibility, &CubemapFrusta, - Option>, + Option<&RenderLayers>, Option<&VolumetricLight>, ), Or<( @@ -368,7 +368,7 @@ pub fn extract_lights( &GlobalTransform, &ViewVisibility, &Frustum, - Option>, + Option<&RenderLayers>, Option<&VolumetricLight>, ), Or<( @@ -394,7 +394,7 @@ pub fn extract_lights( &CascadesFrusta, &GlobalTransform, &ViewVisibility, - Option>, + Option<&RenderLayers>, Option<&VolumetricLight>, Has, Option<&SunDisk>, @@ -595,14 +595,7 @@ pub fn extract_lights( extracted_point_light, (*frusta).clone(), MainEntity::from(main_entity), - maybe_render_layers.map_or_else(default, |render_layers| { - ( - (*render_layers).clone(), - ExtractedRenderLayersMeta { - changed: render_layers.is_changed(), - }, - ) - }), + maybe_render_layers.unwrap_or_default().clone(), )); } @@ -741,14 +734,7 @@ pub fn extract_lights( extracted_spot_light, *frustum, MainEntity::from(main_entity), - maybe_render_layers.map_or_else(default, |render_layers| { - ( - (*render_layers).clone(), - ExtractedRenderLayersMeta { - changed: render_layers.is_changed(), - }, - ) - }), + maybe_render_layers.unwrap_or_default().clone(), )); } @@ -906,14 +892,7 @@ pub fn extract_lights( entity_commands.insert(( extracted_directional_light, MainEntity::from(main_entity), - maybe_render_layers.map_or_else(default, |render_layers| { - ( - (*render_layers).clone(), - ExtractedRenderLayersMeta { - changed: render_layers.is_changed(), - }, - ) - }), + maybe_render_layers.unwrap_or_default().clone(), )); } @@ -972,6 +951,37 @@ pub fn extract_lights( } } +pub fn extract_lights_render_layers_meta( + mut commands: Commands, + all_light_query: Extract< + Query< + (RenderEntity, Ref), + Or<( + With, + With, + With, + With, + )>, + >, + >, + mut extracted_render_layer_meta_query: Query<&mut ExtractedRenderLayersMeta>, +) { + for (render_entity, render_layers) in all_light_query.iter() { + match extracted_render_layer_meta_query.get_mut(render_entity) { + Ok(mut meta) => { + meta.changed = render_layers.is_changed(); + } + Err(_) => { + commands + .entity(render_entity) + .insert(ExtractedRenderLayersMeta { + changed: render_layers.is_changed(), + }); + } + } + } +} + #[derive(Component, Default, Deref, DerefMut)] /// Component automatically attached to a light entity to track light-view entities /// for each view. diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 72afefb5dcf81..8ca7c4f402e84 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -2416,37 +2416,41 @@ fn collect_gpu_culled_meshes_for_subview( } // Process entities that changed layers. - if view_render_layers_changed { - for (main_entity, render_layers) in render_mesh_instance_gpu_queues.entities.iter() { - let entity_is_relevant = is_entity_relevant(render_layers); - let entity_was_relevant = render_view_visible_mesh_entities - .entities_gpu_culling - .contains_key(main_entity); + let mut process_changed_layer = |main_entity: &MainEntity, render_layers: &RenderLayers| { + let entity_is_relevant = is_entity_relevant(render_layers); + let entity_was_relevant = render_view_visible_mesh_entities + .entities_gpu_culling + .contains_key(main_entity); - match (entity_was_relevant, entity_is_relevant) { - (false, false) | (true, true) => { - // No change; do nothing. - } - (false, true) => { - // The entity became visible. This is an addition. - render_view_visible_mesh_entities - .entities_gpu_culling - .insert(*main_entity, Entity::PLACEHOLDER); - render_view_visible_mesh_entities - .added_entities - .push((Entity::PLACEHOLDER, *main_entity)); - any_added = true; - } - (true, false) => { - // The entity became invisible. This is a removal. - render_view_visible_mesh_entities - .entities_gpu_culling - .remove(main_entity); - render_view_visible_mesh_entities - .removed_entities - .push((Entity::PLACEHOLDER, *main_entity)); - } + match (entity_was_relevant, entity_is_relevant) { + (false, false) | (true, true) => { + // No change; do nothing. + } + (false, true) => { + // The entity became visible. This is an addition. + render_view_visible_mesh_entities + .entities_gpu_culling + .insert(*main_entity, Entity::PLACEHOLDER); + render_view_visible_mesh_entities + .added_entities + .push((Entity::PLACEHOLDER, *main_entity)); + any_added = true; } + (true, false) => { + // The entity became invisible. This is a removal. + render_view_visible_mesh_entities + .entities_gpu_culling + .remove(main_entity); + render_view_visible_mesh_entities + .removed_entities + .push((Entity::PLACEHOLDER, *main_entity)); + } + } + }; + + if view_render_layers_changed { + for (main_entity, render_layers) in render_mesh_instance_gpu_queues.entities.iter() { + process_changed_layer(main_entity, render_layers); } } else { for main_entity in &render_mesh_instance_gpu_queues.changed_layers { @@ -2454,36 +2458,7 @@ fn collect_gpu_culled_meshes_for_subview( else { continue; }; - - // This is either treated as no change, as an addition, or as a removal. - let entity_was_relevant = render_view_visible_mesh_entities - .entities_gpu_culling - .contains_key(main_entity); - let entity_is_relevant = is_entity_relevant(render_layers); - match (entity_was_relevant, entity_is_relevant) { - (false, false) | (true, true) => { - // No change; do nothing. - } - (false, true) => { - // The entity became visible. This is an addition. - render_view_visible_mesh_entities - .entities_gpu_culling - .insert(*main_entity, Entity::PLACEHOLDER); - render_view_visible_mesh_entities - .added_entities - .push((Entity::PLACEHOLDER, *main_entity)); - any_added = true; - } - (true, false) => { - // The entity became invisible. This is a removal. - render_view_visible_mesh_entities - .entities_gpu_culling - .remove(main_entity); - render_view_visible_mesh_entities - .removed_entities - .push((Entity::PLACEHOLDER, *main_entity)); - } - } + process_changed_layer(main_entity, render_layers); } }