From bbf1c23d500a1cf13419faef86d8123033ad2660 Mon Sep 17 00:00:00 2001 From: Cameron <51241057+maniwani@users.noreply.github.com> Date: Wed, 2 Aug 2023 16:41:23 -0700 Subject: [PATCH] Change `WinitPlugin` defaults to limit game update rate when window is not visible (#7611) Fixes #5856. Fixes #8080. Fixes #9040. # Objective We need to limit the update rate of games whose windows are not visible (minimized or completely occluded). Compositors typically ignore the VSync settings of windows that aren't visible. That, combined with the lack of rendering work, results in a scenario where an app becomes completely CPU-bound and starts updating without limit. There are currently three update modes. - `Continuous` updates an app as often as possible. - `Reactive` updates when new window or device events have appeared, a timer expires, or a redraw is requested. - `ReactiveLowPower` is the same as `Reactive` except it ignores device events (e.g. general mouse movement). The problem is that the default "game" settings are set to `Contiuous` even when no windows are visible. ### More Context - https://github.com/libsdl-org/SDL/issues/1871 - https://github.com/glfw/glfw/issues/680 - https://github.com/godotengine/godot/issues/19741 - https://github.com/godotengine/godot/issues/64708 ## Solution Change the default "unfocused" `UpdateMode` for games to `ReactiveLowPower` just like desktop apps. This way, even when the window is occluded, the app still updates at a sensible rate or if something about the window changes. I chose 20Hz arbitrarily. --- crates/bevy_winit/src/winit_config.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/bevy_winit/src/winit_config.rs b/crates/bevy_winit/src/winit_config.rs index c71a928140627..89f67707a0dae 100644 --- a/crates/bevy_winit/src/winit_config.rs +++ b/crates/bevy_winit/src/winit_config.rs @@ -38,8 +38,17 @@ pub struct WinitSettings { impl WinitSettings { /// Default settings for games. + /// + /// [`Continuous`](UpdateMode::Continuous) if windows have focus, + /// [`ReactiveLowPower`](UpdateMode::ReactiveLowPower) otherwise. pub fn game() -> Self { - WinitSettings::default() + WinitSettings { + focused_mode: UpdateMode::Continuous, + unfocused_mode: UpdateMode::ReactiveLowPower { + wait: Duration::from_secs_f64(1.0 / 60.0), // 60Hz + }, + ..Default::default() + } } /// Default settings for desktop applications.