mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Reduce allocations in ui_layout_system (#15001)
# Objective - Shave off some allocations from `ui_layout_system`. ## Solution - Add a `Local` for allocation buffers.
This commit is contained in:
parent
547b1c7a7a
commit
3fc02cb925
1 changed files with 34 additions and 15 deletions
|
@ -1,11 +1,11 @@
|
||||||
use crate::{ContentSize, DefaultUiCamera, Node, Outline, Style, TargetCamera, UiScale};
|
use crate::{ContentSize, DefaultUiCamera, Node, Outline, Style, TargetCamera, UiScale};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
change_detection::{DetectChanges, DetectChangesMut},
|
change_detection::{DetectChanges, DetectChangesMut},
|
||||||
entity::Entity,
|
entity::{Entity, EntityHashMap, EntityHashSet},
|
||||||
event::EventReader,
|
event::EventReader,
|
||||||
query::{With, Without},
|
query::{With, Without},
|
||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
system::{Query, Res, ResMut, SystemParam},
|
system::{Local, Query, Res, ResMut, SystemParam},
|
||||||
world::Ref,
|
world::Ref,
|
||||||
};
|
};
|
||||||
use bevy_hierarchy::{Children, Parent};
|
use bevy_hierarchy::{Children, Parent};
|
||||||
|
@ -15,7 +15,6 @@ use bevy_render::camera::{Camera, NormalizedRenderTarget};
|
||||||
use bevy_text::{CosmicBuffer, TextPipeline};
|
use bevy_text::{CosmicBuffer, TextPipeline};
|
||||||
use bevy_transform::components::Transform;
|
use bevy_transform::components::Transform;
|
||||||
use bevy_utils::tracing::warn;
|
use bevy_utils::tracing::warn;
|
||||||
use bevy_utils::{HashMap, HashSet};
|
|
||||||
use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
|
use bevy_window::{PrimaryWindow, Window, WindowScaleFactorChanged};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use ui_surface::UiSurface;
|
use ui_surface::UiSurface;
|
||||||
|
@ -63,6 +62,7 @@ pub enum LayoutError {
|
||||||
TaffyError(#[from] taffy::TaffyError),
|
TaffyError(#[from] taffy::TaffyError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
#[derive(SystemParam)]
|
#[derive(SystemParam)]
|
||||||
pub struct UiLayoutSystemRemovedComponentParam<'w, 's> {
|
pub struct UiLayoutSystemRemovedComponentParam<'w, 's> {
|
||||||
removed_cameras: RemovedComponents<'w, 's, Camera>,
|
removed_cameras: RemovedComponents<'w, 's, Camera>,
|
||||||
|
@ -71,9 +71,25 @@ pub struct UiLayoutSystemRemovedComponentParam<'w, 's> {
|
||||||
removed_nodes: RemovedComponents<'w, 's, Node>,
|
removed_nodes: RemovedComponents<'w, 's, Node>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct UiLayoutSystemBuffers {
|
||||||
|
interned_root_notes: Vec<Vec<Entity>>,
|
||||||
|
resized_windows: EntityHashSet,
|
||||||
|
camera_layout_info: EntityHashMap<CameraLayoutInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CameraLayoutInfo {
|
||||||
|
size: UVec2,
|
||||||
|
resized: bool,
|
||||||
|
scale_factor: f32,
|
||||||
|
root_nodes: Vec<Entity>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates the UI's layout tree, computes the new layout geometry and then updates the sizes and transforms of all the UI nodes.
|
/// Updates the UI's layout tree, computes the new layout geometry and then updates the sizes and transforms of all the UI nodes.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn ui_layout_system(
|
pub fn ui_layout_system(
|
||||||
|
mut buffers: Local<UiLayoutSystemBuffers>,
|
||||||
primary_window: Query<(Entity, &Window), With<PrimaryWindow>>,
|
primary_window: Query<(Entity, &Window), With<PrimaryWindow>>,
|
||||||
cameras: Query<(Entity, &Camera)>,
|
cameras: Query<(Entity, &Camera)>,
|
||||||
default_ui_camera: DefaultUiCamera,
|
default_ui_camera: DefaultUiCamera,
|
||||||
|
@ -98,20 +114,20 @@ pub fn ui_layout_system(
|
||||||
#[cfg(feature = "bevy_text")] mut buffer_query: Query<&mut CosmicBuffer>,
|
#[cfg(feature = "bevy_text")] mut buffer_query: Query<&mut CosmicBuffer>,
|
||||||
#[cfg(feature = "bevy_text")] mut text_pipeline: ResMut<TextPipeline>,
|
#[cfg(feature = "bevy_text")] mut text_pipeline: ResMut<TextPipeline>,
|
||||||
) {
|
) {
|
||||||
struct CameraLayoutInfo {
|
let UiLayoutSystemBuffers {
|
||||||
size: UVec2,
|
interned_root_notes,
|
||||||
resized: bool,
|
resized_windows,
|
||||||
scale_factor: f32,
|
camera_layout_info,
|
||||||
root_nodes: Vec<Entity>,
|
} = &mut *buffers;
|
||||||
}
|
|
||||||
|
|
||||||
let default_camera = default_ui_camera.get();
|
let default_camera = default_ui_camera.get();
|
||||||
let camera_with_default = |target_camera: Option<&TargetCamera>| {
|
let camera_with_default = |target_camera: Option<&TargetCamera>| {
|
||||||
target_camera.map(TargetCamera::entity).or(default_camera)
|
target_camera.map(TargetCamera::entity).or(default_camera)
|
||||||
};
|
};
|
||||||
|
|
||||||
let resized_windows: HashSet<Entity> = resize_events.read().map(|event| event.window).collect();
|
resized_windows.clear();
|
||||||
let calculate_camera_layout_info = |camera: &Camera| {
|
resized_windows.extend(resize_events.read().map(|event| event.window));
|
||||||
|
let mut calculate_camera_layout_info = |camera: &Camera| {
|
||||||
let size = camera.physical_viewport_size().unwrap_or(UVec2::ZERO);
|
let size = camera.physical_viewport_size().unwrap_or(UVec2::ZERO);
|
||||||
let scale_factor = camera.target_scaling_factor().unwrap_or(1.0);
|
let scale_factor = camera.target_scaling_factor().unwrap_or(1.0);
|
||||||
let camera_target = camera
|
let camera_target = camera
|
||||||
|
@ -124,12 +140,12 @@ pub fn ui_layout_system(
|
||||||
size,
|
size,
|
||||||
resized,
|
resized,
|
||||||
scale_factor: scale_factor * ui_scale.0,
|
scale_factor: scale_factor * ui_scale.0,
|
||||||
root_nodes: Vec::new(),
|
root_nodes: interned_root_notes.pop().unwrap_or_default(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Precalculate the layout info for each camera, so we have fast access to it for each node
|
// Precalculate the layout info for each camera, so we have fast access to it for each node
|
||||||
let mut camera_layout_info: HashMap<Entity, CameraLayoutInfo> = HashMap::new();
|
camera_layout_info.clear();
|
||||||
root_node_query.iter().for_each(|(entity,target_camera)|{
|
root_node_query.iter().for_each(|(entity,target_camera)|{
|
||||||
match camera_with_default(target_camera) {
|
match camera_with_default(target_camera) {
|
||||||
Some(camera_entity) => {
|
Some(camera_entity) => {
|
||||||
|
@ -232,11 +248,11 @@ pub fn ui_layout_system(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (camera_id, camera) in &camera_layout_info {
|
for (camera_id, mut camera) in camera_layout_info.drain() {
|
||||||
let inverse_target_scale_factor = camera.scale_factor.recip();
|
let inverse_target_scale_factor = camera.scale_factor.recip();
|
||||||
|
|
||||||
ui_surface.compute_camera_layout(
|
ui_surface.compute_camera_layout(
|
||||||
*camera_id,
|
camera_id,
|
||||||
camera.size,
|
camera.size,
|
||||||
#[cfg(feature = "bevy_text")]
|
#[cfg(feature = "bevy_text")]
|
||||||
text_buffers,
|
text_buffers,
|
||||||
|
@ -255,6 +271,9 @@ pub fn ui_layout_system(
|
||||||
Vec2::ZERO,
|
Vec2::ZERO,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
camera.root_nodes.clear();
|
||||||
|
interned_root_notes.push(camera.root_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_uinode_geometry_recursive(
|
fn update_uinode_geometry_recursive(
|
||||||
|
|
Loading…
Reference in a new issue