bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Skip the UV calculations for untextured UI nodes

Open ickshonpe opened this issue 2 years ago • 3 comments
trafficstars

Objective

The UV calculations in prepare_uinodes can be skipped for nodes without images.

Solution

Skip the UV calculations if the image handle id is equal to DEFAULT_IMAGE_HANDLE.id().


ickshonpe avatar Feb 24 '23 15:02 ickshonpe

Could you check perfs with example many_buttons? They are very slightly worse (by ~0.15ms) on my laptop with this PR. This example has no images at all, so it would be supposedly worse with many textures nodes.

mockersf avatar Feb 24 '23 20:02 mockersf

many_buttons draws lots of text, and each glyph is an image. Text is a special case and I've got a separate idea on how to improve performance there, once I've finished with the text wrapping PR.

Try comparing with this example instead:

use bevy::{
    diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
    prelude::*,
    window::{PresentMode, WindowPlugin},
};

fn main() {
    App::new()
        .add_plugins(DefaultPlugins.set(WindowPlugin {
            primary_window: Some(Window {
                present_mode: PresentMode::Immediate,
                ..default()
            }),
            ..default()
        }))
        .add_plugin(FrameTimeDiagnosticsPlugin::default())
        .add_plugin(LogDiagnosticsPlugin::default())
        .add_startup_system(setup)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera2dBundle::default());
    let parent = commands.spawn(NodeBundle {
        style: Style {
            flex_basis: Val::Percent(100.),
            flex_wrap: FlexWrap::Wrap,
            align_content: AlignContent::FlexStart,
            align_items: AlignItems::FlexStart,
            justify_content: JustifyContent::FlexStart,
            ..Default::default()
        },
        background_color: BackgroundColor(Color::BLACK),
        ..Default::default()
    })
    .id();
    
    for _ in 0..100_000 {
        let child = commands.spawn(NodeBundle {
            style: Style {
                size: Size::all(Val::Px(2.0)),
                align_self: AlignSelf::FlexStart,
                ..Default::default()
            },
            background_color: BackgroundColor(Color::YELLOW),
            ..Default::default()
        })
        .id();    
        commands.entity(parent).add_child(child);
    }
}

ickshonpe avatar Feb 24 '23 22:02 ickshonpe

Right, forgot that this example has text as it's too small to read 😄

Removing the text, this PR improves perfs by a similar amount 👍

mockersf avatar Feb 25 '23 03:02 mockersf

Adding to 0.10.1 as this is useful to anyone using UI and is non-breaking.

james7132 avatar Mar 17 '23 09:03 james7132

Some benches:

cargo run --example many_buttons --features trace_tracey --profile stress-test
many_buttons_prepare_default

A slight performance regression but many_buttons with text is about the worst possible case here.

cargo run --example many_buttons --no-default-features --features bevy_ui,bevy_sprite,bevy_render,bevy_core_pipeline,bevy_asset,bevy_winit,trace_tracy --profile stress-test
many_buttons_no_text The second is `many_buttons` with text disabled. I don't know what the reason is for the two peaks.

Got the #[cfg(not(feature = "bevy_text"))] many_buttons on a separate branch I'm going to PR in a moment.

ickshonpe avatar Mar 17 '23 10:03 ickshonpe