Add `WgpuConfiguration::desired_maximum_frame_latency` (#3874)
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 https://github.com/emilk/egui/pull/3714 * See also https://github.com/gfx-rs/wgpu/pull/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.
This commit is contained in:
parent
11c89125f7
commit
4d1a736016
|
|
@ -4219,9 +4219,9 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wgpu"
|
name = "wgpu"
|
||||||
version = "0.19.0"
|
version = "0.19.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d0b71d2ded29e2161db50ab731d6cb42c037bd7ab94864a98fa66ff36b4721a8"
|
checksum = "0bfe9a310dcf2e6b85f00c46059aaeaf4184caa8e29a1ecd4b7a704c3482332d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ glow = "0.13"
|
||||||
puffin = "0.18"
|
puffin = "0.18"
|
||||||
raw-window-handle = "0.6.0"
|
raw-window-handle = "0.6.0"
|
||||||
thiserror = "1.0.37"
|
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:
|
# Make the renderer `Sync` even on wasm32, because it makes the code simpler:
|
||||||
"fragile-send-sync-non-atomic-wasm",
|
"fragile-send-sync-non-atomic-wasm",
|
||||||
] }
|
] }
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,15 @@ pub struct WgpuConfiguration {
|
||||||
/// Present mode used for the primary surface.
|
/// Present mode used for the primary surface.
|
||||||
pub present_mode: wgpu::PresentMode,
|
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.
|
/// Power preference for the adapter.
|
||||||
pub power_preference: wgpu::PowerPreference,
|
pub power_preference: wgpu::PowerPreference,
|
||||||
|
|
||||||
|
|
@ -237,10 +246,22 @@ pub struct WgpuConfiguration {
|
||||||
|
|
||||||
impl std::fmt::Debug for WgpuConfiguration {
|
impl std::fmt::Debug for WgpuConfiguration {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
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")
|
f.debug_struct("WgpuConfiguration")
|
||||||
.field("supported_backends", &self.supported_backends)
|
.field("supported_backends", &supported_backends)
|
||||||
.field("present_mode", &self.present_mode)
|
.field("present_mode", &present_mode)
|
||||||
.field("power_preference", &self.power_preference)
|
.field(
|
||||||
|
"desired_maximum_frame_latency",
|
||||||
|
&desired_maximum_frame_latency,
|
||||||
|
)
|
||||||
|
.field("power_preference", &power_preference)
|
||||||
.finish_non_exhaustive()
|
.finish_non_exhaustive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -274,6 +295,8 @@ impl Default for WgpuConfiguration {
|
||||||
|
|
||||||
present_mode: wgpu::PresentMode::AutoVsync,
|
present_mode: wgpu::PresentMode::AutoVsync,
|
||||||
|
|
||||||
|
desired_maximum_frame_latency: None,
|
||||||
|
|
||||||
power_preference: wgpu::util::power_preference_from_env()
|
power_preference: wgpu::util::power_preference_from_env()
|
||||||
.unwrap_or(wgpu::PowerPreference::HighPerformance),
|
.unwrap_or(wgpu::PowerPreference::HighPerformance),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ impl Painter {
|
||||||
fn configure_surface(
|
fn configure_surface(
|
||||||
surface_state: &SurfaceState,
|
surface_state: &SurfaceState,
|
||||||
render_state: &RenderState,
|
render_state: &RenderState,
|
||||||
present_mode: wgpu::PresentMode,
|
config: &WgpuConfiguration,
|
||||||
) {
|
) {
|
||||||
crate::profile_function!();
|
crate::profile_function!();
|
||||||
|
|
||||||
|
|
@ -155,21 +155,25 @@ impl Painter {
|
||||||
let width = surface_state.width;
|
let width = surface_state.width;
|
||||||
let height = surface_state.height;
|
let height = surface_state.height;
|
||||||
|
|
||||||
surface_state.surface.configure(
|
let mut surf_config = wgpu::SurfaceConfiguration {
|
||||||
&render_state.device,
|
usage,
|
||||||
&wgpu::SurfaceConfiguration {
|
format: render_state.target_format,
|
||||||
// TODO(emilk): expose `desired_maximum_frame_latency` to eframe users
|
present_mode: config.present_mode,
|
||||||
usage,
|
alpha_mode: surface_state.alpha_mode,
|
||||||
format: render_state.target_format,
|
view_formats: vec![render_state.target_format],
|
||||||
present_mode,
|
..surface_state
|
||||||
alpha_mode: surface_state.alpha_mode,
|
.surface
|
||||||
view_formats: vec![render_state.target_format],
|
.get_default_config(&render_state.adapter, width, height)
|
||||||
..surface_state
|
.expect("The surface isn't supported by this adapter")
|
||||||
.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`]
|
/// Updates (or clears) the [`winit::window::Window`] associated with the [`Painter`]
|
||||||
|
|
@ -328,7 +332,7 @@ impl Painter {
|
||||||
surface_state.width = width;
|
surface_state.width = width;
|
||||||
surface_state.height = height;
|
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 {
|
if let Some(depth_format) = self.depth_format {
|
||||||
self.depth_texture_view.insert(
|
self.depth_texture_view.insert(
|
||||||
|
|
@ -525,11 +529,7 @@ impl Painter {
|
||||||
Ok(frame) => frame,
|
Ok(frame) => frame,
|
||||||
Err(err) => match (*self.configuration.on_surface_error)(err) {
|
Err(err) => match (*self.configuration.on_surface_error)(err) {
|
||||||
SurfaceErrorAction::RecreateSurface => {
|
SurfaceErrorAction::RecreateSurface => {
|
||||||
Self::configure_surface(
|
Self::configure_surface(surface_state, render_state, &self.configuration);
|
||||||
surface_state,
|
|
||||||
render_state,
|
|
||||||
self.configuration.present_mode,
|
|
||||||
);
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
SurfaceErrorAction::SkipFrame => {
|
SurfaceErrorAction::SkipFrame => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue