mirror of
https://github.com/emilk/egui.git
synced 2026-06-26 22:53:14 -04:00
## Summary
This fixes macOS live-resize behavior for the `eframe`/`egui-wgpu` path
when using the low-latency wgpu surface configuration.
The problem I was seeing is that native window resize can look visibly
below the baseline expected from a desktop GUI: stale or stretched
frames (manifesting as wobble/jitter), or severe lag while dragging a
window edge.
The fix has three parts:
- use `CAMetalLayer.presentsWithTransaction` during live resize to avoid
stale/stretched frames
- temporarily use at least `desired_maximum_frame_latency = 2` while
live resize is active, so transaction presentation does not stall when
the app normally uses `SurfaceConfig::LOW_LATENCY`
- treat macOS `WindowEvent::Moved` as part of the live-resize event
stream, since resizing from the top or left edge changes the window
origin
This PR depends on the winit-side AppKit live-resize timing fix in
[rust-windowing/winit#4588](https://github.com/rust-windowing/winit/pull/4588)
A renderer-only frame-latency change is not enough by itself. The
temporary latency bump only solves the drawable starvation caused by
combining `presentsWithTransaction` with `SurfaceConfig::LOW_LATENCY`.
It does not change when winit emits resize/redraw events, whether
redraws are delivered during AppKit's live-resize event-tracking loop,
or whether the surface size is derived from the current backing rect.
That is why the winit fix is needed first: it makes the windowing layer
report the current AppKit backing size and request redraws from the
live-resize/display callbacks. egui-wgpu still needs this PR on top
because winit does not own the wgpu `Surface` or the underlying
`CAMetalLayer` presentation policy.
In other words: winit fixes when the windowing layer reports
resize/redraw work, while this PR fixes how egui-wgpu presents
Metal-backed wgpu frames during that resize.
## Why change the existing feature?
The existing `macos-window-resize-jitter-fix` feature addresses one
symptom by enabling transaction presentation during resize, but it is
not enough for the low-latency wgpu path.
In particular, `presentsWithTransaction` and
`SurfaceConfig::LOW_LATENCY` interact poorly during AppKit live resize.
The old code avoids that by [skipping transaction presentation when
latency is
`1`](71c4ff3c33/crates/egui-wgpu/src/winit.rs (L417)),
but that means low-latency users get the resize jitter/wobble back.
This PR keeps the low-latency path normally, but temporarily bumps frame
latency only while live resize is active. That gives the resize path
enough drawable slack without changing normal interaction latency.
I removed the `macos-window-resize-jitter-fix` feature because this
seems like the behavior the macOS wgpu path should have by default, not
a separate opt-in. If keeping the feature as a no-op compatibility alias
is preferred, I can adjust the PR.
## Validation
I created a small demo app that somewhat resembles the layout of my
actual app and highlights both horizontal and vertical resize jitter:
- a borderless macOS window
- a simple toolbar
- a scrolling side list
- `SurfaceConfig::LOW_LATENCY`
The toolbar and list make stale or stretched frames easy to see during
native resize. The jitter is visible even on the traffic light buttons.
Recordings:
### Before 1: no transaction presentation, low latency
Shows jitter/wobble and stale/stretched frames during live resize.
https://github.com/user-attachments/assets/2cf4467b-e14c-4f41-8021-0b8c23f41004
### Before 2: transaction presentation with low latency
Shows the other failure mode: live resize can become severely laggy when
transaction presentation is used while keeping
`SurfaceConfig::LOW_LATENCY`.
https://github.com/user-attachments/assets/2f866790-f472-4ede-a3c0-480e8f0f041a
### After: patched egui-wgpu + patched winit, low latency
No visible wobble/jitter and no severe live-resize lag.
https://github.com/user-attachments/assets/59e46e9f-7906-4b5c-a6c7-1d09eae644cd
---------
Co-authored-by: lucasmerlin <hi@lucasmerlin.me>
76 lines
2.7 KiB
TOML
76 lines
2.7 KiB
TOML
[package]
|
|
name = "egui-wgpu"
|
|
version.workspace = true
|
|
description = "Bindings for using egui natively using the wgpu library"
|
|
authors = [
|
|
"Nils Hasenbanck <nils@hasenbanck.de>",
|
|
"embotech <opensource@embotech.com>",
|
|
"Emil Ernerfeldt <emil.ernerfeldt@gmail.com>",
|
|
]
|
|
edition.workspace = true
|
|
rust-version.workspace = true
|
|
homepage = "https://github.com/emilk/egui/tree/main/crates/egui-wgpu"
|
|
license.workspace = true
|
|
readme = "README.md"
|
|
repository = "https://github.com/emilk/egui/tree/main/crates/egui-wgpu"
|
|
categories = ["gui", "game-development"]
|
|
keywords = ["wgpu", "egui", "gui", "gamedev"]
|
|
include = ["../../LICENSE-APACHE", "../../LICENSE-MIT", "**/*.rs", "**/*.wgsl", "Cargo.toml"]
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[package.metadata.docs.rs]
|
|
all-features = true
|
|
rustdoc-args = ["--generate-link-to-definition"]
|
|
|
|
[features]
|
|
default = [
|
|
"fragile-send-sync-non-atomic-wasm",
|
|
"macos-window-resize-jitter-fix",
|
|
"wgpu/default",
|
|
"wgpu/webgl", # A very important fallback for web support
|
|
]
|
|
|
|
## Enables the `capture` module for capturing screenshots.
|
|
capture = ["dep:egui"]
|
|
|
|
## Enable [`winit`](https://docs.rs/winit) integration. On Linux, requires either `wayland` or `x11`
|
|
winit = ["dep:winit", "winit/rwh_06", "dep:egui", "capture"]
|
|
|
|
## Enables Wayland support for winit.
|
|
wayland = ["winit?/wayland"]
|
|
|
|
## Enables x11 support for winit.
|
|
x11 = ["winit?/x11"]
|
|
|
|
## Make the renderer `Sync` on wasm, exploiting that by default wasm isn't multithreaded.
|
|
## It may make code easier, especially when targeting both native and web.
|
|
## On native most wgpu objects are send and sync, on the web they are not (by nature of the WebGPU specification).
|
|
## This is not supported in [multithreaded WASM](https://gpuweb.github.io/gpuweb/explainer/#multithreading-transfer).
|
|
## Thus that usage is guarded against with compiler errors in wgpu.
|
|
fragile-send-sync-non-atomic-wasm = ["wgpu/fragile-send-sync-non-atomic-wasm"]
|
|
|
|
## Enables the macOS live-resize jitter fix, which uses `present_with_transaction`.
|
|
## This requires the `wgpu/metal` backend. Disable this feature if you want to use egui-wgpu
|
|
## with a different backend (e.g. Vulkan or GL) on macOS without pulling in Metal.
|
|
macos-window-resize-jitter-fix = ["wgpu/metal"]
|
|
|
|
[dependencies]
|
|
epaint = { workspace = true, default-features = false, features = ["bytemuck"] }
|
|
|
|
ahash.workspace = true
|
|
bytemuck.workspace = true
|
|
document-features.workspace = true
|
|
log.workspace = true
|
|
profiling.workspace = true
|
|
thiserror.workspace = true
|
|
type-map.workspace = true
|
|
web-time.workspace = true
|
|
wgpu = { workspace = true, features = ["wgsl"] }
|
|
|
|
# Optional dependencies:
|
|
|
|
egui = { workspace = true, optional = true, default-features = false }
|
|
winit = { workspace = true, optional = true, default-features = false }
|