From b3f2a89944278b704231cffdcf928b2b6d94b21c Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 9 Oct 2026 09:44:20 -0400 Subject: [PATCH] Windows: default to Vulkan | DX12 | Metal (drop only GL) instead of forcing DX12 Forcing DX12 compiles shaders through FXC, which rejects fx.wgsl (silent CPU fallback), and leaves machines without DX12 with no backend. Leaving GL out is what avoids the AMD atio6axx.dll crash. Co-Authored-By: Claude Opus 5.5 --- README.md | 4 ++-- apps/filmcraft/src/graphics.rs | 19 ++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 39eb0325..606b3e31 100644 --- a/README.md +++ b/README.md @@ -327,8 +327,8 @@ Nothing below the front ends depends on a UI toolkit or OS API. `cargo xtask ci` 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 +**If the app doesn't open on Windows:** the desktop app initializes only Vulkan and DirectX 12 by +default, not OpenGL. 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: diff --git a/apps/filmcraft/src/graphics.rs b/apps/filmcraft/src/graphics.rs index ccd0c459..b2be99cb 100644 --- a/apps/filmcraft/src/graphics.rs +++ b/apps/filmcraft/src/graphics.rs @@ -2,16 +2,18 @@ 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. +/// Restrict the wgpu instance to the primary backends (Vulkan, DirectX 12, Metal), i.e. leave +/// OpenGL out, 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); + // out of the instance avoids it. Keep Vulkan and DX12 both: forcing DX12 alone sends + // shaders through FXC (which rejects fx.wgsl, silently falling back to the CPU) and + // leaves machines without DX12 with no backend at all. + create.instance_descriptor.backends = backend_override.unwrap_or(Backends::PRIMARY); } } @@ -29,13 +31,16 @@ mod tests { } #[test] - fn windows_default_initializes_only_dx12() { + fn windows_default_leaves_out_gl() { // 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); + let configured = configured_backends(None); + assert_eq!(configured, Backends::PRIMARY); + assert!(!configured.contains(Backends::GL)); + assert!(configured.contains(Backends::DX12) && configured.contains(Backends::VULKAN)); } #[test]