Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions crates/lambda-rs-platform/src/wgpu/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,11 +318,23 @@ fn select_present_mode(
return requested;
}

// Note on ordering:
// - When callers request non-vsync (Immediate/AutoNoVsync), prefer true
// non-vsync modes (Immediate, AutoNoVsync) over low-latency vsync modes
// (Mailbox). Mailbox still synchronizes presentation to refresh and can
// appear "vsync-like" to users who disable vsync expecting uncapped loops.
let candidates: &[wgpu::PresentMode] = match requested {
wgpu::PresentMode::Immediate | wgpu::PresentMode::AutoNoVsync => &[
wgpu::PresentMode::Immediate => &[
wgpu::PresentMode::Immediate,
wgpu::PresentMode::AutoNoVsync,
wgpu::PresentMode::Mailbox,
wgpu::PresentMode::Fifo,
wgpu::PresentMode::AutoVsync,
],
wgpu::PresentMode::AutoNoVsync => &[
wgpu::PresentMode::AutoNoVsync,
wgpu::PresentMode::Immediate,
wgpu::PresentMode::Mailbox,
wgpu::PresentMode::Fifo,
wgpu::PresentMode::AutoVsync,
],
Expand All @@ -336,7 +348,15 @@ fn select_present_mode(
wgpu::PresentMode::Fifo,
wgpu::PresentMode::AutoVsync,
],
wgpu::PresentMode::Fifo | wgpu::PresentMode::AutoVsync => &[
wgpu::PresentMode::AutoVsync => &[
wgpu::PresentMode::AutoVsync,
wgpu::PresentMode::Fifo,
wgpu::PresentMode::FifoRelaxed,
wgpu::PresentMode::Mailbox,
wgpu::PresentMode::Immediate,
wgpu::PresentMode::AutoNoVsync,
],
wgpu::PresentMode::Fifo => &[
wgpu::PresentMode::Fifo,
wgpu::PresentMode::AutoVsync,
wgpu::PresentMode::FifoRelaxed,
Expand Down Expand Up @@ -414,4 +434,39 @@ mod tests {
let selected = select_present_mode(wgpu::PresentMode::Immediate, available);
assert_eq!(selected, wgpu::PresentMode::AutoNoVsync);
}

#[test]
fn select_present_mode_prefers_auto_no_vsync_over_mailbox_for_immediate_request(
) {
let available = &[
wgpu::PresentMode::Mailbox,
wgpu::PresentMode::AutoNoVsync,
wgpu::PresentMode::Fifo,
];
let selected = select_present_mode(wgpu::PresentMode::Immediate, available);
assert_eq!(selected, wgpu::PresentMode::AutoNoVsync);
}

#[test]
fn select_present_mode_prefers_auto_no_vsync_when_requested() {
let available = &[
wgpu::PresentMode::Immediate,
wgpu::PresentMode::AutoNoVsync,
wgpu::PresentMode::Fifo,
];
let selected =
select_present_mode(wgpu::PresentMode::AutoNoVsync, available);
assert_eq!(selected, wgpu::PresentMode::AutoNoVsync);
}

#[test]
fn select_present_mode_prefers_auto_vsync_when_requested() {
let available = &[
wgpu::PresentMode::Fifo,
wgpu::PresentMode::AutoVsync,
wgpu::PresentMode::Immediate,
];
let selected = select_present_mode(wgpu::PresentMode::AutoVsync, available);
assert_eq!(selected, wgpu::PresentMode::AutoVsync);
}
}
48 changes: 37 additions & 11 deletions crates/lambda-rs/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,17 +190,8 @@ impl RenderContextBuilder {
})?;

let size = window.dimensions();
let requested_present_mode = present_mode.unwrap_or_else(|| {
if window.vsync_requested() {
return PresentMode::Vsync;
}
return PresentMode::Immediate;
});
let platform_present_mode = match requested_present_mode {
PresentMode::Vsync => targets::surface::PresentMode::Fifo,
PresentMode::Immediate => targets::surface::PresentMode::Immediate,
PresentMode::Mailbox => targets::surface::PresentMode::Mailbox,
};
let platform_present_mode =
resolve_surface_present_mode(present_mode, window.vsync_requested());
surface
.configure_with_defaults(
&gpu,
Expand Down Expand Up @@ -261,6 +252,23 @@ impl RenderContextBuilder {
}
}

fn resolve_surface_present_mode(
builder_mode: Option<PresentMode>,
window_vsync: bool,
) -> targets::surface::PresentMode {
let requested = builder_mode.unwrap_or(if window_vsync {
PresentMode::Vsync
} else {
PresentMode::Immediate
});

return match requested {
PresentMode::Vsync => targets::surface::PresentMode::Fifo,
PresentMode::Immediate => targets::surface::PresentMode::Immediate,
PresentMode::Mailbox => targets::surface::PresentMode::Mailbox,
};
}

/// High‑level rendering context for a single window.
///
/// Purpose
Expand Down Expand Up @@ -1104,4 +1112,22 @@ mod tests {
.expect_err("must error");
assert!(err.to_string().contains("Unknown pipeline 7"));
}

#[test]
fn present_mode_defaults_to_window_vsync_true() {
let mode = resolve_surface_present_mode(None, true);
assert_eq!(mode, targets::surface::PresentMode::Fifo);
}

#[test]
fn present_mode_defaults_to_window_vsync_false() {
let mode = resolve_surface_present_mode(None, false);
assert_eq!(mode, targets::surface::PresentMode::Immediate);
}

#[test]
fn present_mode_builder_override_wins_over_window_setting() {
let mode = resolve_surface_present_mode(Some(PresentMode::Vsync), false);
assert_eq!(mode, targets::surface::PresentMode::Fifo);
}
}
3 changes: 3 additions & 0 deletions crates/lambda-rs/src/render/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ impl WindowBuilder {
///
/// This value is consumed when building a `RenderContext` if no explicit
/// present mode is provided to `RenderContextBuilder`.
///
/// Disabling vsync is best‑effort; the final present mode depends on the
/// platform and adapter surface capabilities.
pub fn with_vsync(mut self, vsync: bool) -> Self {
self.vsync = vsync;
return self;
Expand Down
Loading