rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.86k stars 909 forks source link

ControlFlow::WaitUntil race on Firefox #3528

Closed thebluefish closed 8 months ago

thebluefish commented 8 months ago

Original issue


Here is an example project based on bevy. I am too unfamiliar with using winit directly to boil it down without bevy.

Run the example with trunk serve and browse to it.

The game should start out focused and run at roughly vsync, control flow is set to Poll.

Unfocus the game element, and the console will start spamming with errors like

Uncaught Error: closure invoked recursively or after being dropped wbindgen_throw https://bevy-webgl2-examples.pages.dev/Games/breakout/wasm_example.js:2035 wbg_adapter_51 https://bevy-webgl2-examples.pages.dev/Games/breakout/wasm_example.js:237 real https://bevy-webgl2-examples.pages.dev/Games/breakout/wasm_example.js:210

Notably the game should run at half vsync while unfocused, and control flow is set to WaitUntil.

Focus the game element again, and the FPS should drop significantly while under Poll.


From placing logging points around bevy and winit, the problem appears to start when winit::platform_impl::platform::event_loop::runner::apply_control_flow processes a ControlFlow::WaitUntil(_) where the calculated delay is zero. Notably not all logs with a delay of 0 appear to cause this, but I am unable to find another factor.

This issue can be patched by introducing a minimum 1ms delay:

let delay = if end <= start {
    Duration::from_millis(1)
} else {
    end - start
};

This is not a proper solution, since adding an unnecessary random delay is generally unacceptable.


While investigating this, I noticed that any attempts to handle WaitUntil like Poll have produced the same FPS drop on bevy-side while eliminating the console error spam. This leads me to suspect that part of the issue may lie in bevy, but I have been unsuccessful poking around bevy_winit's runner.

daxpedda commented 8 months ago

From a quick look at it and running it locally I'm unsure how to help here. Happy to consult Bevy on Web/wasm-bindgen/Winit issues, but I can't help debug it as I'm not familiar with Bevy's codebase.

I can look more into it if this can be reproduced with Winit. Please let me know if I can help any other way!

daxpedda commented 8 months ago

I figured it out in https://github.com/rust-windowing/winit/pull/3553.