-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
macOS: Memory usage skyrockets when window is occluded #5856
Description
Bevy version
0.8.1
[Optional] Relevant system information
MacBook Pro (16-inch, 2021)
`AdapterInfo { name: "Apple M1 Max", vendor: 0, device: 0, device_type: IntegratedGpu, backend: Metal }`What you did
- Cloned out the repository.
- Checked out the
v0.8.1tag. - Tried the
shader-instancingexample locally on release mode:cargo run --release --example shader_instancing.
What went wrong
When occluding or minimizing the Bevy window, memory usages skyrockets at gigabytes per second until the window is shown again.
Additional information
The memory usage is caused by gfx-rs/wgpu#1783. The following information stems from a long and somewhat redundant investigation on this issue, plus a bunch of other macOS-related issues (discord thread).
It was concluded that this is impractical to solve entirely at the wgpu level, and that there are two primary workarounds for this issue:
-
Detecting window occlusion using
winit'sWindowEvent::Occludedand avoiding any rendering at all when the window is occluded.+ Probably easier to plumb into an existing codebase. / WindowEvent::Occluded was introduced on winit 0.27.0. / Care must be taken to throtte the winit loop (or put it on ControlLoop::Wait) when the window is occluded, (and/or drive the app world through a different means?), since without wgpu surface obtention throttling it at vsync, it would just collapse into a tight loop, causing massive CPU usage. - Only mitigates the memory leak; on optimized builds it will still leak around 100 Mb when un-occluding the window. -
Driving rendering through
CVDisplayLink(macOS) /CADisplayLink(iOS) frame callbacks (both essentially do kind of the same).
Preliminary tests using thedisplay-link 0.2crate on rawwgpuexamples were successful, but more interesting stuff is exposed on the raw APIs themselves (documentation). Apple itself explains how it works in this WWDC 2021 talk.It is noted exploring such integration for Bevy is already being studied as part of macOS and iOS CPU ussage fix #5713.
+ Fixes the memory leak. + If used as a way to drive winit redraw requests, can potentially ensure it keeps looping at target framerate even if the window is in the background. + Automatically handles system conditions (e.g. can throttle the application down automatically when thermals are high) / Likely the Apple recommended way to do it, given I have not seen any official Metal examples that *don't* use it. / Callback comes with nanosecond-precision timestamp(-s), could be used to derive delta timestamps? / Can be configured to target a specified framerate as long as it's divisible by vsync. - Essentially forces Vsync. - Likely very annoying to plumb on an existing codebase?