From 89d23ffa85f37fca36df4b3490bd4995e4a56742 Mon Sep 17 00:00:00 2001 From: DWAA1660 Date: Fri, 9 Oct 2026 08:30:12 -0600 Subject: [PATCH] Default Windows startup to DirectX 12 (#16) eframe's default wgpu instance enables PRIMARY | GL on Windows. Creating the OpenGL backend can crash inside AMD's atio6axx.dll before the window appears, so the app exits silently at launch. When WGPU_BACKEND is not set, the Windows instance now enables only DirectX 12; an explicit WGPU_BACKEND is still honoured. macOS, Linux and web are unchanged. Same fix as storytold/designcraft#168 and storytold/filmcraft#179. Claude-Session: https://claude.ai/code/session_01LyVbT6Vv4BwWZ4hY8973qD Co-authored-by: Claude Opus 5.5 Co-authored-by: Brandon Thomas --- README.md | 15 +++++++++++ apps/deckcraft/src/graphics.rs | 47 ++++++++++++++++++++++++++++++++++ apps/deckcraft/src/main.rs | 5 ++++ 3 files changed, 67 insertions(+) create mode 100644 apps/deckcraft/src/graphics.rs diff --git a/README.md b/README.md index 62553f6..5bf4f14 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,21 @@ scorecard. Installers and executables are code-signed. +**If the app doesn't open on Windows:** the desktop app initializes only DirectX 12 by default. +Letting wgpu also create an OpenGL instance can crash some graphics drivers (AMD's +`atio6axx.dll`) before the window appears, so the app would flash in Task Manager and quit. +`WGPU_BACKEND` overrides the default for troubleshooting (for example `dx12` or `vulkan`). In +PowerShell, from the folder containing the executable: + +```powershell +$env:WGPU_BACKEND = "vulkan" +& .\deckcraft.exe +Remove-Item Env:WGPU_BACKEND # restore the default for later launches +``` + +An explicit `gl` override can bring the driver crash back on affected systems. The macOS, Linux +and web backend defaults are unchanged. + ### macOS | Build | File | Notes | diff --git a/apps/deckcraft/src/graphics.rs b/apps/deckcraft/src/graphics.rs new file mode 100644 index 0000000..ccd0c45 --- /dev/null +++ b/apps/deckcraft/src/graphics.rs @@ -0,0 +1,47 @@ +//! Windows graphics instance configuration, applied before wgpu can initialize any driver. + +use eframe::{NativeOptions, egui_wgpu::WgpuSetup, wgpu::Backends}; + +/// Restrict the wgpu instance to DirectX 12 unless `backend_override` (normally +/// `Backends::from_env()`, i.e. `WGPU_BACKEND`) names other backends. +pub fn configure(options: &mut NativeOptions, backend_override: Option) { + if let WgpuSetup::CreateNew(create) = &mut options.wgpu_options.wgpu_setup { + // eframe's default includes GL. Creating that backend can crash inside AMD's + // atio6axx.dll before adapter selection or any Rust error handling runs, so the + // window never appears. Choosing an adapter afterwards is too late: only leaving GL + // out of the instance avoids it. This matches the verified WGPU_BACKEND=dx12 + // workaround without mutating process environment variables. + create.instance_descriptor.backends = backend_override.unwrap_or(Backends::DX12); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn configured_backends(backend_override: Option) -> Backends { + let mut options = NativeOptions::default(); + configure(&mut options, backend_override); + let WgpuSetup::CreateNew(create) = options.wgpu_options.wgpu_setup else { + panic!("default native options must create a wgpu instance"); + }; + create.instance_descriptor.backends + } + + #[test] + fn windows_default_initializes_only_dx12() { + // eframe's own default (PRIMARY | GL) would initialize OpenGL as well. + let WgpuSetup::CreateNew(eframe_default) = NativeOptions::default().wgpu_options.wgpu_setup else { + panic!("default native options must create a wgpu instance"); + }; + assert!(eframe_default.instance_descriptor.backends.contains(Backends::GL)); + assert_eq!(configured_backends(None), Backends::DX12); + } + + #[test] + fn explicit_backend_override_is_preserved() { + for backends in [Backends::VULKAN, Backends::GL, Backends::DX12, Backends::VULKAN | Backends::DX12, Backends::empty()] { + assert_eq!(configured_backends(Some(backends)), backends); + } + } +} diff --git a/apps/deckcraft/src/main.rs b/apps/deckcraft/src/main.rs index 3d64655..7b5e48b 100644 --- a/apps/deckcraft/src/main.rs +++ b/apps/deckcraft/src/main.rs @@ -14,6 +14,8 @@ mod audio; mod control_server; +#[cfg(any(target_os = "windows", test))] +mod graphics; mod logging; use deckcraft_engine::Session; @@ -188,6 +190,9 @@ fn main() -> eframe::Result { b.with_x11(); })); } + // Before eframe creates the wgpu instance: default Windows to DirectX 12 only (see graphics.rs). + #[cfg(target_os = "windows")] + graphics::configure(&mut options, eframe::wgpu::Backends::from_env()); eframe::run_native( "DeckCraft", options,