From 74c97332a68177849bd73bbbb2df6a8377049476 Mon Sep 17 00:00:00 2001 From: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com> Date: Tue, 14 Nov 2023 03:13:21 +0100 Subject: [PATCH] Ignore inactive cameras (#10543) # Objective Currently, if a large amount of inactive cameras are spawned, they will immensely slow down performance. This can be reproduced by adding ```rust let default_image = images.add(default()); for _ in 0..10000 { commands.spawn(Camera3dBundle { camera: Camera { is_active: false, target: RenderTarget::Image(default_image.clone()), ..default() }, ..default() }); } ``` to for example `3d_shapes`. Using `tracy`, it's clear that preparing view bind groups for all cameras is still happening. Also, visibility checks on the extracted views from inactive cameras also take place. ## Performance gains The following `tracy` comparisons show the effect of skipping this unneeded work. Yellow is Bevy main, red is with the fix. ### Visibility checks ![bevy-visibility-check-savings](https://github.com/bevyengine/bevy/assets/52322338/154a20ce-bd70-487e-a85c-8b993950ea2b) ### Bind group preparation ![bevy-mesh2d-savings](https://github.com/bevyengine/bevy/assets/52322338/a48d8d9a-8c37-4c34-9698-b1b1bf01f070) ## Solution - Check if the cameras are inactive in the appropriate places, and if so skip them ## Changelog ### Changed - Do not extract views from inactive cameras or check visiblity from their extracted views Signed-off-by: Torstein Grindvik Co-authored-by: Torstein Grindvik --- crates/bevy_render/src/view/visibility/mod.rs | 13 +++++++++++-- crates/bevy_ui/src/render/mod.rs | 5 +++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 0bd224f4d4..49bb64b689 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -384,7 +384,12 @@ fn reset_view_visibility(mut query: Query<&mut ViewVisibility>) { /// for that view. pub fn check_visibility( mut thread_queues: Local>>>, - mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With>, + mut view_query: Query<( + &mut VisibleEntities, + &Frustum, + Option<&RenderLayers>, + &Camera, + )>, mut visible_aabb_query: Query<( Entity, &InheritedVisibility, @@ -395,7 +400,11 @@ pub fn check_visibility( Has, )>, ) { - for (mut visible_entities, frustum, maybe_view_mask) in &mut view_query { + for (mut visible_entities, frustum, maybe_view_mask, camera) in &mut view_query { + if !camera.is_active { + continue; + } + let view_mask = maybe_view_mask.copied().unwrap_or_default(); visible_entities.entities.clear(); diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index f63fd1a0dc..b86f6544e6 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -551,6 +551,11 @@ pub fn extract_default_ui_camera_view( if matches!(camera_ui, Some(&UiCameraConfig { show_ui: false, .. })) { continue; } + // ignore inactive cameras + if !camera.is_active { + continue; + } + if let ( Some(logical_size), Some(URect {