Conversation
I wanted to remove vsync since it has little to do with the example.
|
Welcome, new contributor! Please make sure you've read our contributing guide, as well as our policy regarding AI usage, and we look forward to reviewing your pull request shortly ✨ |
| fn main() { | ||
| App::new() | ||
| .insert_resource(FrameLimiterSettings::default()) | ||
| .insert_resource(WinitSettings::game_with_max_fps(DEFAULT_FPS as f64)) |
There was a problem hiding this comment.
I really don't like defaulting to 60 fps locked. Winit exposes the monitor refresh rate which should always be used when it's available.
There was a problem hiding this comment.
Additionally, winit only provides monitor Hz to the nearest integer. If you don't round your fps up, you'll end up accumulating frames and latency, which defeats the point of pacing.
There was a problem hiding this comment.
IceSentry
left a comment
There was a problem hiding this comment.
Frame pacing is already done in browsers so this should not be enabled when compiled for wasm
There was a problem hiding this comment.
Frame limiting should probably not be tied to winit, and be based around the render/vblank timing so we can do proper frame pacing, not just limit the event loop poll.
Here's some prior art that's existed since 0.6: https://github.com/aevyrie/bevy_framepace
See also: https://www.activision.com/cdn/research/Hogge_Akimitsu_Controller_to_display.pdf
It's possible that limiting at the event loop poll could give us better results, but from what I can tell the speed of the polling is a black box, and I don't know if we can rely on it for stable timings. Another consideration is power use. One of the motivating factors for bevy_framepace, and framelimiting in general is reducing power use for non game apps. This PR doesn't address this in two ways:
- There is no testing to show this is as efficient as, say
spin_sleep - This is coupled to update modes, for app use at work we usually use reactive rendering with framelimiting/pacing. Frame limiting should be orthogonal to the event loop mode, not baked into it. These two things combined are the only way I've found to get bevy's power use down to the low single digits.
|
I would really love work here, but I think the correct strategy is to upstream bevy_mod_framepace, possibly with improvements. |
Objective
Allow developers to limit an application's frame rate when using bevy_winit.
This closes #1343.
Fixes the inability to limit the framerate of the game.
Solution
This PR adds a new windowed update mode for bevy_winit:
It also adds convenience constructors:
The new mode behaves like a continuous game loop, but instead of running as fast as possible, it advances on a scheduled timeout cadence. Unlike Reactive, it does not wake early for user, window, or device events. Those events are batched and handled on the next scheduled update.
Note:
One thing to note when I was looking into this PR, I noticed several reworks made for winit runner based on this PR#9304. Mine utilizes this older version of the system. I could take a crack at reviving that PR and modernizing it.
Testing
Yes, I did.
Manual testing:
PR Reviewers can test with:
I added
--releasebecause it helps reduce performance issues when limiting the frame rate, particularly with 240fps. I am slightly concerned that my method could be somehow making the game update slower, hence the framerate issue. The only thing I can think of is the timers limiting the frame pacing. Which is why I have a cap of 180fps while running the demo in debug, but that's not the case in release.Showcase
Click to view showcase
This PR adds a new public API for capped continuous updates:For more direct control: