Skip to content

Commit

Permalink
Add WgpuConfiguration::desired_maximum_frame_latency (#3874)
Browse files Browse the repository at this point in the history
Setting `desired_maximum_frame_latency` to a low value should
theoretically lead to lower latency in winit apps using `egui-wgpu`
(e.g. in `eframe` with `wgpu` backend).

* Replaces #3714
* See also gfx-rs/wgpu#4899

----

It seems like `desired_maximum_frame_latency` has no effect on my Mac. I
lowered my monitor refresh-rate to 30Hz to test, and can see no
difference between `desired_maximum_frame_latency` of `0` or `3`.

Before when experimenting with changing the global `DESIRED_NUM_FRAMES`
in `wgpu` I saw a huge difference, so I wonder what has changed.

I verified that `set_maximum_drawable_count` is being called with either
`1` or `2`, but I perceive no difference between the two.
  • Loading branch information
emilk authored Jan 24, 2024
1 parent 11c8912 commit 4d1a736
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 28 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ glow = "0.13"
puffin = "0.18"
raw-window-handle = "0.6.0"
thiserror = "1.0.37"
wgpu = { version = "0.19", features = [
wgpu = { version = "0.19.1", features = [
# Make the renderer `Sync` even on wasm32, because it makes the code simpler:
"fragile-send-sync-non-atomic-wasm",
] }
Expand Down
29 changes: 26 additions & 3 deletions crates/egui-wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ pub struct WgpuConfiguration {
/// Present mode used for the primary surface.
pub present_mode: wgpu::PresentMode,

/// Desired maximum number of frames that the presentation engine should queue in advance.
///
/// Use `1` for low-latency, and `2` for high-throughput.
///
/// See [`wgpu::SurfaceConfiguration::desired_maximum_frame_latency`] for details.
///
/// `None` = `wgpu` default.
pub desired_maximum_frame_latency: Option<u32>,

/// Power preference for the adapter.
pub power_preference: wgpu::PowerPreference,

Expand All @@ -237,10 +246,22 @@ pub struct WgpuConfiguration {

impl std::fmt::Debug for WgpuConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
supported_backends,
device_descriptor: _,
present_mode,
desired_maximum_frame_latency,
power_preference,
on_surface_error: _,
} = self;
f.debug_struct("WgpuConfiguration")
.field("supported_backends", &self.supported_backends)
.field("present_mode", &self.present_mode)
.field("power_preference", &self.power_preference)
.field("supported_backends", &supported_backends)
.field("present_mode", &present_mode)
.field(
"desired_maximum_frame_latency",
&desired_maximum_frame_latency,
)
.field("power_preference", &power_preference)
.finish_non_exhaustive()
}
}
Expand Down Expand Up @@ -274,6 +295,8 @@ impl Default for WgpuConfiguration {

present_mode: wgpu::PresentMode::AutoVsync,

desired_maximum_frame_latency: None,

power_preference: wgpu::util::power_preference_from_env()
.unwrap_or(wgpu::PowerPreference::HighPerformance),

Expand Down
44 changes: 22 additions & 22 deletions crates/egui-wgpu/src/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl Painter {
fn configure_surface(
surface_state: &SurfaceState,
render_state: &RenderState,
present_mode: wgpu::PresentMode,
config: &WgpuConfiguration,
) {
crate::profile_function!();

Expand All @@ -155,21 +155,25 @@ impl Painter {
let width = surface_state.width;
let height = surface_state.height;

surface_state.surface.configure(
&render_state.device,
&wgpu::SurfaceConfiguration {
// TODO(emilk): expose `desired_maximum_frame_latency` to eframe users
usage,
format: render_state.target_format,
present_mode,
alpha_mode: surface_state.alpha_mode,
view_formats: vec![render_state.target_format],
..surface_state
.surface
.get_default_config(&render_state.adapter, width, height)
.expect("The surface isn't supported by this adapter")
},
);
let mut surf_config = wgpu::SurfaceConfiguration {
usage,
format: render_state.target_format,
present_mode: config.present_mode,
alpha_mode: surface_state.alpha_mode,
view_formats: vec![render_state.target_format],
..surface_state
.surface
.get_default_config(&render_state.adapter, width, height)
.expect("The surface isn't supported by this adapter")
};

if let Some(desired_maximum_frame_latency) = config.desired_maximum_frame_latency {
surf_config.desired_maximum_frame_latency = desired_maximum_frame_latency;
}

surface_state
.surface
.configure(&render_state.device, &surf_config);
}

/// Updates (or clears) the [`winit::window::Window`] associated with the [`Painter`]
Expand Down Expand Up @@ -328,7 +332,7 @@ impl Painter {
surface_state.width = width;
surface_state.height = height;

Self::configure_surface(surface_state, render_state, self.configuration.present_mode);
Self::configure_surface(surface_state, render_state, &self.configuration);

if let Some(depth_format) = self.depth_format {
self.depth_texture_view.insert(
Expand Down Expand Up @@ -525,11 +529,7 @@ impl Painter {
Ok(frame) => frame,
Err(err) => match (*self.configuration.on_surface_error)(err) {
SurfaceErrorAction::RecreateSurface => {
Self::configure_surface(
surface_state,
render_state,
self.configuration.present_mode,
);
Self::configure_surface(surface_state, render_state, &self.configuration);
return None;
}
SurfaceErrorAction::SkipFrame => {
Expand Down

0 comments on commit 4d1a736

Please sign in to comment.