bevy
bevy copied to clipboard
Bevy 0.10 regression: very long startup if `WinitSettings.unfocused_mode` is set to `UpdateMode::Reactive`
Bevy version
The release number or commit hash of the version you're using.
0.10/0.11/0.12
Relevant system information
Arch Linux
What you did
Running https://github.com/JayceFayne/bevy_regression Pasting main.rs below:
use bevy::prelude::*;
use bevy::winit::WinitSettings;
fn main() {
App::new()
.insert_resource(WinitSettings::desktop_app())
.add_plugins(DefaultPlugins.build())
.run();
}
What went wrong
Takes very long to start on bevy 0.10/0.11/0.12
Additional information
Downgrading to 0.9 fixes the issue
Could you give us a before / after tracing flamegraph? This might be due to the more involved system graph processing.
If that's the case, there are a number of things we can do to improve performance there, ranging from simple optimizations to caching the graph on disk.
See https://github.com/bevyengine/bevy/blob/main/docs/profiling.md for more info.
Alternatively, given your reproduction this could just be a bug with how we / winit is handling that specific mode.
Could you give us a before / after tracing flamegraph? This might be due to the more involved system graph processing.
If that's the case, there are a number of things we can do to improve performance there, ranging from simple optimizations to caching the graph on disk.
See https://github.com/bevyengine/bevy/blob/main/docs/profiling.md for more info.
Sure, I have traces for 0.9 and 0.10 in chrome tracing format, ~~I'll attach them here.~~ Since github does not allow me to upload json files I'll upload the rendered flamegraph.
My guess is that the 60 sec wait in 0.10 is because max_wait
is set to 60 secs in unfocused mode for the desktop_app
preset.
FYI in the future you can bypass that limitation by using .zip files :) And agreed: that looks squarely like a windowing bug: let's see if we can't get this fixed for 0.10.1...
I've had a look at this and there are two parts that cause this behavior:
- Wayland initializes the window with an unfocused state and only displays and focuses the window after a frame is submitted.
- Pipelined rendering, which can cause
app.update()
to finish before the frame is submitted.
Tasks like running the prepare_windows
system are spawned by a render thread to run on the main thread. If app.update()
is already finished, those tasks have to wait until app.update()
is called again.
With DefaultPlugins.build().disable::<PipelinedRenderingPlugin>()
this issue does not appear, since the frame is submitted during the first app.update()
. Winit sends a WindowEvent::Focused(false)
event after creating the window, therefore the app is always updated at startup.
I think the most clean solution (from a task-stall-prevention perspective) would be to wake the main thread (by sending a user event through the winit event proxy) when a main-thread task is spawned by a render-thread, but this would require a lot of changes in a lot of unrelated places and probably hurt performance.
A more pragmatic solution could be to consider a Wayland window focused at creation (ignoring the WindowEvent::Focused(false)
event unless we already received a WindowEvent::Focused(true)
event for the same window). I can submit a PR for that if such a solution is acceptable.
Just checking in after seeing Mastodon post: https://fosstodon.org/@[email protected]/111811705662087955
I can reproduce this issue on Wayland (Fedora 39, Sway WM) still, so I guess it is still a valid issue.