text_pipeline/
text_pipeline.rs

1//! Text pipeline benchmark.
2//!
3//! Continuously recomputes a large block of text with 100 text spans.
4
5use bevy::{
6    color::palettes::basic::{BLUE, YELLOW},
7    diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
8    prelude::*,
9    text::{LineBreak, TextBounds},
10    window::{PresentMode, WindowResolution},
11    winit::WinitSettings,
12};
13
14fn main() {
15    App::new()
16        .add_plugins((
17            DefaultPlugins.set(WindowPlugin {
18                primary_window: Some(Window {
19                    present_mode: PresentMode::AutoNoVsync,
20                    resolution: WindowResolution::new(1920, 1080).with_scale_factor_override(1.0),
21                    ..default()
22                }),
23                ..default()
24            }),
25            FrameTimeDiagnosticsPlugin::default(),
26            LogDiagnosticsPlugin::default(),
27        ))
28        .insert_resource(WinitSettings::continuous())
29        .add_systems(Startup, spawn)
30        .add_systems(Update, update_text_bounds)
31        .run();
32}
33
34fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {
35    warn!(include_str!("warning_string.txt"));
36
37    commands.spawn(Camera2d);
38
39    let make_spans = |i| {
40        [
41            (
42                TextSpan("text".repeat(i)),
43                TextFont {
44                    font: asset_server.load("fonts/FiraMono-Medium.ttf"),
45                    font_size: (4 + i % 10) as f32,
46                    ..Default::default()
47                },
48                TextColor(BLUE.into()),
49            ),
50            (
51                TextSpan("pipeline".repeat(i)),
52                TextFont {
53                    font: asset_server.load("fonts/FiraSans-Bold.ttf"),
54                    font_size: (4 + i % 11) as f32,
55                    ..default()
56                },
57                TextColor(YELLOW.into()),
58            ),
59        ]
60    };
61
62    let spans = (1..50).flat_map(|i| make_spans(i).into_iter());
63
64    commands
65        .spawn((
66            Text2d::default(),
67            TextLayout {
68                justify: Justify::Center,
69                linebreak: LineBreak::AnyCharacter,
70            },
71            TextBounds::default(),
72        ))
73        .with_children(|p| {
74            for span in spans {
75                p.spawn(span);
76            }
77        });
78}
79
80// changing the bounds of the text will cause a recomputation
81fn update_text_bounds(time: Res<Time>, mut text_bounds_query: Query<&mut TextBounds>) {
82    let width = (1. + ops::sin(time.elapsed_secs())) * 600.0;
83    for mut text_bounds in text_bounds_query.iter_mut() {
84        text_bounds.width = Some(width);
85    }
86}