Merge pull request #2158 from Silvertree2010/fix/2116-graphics-fallback-marks-a-workin

Keep the graphics backend when the window closes before its first frame
This commit is contained in:
Brandon Thomas authored and GitHub committed 2026-11-02 23:23:50 -05:00
commit 3a40dc7577
2 files changed
+26 -3

No files matched your search

+6 -1
View File
@@ -678,7 +678,12 @@ fn restart_without<'a>(graphics_failed: bool, frames: u64, picked: Option<&'a st
/// ended it.
pub fn finish(outcome: Result<eframe::Result, String>, startup: &Startup) -> Result<(), String> {
let (why, graphics_failed) = match outcome {
Ok(Ok(())) => return Ok(()),
// The window closed normally, perhaps before its first frame or before the app was
// created (so `on_exit` never ran): no driver fault took this start down (#2116).
Ok(Ok(())) => {
startup.presented();
return Ok(());
}
Ok(Err(e @ eframe::Error::Wgpu(_))) => (e.to_string(), true),
Ok(Err(e)) => (e.to_string(), false),
Err(panic) => (panic, GRAPHICS_PANIC.load(Ordering::Relaxed)),
+20 -2
View File
@@ -14,8 +14,9 @@
//! fallback off.
//!
//! The fallback: before the window is created, `gpu.json` in the settings directory records the
//! backend being tried; once a frame has been presented, or the graphics failed with an error the
//! app caught (see `gpu::finish`), that entry is cleared. An entry still there at the next start
//! backend being tried; once a frame has been presented, the window closed normally (even before
//! its first frame), or the graphics failed with an error the app caught (see `gpu::finish`), that
//! entry is cleared. An entry still there at the next start
//! means the previous start never got that far — the driver crashed, or the app was killed
//! meanwhile — so that backend joins `failed`, the next candidate is tried and the status bar says
//! so. Backends a restart left out (`--gpu-skip=`, see `gpu`) aren't chosen for that start but
@@ -538,6 +539,23 @@ mod tests {
let _ = std::fs::remove_dir_all(path.parent().expect("dir"));
}
/// A window closed before its first frame (#2116): the app was created slowly or not at all,
/// so neither a frame nor `on_exit` cleared the record, but eframe ended cleanly. No driver
/// fault took that start down, so the next start keeps the backend.
#[test]
fn a_start_that_ends_cleanly_before_its_first_frame_does_not_fail_its_backend() {
let path = temp_path("clean-end");
let fallback = Fallback::begin_unforced(Some(path.clone()), V, &[]).expect("candidates");
let first = fallback.backend;
assert_eq!(read(&path).trying, Some(first));
let startup = super::super::Startup::new(Some(fallback), Vec::new());
assert_eq!(super::super::finish(Ok(Ok(())), &startup), Ok(()));
assert_eq!(read(&path).trying, None, "a clean end leaves no backend being tried");
let c = choose(candidates(), &read(&path), V, &[]).expect("candidates");
assert_eq!((c.backend, c.record.failed, c.switched_from), (first, Vec::new(), None));
let _ = std::fs::remove_dir_all(path.parent().expect("dir"));
}
#[test]
fn without_a_path_nothing_is_written_and_a_bad_path_is_not_fatal() {
let mut s = Fallback::begin_unforced(None, V, &[]).expect("candidates");