diff --git a/Cargo.lock b/Cargo.lock
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -290,6 +290,7 @@ dependencies = [
  "objc2 0.6.5",
  "objc2-app-kit 0.3.2",
  "objc2-foundation 0.3.2",
+ "pollster",
  "ron",
  "serde",
  "tray-icon",
diff --git a/apps/artcraft-launcher/Cargo.toml b/apps/artcraft-launcher/Cargo.toml
--- a/apps/artcraft-launcher/Cargo.toml
+++ b/apps/artcraft-launcher/Cargo.toml
@@ -51,6 +51,9 @@ objc2-app-kit = { version = "=0.3.2", default-features = false, features = ["std
 # artcraft-launcher-native.
 [target.'cfg(target_os = "windows")'.dependencies]
 winreg = "0.55"
+# Waits on wgpu's adapter list in the Direct3D 12 probe (main.rs, `dx12_has_adapter`). Already in
+# Cargo.lock through eframe.
+pollster = "1"
 
 # Linux and the BSDs: the desktop's animations setting, from its settings portal (motion.rs).
 # Already in Cargo.lock through tray-icon and notify-rust.
diff --git a/apps/artcraft-launcher/src/main.rs b/apps/artcraft-launcher/src/main.rs
--- a/apps/artcraft-launcher/src/main.rs
+++ b/apps/artcraft-launcher/src/main.rs
@@ -155,12 +155,15 @@ fn native_options(hidden: bool) -> eframe::NativeOptions {
     eframe::NativeOptions { viewport, persist_window: true, wgpu_options: wgpu_options(), ..Default::default() }
 }
 
-/// wgpu's backend list. On Windows that is Direct3D 12 with GL as the fallback, not Vulkan:
-/// Vulkan goes through vendor ICDs and third-party overlay layers, and on hybrid AMD laptops whose
-/// integrated and discrete GPUs run different driver packages (common on OEM machines, where the
-/// Adrenalin installer leaves the integrated GPU on the OEM driver) it crashes inside
-/// `amdvlk64.dll` before the first frame. `WGPU_BACKEND` still overrides the default, and then
-/// wgpu picks the adapter itself. Direct3D 12 shaders compile with FXC ([`pin_dx12_compiler`]).
+/// wgpu's backend list. On Windows that is Direct3D 12, not Vulkan: Vulkan goes through vendor
+/// ICDs and third-party overlay layers, and on hybrid AMD laptops whose integrated and discrete
+/// GPUs run different driver packages (common on OEM machines, where the Adrenalin installer
+/// leaves the integrated GPU on the OEM driver) it crashes inside `amdvlk64.dll` before the first
+/// frame. GL is only added when Direct3D 12 lists no adapter at all ([`dx12_has_adapter`]): wgpu's
+/// GL backend makes a WGL context while it enumerates, which loads every GPU's OpenGL driver, and
+/// on such laptops an old AMD one (`atio6axx.dll`) crashes the launcher even though Direct3D 12
+/// would draw fine. `WGPU_BACKEND` still overrides the default, and then wgpu picks the adapter
+/// itself. Direct3D 12 shaders compile with FXC ([`pin_dx12_compiler`]).
 ///
 /// Direct3D 12 presents through DirectComposition rather than straight to the window. The
 /// borderless window's drop shadow moves its client area down a pixel, and a swapchain made from
@@ -177,7 +180,8 @@ fn wgpu_options() -> eframe::WgpuConfiguration {
         if let Some(backends) = Backends::from_env() {
             setup.instance_descriptor.backends = backends;
         } else {
-            setup.instance_descriptor.backends = Backends::DX12 | Backends::GL;
+            setup.instance_descriptor.backends =
+                if dx12_has_adapter(&setup.instance_descriptor) { Backends::DX12 } else { Backends::DX12 | Backends::GL };
             let integrated = setup.power_preference == PowerPreference::LowPower;
             setup.native_adapter_selector = Some(Arc::new(move |adapters, surface| {
                 adapters
@@ -195,6 +199,26 @@ fn wgpu_options() -> eframe::WgpuConfiguration {
     config
 }
 
+/// Whether Direct3D 12 lists any adapter with `desc`'s settings. Windows 10 and later always have
+/// WARP, the software one, so this is false only where Direct3D 12 itself is missing or broken.
+/// Asked once; Direct3D 12 alone never loads an OpenGL driver.
+#[cfg(windows)]
+fn dx12_has_adapter(desc: &eframe::wgpu::InstanceDescriptor) -> bool {
+    use eframe::wgpu::{Backends, Instance, InstanceDescriptor};
+    static HAS_ADAPTER: OnceLock<bool> = OnceLock::new();
+    *HAS_ADAPTER.get_or_init(|| {
+        let mut probe = InstanceDescriptor::new_without_display_handle();
+        probe.backends = Backends::DX12;
+        probe.flags = desc.flags;
+        probe.backend_options = desc.backend_options.clone();
+        let adapters = pollster::block_on(Instance::new(probe).enumerate_adapters(Backends::DX12));
+        if adapters.is_empty() {
+            log::warn!("Direct3D 12 lists no graphics adapter, trying OpenGL");
+        }
+        !adapters.is_empty()
+    })
+}
+
 /// Compiles Direct3D 12 shaders with FXC (`d3dcompiler_47.dll`, part of Windows) unless
 /// `env_choice` (normally `Dx12Compiler::from_env()`, i.e. `WGPU_DX12_COMPILER`) names another.
 /// wgpu's default (`Auto`) loads whichever `dxcompiler.dll` the DLL search path finds. The launcher
