From 952b6a63c3c24c1b06bdd47924e020d9548fd3ba Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 11 Aug 2024 13:33:10 -0600 Subject: [PATCH] Better graphics backend fallback This attempts the following in order: - wgpu with user-selected backend - wgpu with automatic backend - glow (fallback OpenGL backend) This should eliminate most issues where objdiff fails to launch. --- objdiff-gui/Cargo.toml | 2 +- objdiff-gui/src/app.rs | 2 +- objdiff-gui/src/main.rs | 128 ++++++++++++++++++++++++------ objdiff-gui/src/views/graphics.rs | 2 +- 4 files changed, 105 insertions(+), 29 deletions(-) diff --git a/objdiff-gui/Cargo.toml b/objdiff-gui/Cargo.toml index 50588fb..c989dcb 100644 --- a/objdiff-gui/Cargo.toml +++ b/objdiff-gui/Cargo.toml @@ -18,7 +18,7 @@ name = "objdiff" path = "src/main.rs" [features] -default = ["wgpu", "wsl"] +default = ["glow", "wgpu", "wsl"] glow = ["eframe/glow"] wgpu = ["eframe/wgpu", "dep:wgpu"] wsl = [] diff --git a/objdiff-gui/src/app.rs b/objdiff-gui/src/app.rs index 639d126..fae0e10 100644 --- a/objdiff-gui/src/app.rs +++ b/objdiff-gui/src/app.rs @@ -275,7 +275,7 @@ impl App { #[cfg(feature = "glow")] if let Some(gl) = &cc.gl { use eframe::glow::HasContext; - app.view_state.graphics_state.active_backend = "OpenGL".to_string(); + app.view_state.graphics_state.active_backend = "OpenGL (Fallback)".to_string(); app.view_state.graphics_state.active_device = unsafe { gl.get_parameter_string(0x1F01) }; // GL_RENDERER } diff --git a/objdiff-gui/src/main.rs b/objdiff-gui/src/main.rs index d470d32..59cfe64 100644 --- a/objdiff-gui/src/main.rs +++ b/objdiff-gui/src/main.rs @@ -11,6 +11,7 @@ mod views; use std::{ path::PathBuf, + process::ExitCode, rc::Rc, sync::{Arc, Mutex}, }; @@ -37,7 +38,7 @@ const APP_NAME: &str = "objdiff"; // When compiling natively: #[cfg(not(target_arch = "wasm32"))] -fn main() { +fn main() -> ExitCode { // Log to stdout (if you run with `RUST_LOG=debug`). tracing_subscriber::fmt::init(); @@ -48,7 +49,6 @@ fn main() { let app_path = std::env::current_exe().ok(); let exec_path: Rc>> = Rc::new(Mutex::new(None)); - let exec_path_clone = exec_path.clone(); let mut native_options = eframe::NativeOptions { follow_system_theme: false, ..Default::default() }; match load_icon() { @@ -56,7 +56,7 @@ fn main() { native_options.viewport.icon = Some(Arc::new(data)); } Err(e) => { - log::warn!("Failed to load application icon: {}", e); + log::warn!("Failed to load application icon: {e:?}"); } } let mut graphics_config = GraphicsConfig::default(); @@ -69,7 +69,7 @@ fn main() { } Ok(None) => {} Err(e) => { - log::error!("Failed to load native config: {:?}", e); + log::error!("Failed to load native config: {e:?}"); } } graphics_config_path = Some(config_path); @@ -87,6 +87,104 @@ fn main() { }; } } + let mut eframe_error = None; + if let Err(e) = run_eframe( + native_options.clone(), + utc_offset, + exec_path.clone(), + app_path.clone(), + graphics_config.clone(), + graphics_config_path.clone(), + ) { + eframe_error = Some(e); + } + #[cfg(feature = "wgpu")] + if let Some(e) = eframe_error { + // Attempt to relaunch using wgpu auto backend if the desired backend failed + #[allow(unused_mut)] + let mut should_relaunch = graphics_config.desired_backend != GraphicsBackend::Auto; + #[cfg(feature = "glow")] + { + // If the desired backend is OpenGL, we should try to relaunch using the glow renderer + should_relaunch &= graphics_config.desired_backend != GraphicsBackend::OpenGL; + } + if should_relaunch { + log::warn!("Failed to launch application: {e:?}"); + log::warn!("Attempting to relaunch using auto-detected backend"); + native_options.wgpu_options.supported_backends = Default::default(); + if let Err(e) = run_eframe( + native_options.clone(), + utc_offset, + exec_path.clone(), + app_path.clone(), + graphics_config.clone(), + graphics_config_path.clone(), + ) { + eframe_error = Some(e); + } else { + eframe_error = None; + } + } else { + eframe_error = Some(e); + } + } + #[cfg(all(feature = "wgpu", feature = "glow"))] + if let Some(e) = eframe_error { + // Attempt to relaunch using the glow renderer if the wgpu backend failed + log::warn!("Failed to launch application: {e:?}"); + log::warn!("Attempting to relaunch using fallback OpenGL backend"); + native_options.renderer = eframe::Renderer::Glow; + if let Err(e) = run_eframe( + native_options, + utc_offset, + exec_path.clone(), + app_path, + graphics_config, + graphics_config_path, + ) { + eframe_error = Some(e); + } else { + eframe_error = None; + } + } + if let Some(e) = eframe_error { + log::error!("Failed to launch application: {e:?}"); + return ExitCode::FAILURE; + } + + // Attempt to relaunch application from the updated path + if let Ok(mut guard) = exec_path.lock() { + if let Some(path) = guard.take() { + cfg_if! { + if #[cfg(unix)] { + let e = exec::Command::new(path) + .args(&std::env::args().collect::>()) + .exec(); + log::error!("Failed to relaunch: {e:?}"); + return ExitCode::FAILURE; + } else { + let result = std::process::Command::new(path) + .args(std::env::args()) + .spawn(); + if let Err(e) = result { + log::error!("Failed to relaunch: {e:?}"); + return ExitCode::FAILURE; + } + } + } + } + }; + ExitCode::SUCCESS +} + +fn run_eframe( + native_options: eframe::NativeOptions, + utc_offset: UtcOffset, + exec_path_clone: Rc>>, + app_path: Option, + graphics_config: GraphicsConfig, + graphics_config_path: Option, +) -> Result<(), eframe::Error> { eframe::run_native( APP_NAME, native_options, @@ -101,28 +199,6 @@ fn main() { )) }), ) - .expect("Failed to run eframe application"); - - // Attempt to relaunch application from the updated path - if let Ok(mut guard) = exec_path.lock() { - if let Some(path) = guard.take() { - cfg_if! { - if #[cfg(unix)] { - let result = exec::Command::new(path) - .args(&std::env::args().collect::>()) - .exec(); - log::error!("Failed to relaunch: {result:?}"); - } else { - let result = std::process::Command::new(path) - .args(std::env::args()) - .spawn(); - if let Err(e) = result { - log::error!("Failed to relaunch: {:?}", e); - } - } - } - } - }; } // when compiling to web using trunk. diff --git a/objdiff-gui/src/views/graphics.rs b/objdiff-gui/src/views/graphics.rs index 68eee02..53b3286 100644 --- a/objdiff-gui/src/views/graphics.rs +++ b/objdiff-gui/src/views/graphics.rs @@ -36,7 +36,7 @@ pub enum GraphicsBackend { OpenGL, } -#[derive(Debug, Default, serde::Deserialize, serde::Serialize)] +#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)] pub struct GraphicsConfig { #[serde(default)] pub desired_backend: GraphicsBackend,