diff --git a/crates/bevy_text/src/lib.rs b/crates/bevy_text/src/lib.rs index 4c379e61e5..0b638cdb1d 100644 --- a/crates/bevy_text/src/lib.rs +++ b/crates/bevy_text/src/lib.rs @@ -123,7 +123,8 @@ impl Plugin for TextPlugin { .ambiguous_with(CameraUpdateSystem), remove_dropped_font_atlas_sets, ), - ); + ) + .add_systems(Last, trim_cosmic_cache); if let Some(render_app) = app.get_sub_app_mut(RenderApp) { render_app.add_systems( diff --git a/crates/bevy_text/src/pipeline.rs b/crates/bevy_text/src/pipeline.rs index 7ac4609627..f5fbc64b3a 100644 --- a/crates/bevy_text/src/pipeline.rs +++ b/crates/bevy_text/src/pipeline.rs @@ -1,7 +1,12 @@ use std::sync::Arc; use bevy_asset::{AssetId, Assets}; -use bevy_ecs::{component::Component, entity::Entity, reflect::ReflectComponent, system::Resource}; +use bevy_ecs::{ + component::Component, + entity::Entity, + reflect::ReflectComponent, + system::{ResMut, Resource}, +}; use bevy_math::{UVec2, Vec2}; use bevy_reflect::{std_traits::ReflectDefault, Reflect}; use bevy_render::texture::Image; @@ -407,3 +412,13 @@ fn buffer_dimensions(buffer: &Buffer) -> Vec2 { Vec2::new(width.ceil(), height).ceil() } + +/// Discards stale data cached in `FontSystem`. +pub(crate) fn trim_cosmic_cache(mut pipeline: ResMut) { + // A trim age of 2 was found to reduce frame time variance vs age of 1 when tested with dynamic text. + // See https://github.com/bevyengine/bevy/pull/15037 + // + // We assume only text updated frequently benefits from the shape cache (e.g. animated text, or + // text that is dynamically measured for UI). + pipeline.font_system_mut().shape_run_cache.trim(2); +} diff --git a/examples/ui/text_debug.rs b/examples/ui/text_debug.rs index 0e4fbe1bac..e2f596c352 100644 --- a/examples/ui/text_debug.rs +++ b/examples/ui/text_debug.rs @@ -1,5 +1,7 @@ //! Shows various text layout options. +use std::{collections::VecDeque, time::Duration}; + use bevy::{ color::palettes::css::*, diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin}, @@ -154,7 +156,15 @@ fn infotext_system(mut commands: Commands, asset_server: Res) { builder.spawn(( TextBundle::from_sections([ TextSection::new( - "This text changes in the bottom right", + "", + TextStyle { + font: font.clone(), + font_size: 25.0, + ..default() + }, + ), + TextSection::new( + "\nThis text changes in the bottom right", TextStyle { font: font.clone(), font_size: 25.0, @@ -223,10 +233,23 @@ fn infotext_system(mut commands: Commands, asset_server: Res) { } fn change_text_system( + mut fps_history: Local>, + mut time_history: Local>, time: Res