2

The following program is a very minimalistic example of a large quantity of SpriteComponents. In this example, with an FPS counter, you can see how costly SpriteComponents seem to be.

I did notice that if I reuse the material handle, it does speed things up, but even still, the speed is incredibly slow. Also, I'm not certain how safe it is to reuse a material handle. I noticed in the breakout example, they did not reuse handles.

Still, with no additional systems I am getting around 10 frames per second.

use bevy:: {
    prelude::*,
};

struct Box;
struct Name(String);
#[derive(Default)]
struct FPSCounter(Timer,u32);


const WIDTH: f32 = 640.0;
const HEIGHT: f32 = 480.0;

pub struct drawPlugin;

impl Plugin for drawPlugin {
    fn build(&self, app: &mut AppBuilder) {
        app
            .add_resource(FPSCounter(Timer::from_seconds(1.0,true),0))
            .add_startup_system(setup.system())
            .add_system(fps_counter.system());
    }
}

fn fps_counter(time: Res<Time>, mut timer: ResMut<FPSCounter>) {
    timer.0.tick(time.delta_seconds);
    timer.1 += 1;
    if timer.0.finished {
        println!("One-{}",timer.1);
        timer.1 = 0;
    }
}

fn main() {
    App::build()
        .add_resource(WindowDescriptor {
            title: "Test Prog!".to_string(),
            width: WIDTH as u32,
            height: HEIGHT as u32,
            vsync: true,
            resizable: false,
            ..Default::default()
        })
        .add_default_plugins()
        .add_plugin(drawPlugin)
        .run();
}

fn setup(mut cmds: Commands, mut mats: ResMut<Assets<ColorMaterial>>,asset_server: Res<AssetServer>) {
    const sq_width: f32 = 10.0;
    const sq_height: f32 = 10.0;
    let left = -(WIDTH /2.0) + sq_width / 2.0;
    let right = (WIDTH / 2.0) - sq_width / 2.0;
    let top = (HEIGHT / 2.0) - sq_height / 2.0;
    let bot = -(HEIGHT / 2.0) + sq_height / 2.0;
    let mymat = mats.add(Color::rgb(1.0,0.0,0.0).into());
    cmds
    .spawn(Camera2dComponents::default())
    .spawn(UiCameraComponents::default());
    for box_num2 in 1..=30 {
        for box_num in 1..=30 {
            cmds.spawn(SpriteComponents {
                material: mymat,
                translation: Translation(Vec3::new(left + ((sq_width + 1.0) * box_num as f32),top - ((sq_height + 1.0) * box_num2 as f32),0.0)),
                sprite: Sprite {
                    size: Vec2::new(sq_width,sq_height),
                },
                ..Default::default()
            }).with(Box {}).with(Name("Box1".to_string()));
        }
    }
}
STF_ZBR
  • 617
  • 1
  • 4
  • 19
  • 2
    Did you compile your program in debug mode or in release mode (`--release`)? Note that Cargo builds all dependencies in the same mode as the program (although `std` is precompiled and is always in release mode). – Francis Gagné Aug 26 '20 at 04:14
  • This is definitely a debug problem. In release the FPS is as expected. Perhaps I just can't run in debug even for testing. – STF_ZBR Aug 27 '20 at 04:27
  • Have a look at [Cargo profiles](https://doc.rust-lang.org/cargo/reference/profiles.html). You can enable some optimizations in the debug profile (which has debug info enabled). – Francis Gagné Aug 27 '20 at 04:55
  • 2
    Possibly related: https://github.com/bevyengine/bevy/issues/346 – will-hart Aug 31 '20 at 12:11

1 Answers1

2

There are probably several things here.

  1. Bevy doesn't do any batching in the renderer yet,
  2. Rust debug modes are slow, this is discussed here https://github.com/bevyengine/bevy/issues/346.

Sounds like this is mostly issue two for you. To work around this you can run debug mode with some optimisations set in your cargo.toml. For instance I have

[profile.dev]
opt-level = 3

This makes initial builds a bit slower but after that it doesn't seem to make too much difference to build times. You might find you need to adjust or remove this setting if you want to do more detailed debugging.

will-hart
  • 3,742
  • 2
  • 38
  • 48