From c3f72ba4ad4a005b4560029ad65bb4efc9ad74d5 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Sun, 23 Mar 2025 09:42:44 +0000 Subject: [PATCH] Skip camera look ups in queue uinodes (#17668) # Objective `queue_uinodes` looks up the `ExtractedView` for every extracted UI node, but there's no need to look it up again if consecutive nodes have the same `extracted_camera_entity`. ## Solution In queue uinodes reuse the previously looked up extracted view if the `extracted_camera_entity` doesn't change ## Showcase ``` cargo run --example many_buttons --release --features "trace_tracy" ``` queue-ui-improvement yellow is this PR, red is main --- crates/bevy_ui/src/render/mod.rs | 37 ++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index b5d24f194d..6f691d4163 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -946,26 +946,34 @@ pub fn queue_uinodes( ui_pipeline: Res, mut pipelines: ResMut>, mut transparent_render_phases: ResMut>, - mut render_views: Query<(&UiCameraView, Option<&UiAntiAlias>), With>, + render_views: Query<(&UiCameraView, Option<&UiAntiAlias>), With>, camera_views: Query<&ExtractedView>, pipeline_cache: Res, draw_functions: Res>, ) { let draw_function = draw_functions.read().id::(); + let mut current_camera_entity = Entity::PLACEHOLDER; + let mut current_phase = None; + for (index, extracted_uinode) in extracted_uinodes.uinodes.iter().enumerate() { - let entity = extracted_uinode.render_entity; - let Ok((default_camera_view, ui_anti_alias)) = - render_views.get_mut(extracted_uinode.extracted_camera_entity) - else { - continue; - }; + if current_camera_entity != extracted_uinode.extracted_camera_entity { + current_phase = render_views + .get(extracted_uinode.extracted_camera_entity) + .ok() + .and_then(|(default_camera_view, ui_anti_alias)| { + camera_views + .get(default_camera_view.0) + .ok() + .and_then(|view| { + transparent_render_phases + .get_mut(&view.retained_view_entity) + .map(|transparent_phase| (view, ui_anti_alias, transparent_phase)) + }) + }); + current_camera_entity = extracted_uinode.extracted_camera_entity; + } - let Ok(view) = camera_views.get(default_camera_view.0) else { - continue; - }; - - let Some(transparent_phase) = transparent_render_phases.get_mut(&view.retained_view_entity) - else { + let Some((view, ui_anti_alias, transparent_phase)) = current_phase.as_mut() else { continue; }; @@ -977,10 +985,11 @@ pub fn queue_uinodes( anti_alias: matches!(ui_anti_alias, None | Some(UiAntiAlias::On)), }, ); + transparent_phase.add(TransparentUi { draw_function, pipeline, - entity: (entity, extracted_uinode.main_entity), + entity: (extracted_uinode.render_entity, extracted_uinode.main_entity), sort_key: FloatOrd(extracted_uinode.stack_index as f32 + stack_z_offsets::NODE), index, // batch_range will be calculated in prepare_uinodes