Skip to content

Draw the window with DX12 on Intel and retry a crashed renderer only after a driver update - #124

Merged
whoisaldo merged 6 commits into
release/0.3.4-candidatefrom
fix/intel-renderer
Oct 29, 2026
Merged

whoisaldo merged 6 commits into
release/0.3.4-candidatefrom
fix/intel-renderer

Conversation

@whoisaldo

@whoisaldo whoisaldo commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Change

The window renderer (host/src/gui/renderer.rs) only affects the app's own window. Capture and encoding are unchanged.

  • DX12 first on Intel, on the same GPU. The GPU is chosen exactly as before: not avoided, then GPU type, then capability, then wgpu's backend order. When that GPU is an Intel one (0x8086), it draws with DX12 rather than Vulkan, unless DX12 is avoided or less capable there. Other vendors keep the old order. When another card of the same model (vendor and device) is listed, the DX12 preference is skipped and the selection is kept: backends can list identical cards in different orders, and wgpu's DX12 PCI bus id is looked up by those same ids, so the DX12 adapter could be the other card. An NVIDIA GPU beside an Intel Arc, or beside an Intel iGPU, is still chosen on its own preferred backend. Candidate carries the adapter's PCI vendor and device for this. The Troubleshooting "Window drawing" choice and WGPU_BACKEND still narrow the wgpu instance before pick() runs, so Vulkan chosen either way still draws with Vulkan.
  • Fault attribution. The renderer marker now also records the id of the thread that writes it: the window's thread, which lists adapters, creates the device and draws. The failure reporter now writes renderer/<launch>.fault beside a launch's renderer marker. It holds the module the crash was in (resolved as for the crash report), unknown for a crash in no module it could name or one seen only by its exit code, or terminated for an end without a crash. A crash in a driver module counts as the window's only when the crash record's thread is the marker's thread. Otherwise the note leads with the thread (thread <id>: <module>, or unnamed thread: <module> when the record or the marker names no thread). Capture (D3D11 duplication) and encoder probing run in the same user-mode drivers while the marker is live, so a crash on those threads, or in our own code inside a driver, is not taken for a window driver crash. The note is written only while the marker exists, before the crashed process is released. The next launch's sweep stores it in the history entry as fault. A marker without a note, such as one left with no reporter running, counts as unknown.
  • Only a window driver crash waits for a driver update. A failure stays avoided until the GPU key's driver version changes only when its fault is a known graphics-driver or loader module on the window's thread, and the key names a driver version. A driver version means digits separated by dots (31.0.101.2111), as DXGI gives. When DXGI does not list the adapter, the key falls back to wgpu's driver text, which can be a vendor string that stays the same across updates, so it does not count. Every other failure keeps the old RETRY_AFTER clean-launch retry: another thread's crash, a crash record without a thread, our own module, another program's module, unknown, terminated, or a key without a driver version. A driver crash stays noted if the same backend later fails for another reason.
  • Driver modules (by file-name prefix, case-insensitive), kept narrow so overlays and Windows runtime modules are not included:
    • Intel: igvk (Vulkan driver, the 0.3.3 crash), igd (Direct3D drivers, GMM), igc (shader compiler), igxelpicd (Xe OpenGL).
    • AMD: amdvlk (Vulkan), atio6axx (OpenGL), atidxx and atiumd (Direct3D), amdxx and amdxn (newer drivers' D3D12 and D3D11), amdxc (DX12 shader compiler).
    • NVIDIA: nvoglv (OpenGL and Vulkan), nvwgf2um and nvd3dum (Direct3D), nvldumd (UMD loader), nvgpucomp (shader compiler).
    • Loaders: vulkan-1.dll, opengl32.dll.
  • Saved choices follow driver updates. chosen_plan() and the Troubleshooting "avoiding" status now count only failures recorded on the GPUs and drivers DXGI lists now. A failure on a GPU that now has another driver no longer sets the saved choice aside. A GPU that DXGI does not list cannot show its driver, so its failures still apply.
  • Earlier history files. 0.3.3 entries have no fault. Their crash records were removed once reported, so the old data cannot tell where they crashed. They keep the clean-launch retry, which is how 0.3.3 treated them. On the Intel PCs from the field crash scan, Vulkan is no longer the default anyway. fault is left out when absent, and 0.3.3 ignores it when reading, so a downgrade can still read the file.
  • Logs.
    • The Window renderer selected line gains reason=: intel default when the Intel rule changed the backend, avoiding crashed backend when avoidance changed the pick, or default otherwise. Its avoided list shows only entries for the adapters listed now, with their fault.
    • The sweep warning gives fault= and retry= (after a driver update or after clean launches).
    • The Troubleshooting text is unchanged from the base.

Tests

New or updated tests in renderer.rs:

  • Intel-only, with a capable Vulkan adapter, picks DX12 in either listing order. Avoiding DX12 there gives Vulkan.
  • NVIDIA and AMD keep Vulkan. A hybrid Intel iGPU + NVIDIA laptop keeps NVIDIA Vulkan.
  • NVIDIA (Vulkan) beside a discrete Intel Arc (DX12) picks NVIDIA Vulkan, in any order. An Arc that wgpu's order chose draws with DX12. An Arc beside an Intel iGPU is chosen, with DX12.
  • Two identical Arc cards, with either backend listed first and DX12 listing them in either order, keep wgpu's original selection (the first Vulkan card). A twin listing only DX12 does the same. An Arc beside a different Intel model still gets DX12.
  • The driver-module list matches the listed modules, including amdxx64.dll and amdxn64.dll, and rejects others: our own exe, ntdll, KERNELBASE, d3d12core, overlay and hook modules, unknown, terminated, and notes of another thread's crash.
  • Attribution: a driver crash on the marker's thread keeps its module. A capture-thread crash in igd10iumd64.dll, a record without a thread, and a marker without a thread are noted with their thread. Other modules, unknown and terminated are noted as they are.
  • An igvk64.dll crash stays avoided over 500 clean launches, also after a later terminated failure, and is retried after a driver version change.
  • Our own module, an overlay module, unknown and terminated are retried after RETRY_AFTER clean launches. The same holds for an enumerate-stage failure.
  • A sweep test covers the reporter's notes. An igvk64.dll crash on the window's thread stays avoided over 500 clean launches and is retried after a driver version change. A capture-thread crash in igd10iumd64.dll, a crash record without a thread, our own module, terminated and a marker with no note are retried after RETRY_AFTER clean launches. A note without a marker is removed, and the reporter writes none when there is no marker.
  • Driver keys: a key without a version, or with wgpu's non-version text (Intel Corporation Intel driver, AMD proprietary driver 24.10.1), does not count as a known driver, and an igvk64.dll crash on it is retried after RETRY_AFTER clean launches, then twice as long after a second failure.
  • A saved Vulkan choice that crashed in igvk64.dll is set aside, and draws as chosen after the Intel driver changes.
  • A 0.3.3 history.json and a 0.3.3 marker (no thread) load. The old entry is retried and the marker counts as unknown. A 0.3.3-shaped struct still reads the saved file. The reset clears them.
  • A Vulkan choice or WGPU_BACKEND=vulkan wins over the Intel default. Existing renderer tests pass, including Keep OpenGL out of the window renderer so AMD's driver can't crash startup #115's OpenGL test.

Run on macOS: cargo fmt --all --check, cargo clippy --workspace --all-targets -- -D warnings and cargo test --workspace, all passing. The reporter's Windows-only paths are covered by Windows CI.

Release notes

On some PCs with Intel graphics, EternalMonitor could close as it started because Intel's Vulkan driver crashed while the window was created. The window now draws with DirectX 12 on Intel graphics. When a drawing method crashes inside the graphics driver while it creates or draws the window, EternalMonitor keeps it aside until the driver is updated. Other failed starts try it again after a few launches, as before.

…ide the driver

The failure reporter now notes beside the renderer marker what ended the
launch: the module it crashed in, "unknown" or "terminated". Only a crash
in a known graphics driver or loader module waits for a driver update; any
other end, a launch with no note and 0.3.3's entries are retried after
clean launches as before. A saved Window drawing choice is checked against
the drivers the GPUs have now, so a driver update restores it. The Intel
DX12 preference now applies only among the backends of the GPU wgpu's
order chooses, so it never changes the GPU.
The renderer marker records the thread that lists adapters, creates the
device and draws. The reporter passes the crash record's thread, and a
driver-module crash on any other thread, or on an unnamed one, is noted
with its thread and retried after clean launches. Capture and encoder
threads run in the same user-mode drivers while the marker is live.

A key counts as naming its driver only with a dotted version, so wgpu's
vendor text does not keep a backend aside. Newer AMD D3D12 and D3D11
drivers (amdxx64, amdxn64) join the driver list.
…x/intel-renderer

# Conflicts:
#	host/src/gui/mod.rs
Backends can list two identical cards in different orders, and vendor and
device ids cannot tell which DX12 adapter is the chosen card. wgpu's DX12
PCI bus id is looked up by those same ids, so it cannot either. With a twin
listed, the Intel DX12 preference is skipped and the selection is kept.
@whoisaldo
whoisaldo marked this pull request as ready for review October 29, 2026 19:11
@whoisaldo
whoisaldo merged commit 920d228 into release/0.3.4-candidate Oct 29, 2026
7 checks passed
@whoisaldo whoisaldo added the 0.3.4 Part of the 0.3.4 release label Oct 29, 2026
@whoisaldo whoisaldo mentioned this pull request Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0.3.4 Part of the 0.3.4 release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants