From 5987c0e243f329951d89a08a5ffd494b0846be25 Mon Sep 17 00:00:00 2001 From: Nicola Papale Date: Fri, 8 Jul 2022 20:09:32 +0200 Subject: [PATCH 1/2] Add stress test for many ui elements --- Cargo.toml | 10 +++ examples/stress_tests/many_buttons.rs | 109 ++++++++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 examples/stress_tests/many_buttons.rs diff --git a/Cargo.toml b/Cargo.toml index ba1947661a078..a2a953e7c56e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1254,6 +1254,16 @@ description = "Displays many animated sprites in a grid arrangement with slight category = "Stress Tests" wasm = true +[[example]] +name = "many_buttons" +path = "examples/stress_tests/many_buttons.rs" + +[package.metadata.example.many_buttons] +name = "Many Buttons" +description = "Test rendering of many UI elements" +category = "Stress Tests" +wasm = true + [[example]] name = "many_cubes" path = "examples/stress_tests/many_cubes.rs" diff --git a/examples/stress_tests/many_buttons.rs b/examples/stress_tests/many_buttons.rs new file mode 100644 index 0000000000000..a270abc7b72b2 --- /dev/null +++ b/examples/stress_tests/many_buttons.rs @@ -0,0 +1,109 @@ +use bevy::{ + diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, + prelude::*, + window::PresentMode, +}; + +// For a total of 110 * 110 = 12100 buttons with text +const ROW_COLUMN_COUNT: usize = 110; +const FONT_SIZE: f32 = 7.0; + +/// This example shows what happens when there is a lot of buttons on screen. +fn main() { + App::new() + .insert_resource(WindowDescriptor { + present_mode: PresentMode::Immediate, + ..default() + }) + .add_plugins(DefaultPlugins) + .add_plugin(FrameTimeDiagnosticsPlugin::default()) + .add_plugin(LogDiagnosticsPlugin::default()) + .init_resource::() + .add_startup_system(setup) + .add_system(button_system) + .run(); +} + +#[derive(Component)] +struct IdleColor(UiColor); + +fn button_system( + mut interaction_query: Query<(&Interaction, &mut UiColor, &IdleColor), Changed>, +) { + for (interaction, mut material, IdleColor(idle_color)) in interaction_query.iter_mut() { + if matches!(interaction, Interaction::Hovered) { + *material = Color::ORANGE_RED.into(); + } else { + *material = *idle_color; + } + } +} + +struct UiFont(Handle); +impl FromWorld for UiFont { + fn from_world(world: &mut World) -> Self { + let asset_server = world.get_resource::().unwrap(); + UiFont(asset_server.load("fonts/FiraSans-Bold.ttf")) + } +} + +fn setup(mut commands: Commands, font: Res) { + let count = ROW_COLUMN_COUNT; + let count_f = count as f32; + let as_rainbow = |i: usize| Color::hsl((i as f32 / count_f) * 360.0, 0.9, 0.8); + commands.spawn_bundle(Camera2dBundle::default()); + commands + .spawn_bundle(NodeBundle { + style: Style { + size: Size::new(Val::Percent(100.0), Val::Percent(100.0)), + ..default() + }, + ..default() + }) + .with_children(|commands| { + for i in 0..count { + for j in 0..count { + let color = as_rainbow(j % i.max(1)).into(); + spawn_button(commands, font.0.clone_weak(), color, count_f, i, j); + } + } + }); +} +fn spawn_button( + commands: &mut ChildBuilder, + font: Handle, + color: UiColor, + total: f32, + i: usize, + j: usize, +) { + let width = 90.0 / total; + commands + .spawn_bundle(ButtonBundle { + style: Style { + size: Size::new(Val::Percent(width), Val::Percent(width)), + + position: UiRect { + bottom: Val::Percent(100.0 / total * i as f32), + left: Val::Percent(100.0 / total * j as f32), + ..default() + }, + align_items: AlignItems::Center, + position_type: PositionType::Absolute, + ..default() + }, + color, + ..default() + }) + .with_children(|commands| { + commands.spawn_bundle(TextBundle::from_section( + format!("{i}, {j}"), + TextStyle { + font, + font_size: FONT_SIZE, + color: Color::rgb(0.2, 0.2, 0.2), + }, + )); + }) + .insert(IdleColor(color)); +} From bab1ff1ff48add8a80aa70346441d644e6579eb7 Mon Sep 17 00:00:00 2001 From: Nicola Papale Date: Fri, 8 Jul 2022 20:44:13 +0200 Subject: [PATCH 2/2] update examples README --- examples/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/README.md b/examples/README.md index 6fa1f9acda669..504928ed68e32 100644 --- a/examples/README.md +++ b/examples/README.md @@ -279,6 +279,7 @@ Example | Description --- | --- [Bevymark](../examples/stress_tests/bevymark.rs) | A heavy sprite rendering workload to benchmark your system with Bevy [Many Animated Sprites](../examples/stress_tests/many_animated_sprites.rs) | Displays many animated sprites in a grid arrangement with slight offsets to their animation timers. Used for performance testing. +[Many Buttons](../examples/stress_tests/many_buttons.rs) | Test rendering of many UI elements [Many Cubes](../examples/stress_tests/many_cubes.rs) | Simple benchmark to test per-entity draw overhead. Run with the `sphere` argument to test frustum culling [Many Foxes](../examples/stress_tests/many_foxes.rs) | Loads an animated fox model and spawns lots of them. Good for testing skinned mesh performance. Takes an unsigned integer argument for the number of foxes to spawn. Defaults to 1000 [Many Lights](../examples/stress_tests/many_lights.rs) | Simple benchmark to test rendering many point lights. Run with `WGPU_SETTINGS_PRIO=webgl2` to restrict to uniform buffers and max 256 lights