Skip to content

dxgi: serialize D3D11 immediate context access during swap chain creation - #437

Open
elzuzu wants to merge 1 commit into
crosire:mainfrom
elzuzu:d3d11-swapchain-multithread
Open

dxgi: serialize D3D11 immediate context access during swap chain creation#437
elzuzu wants to merge 1 commit into
crosire:mainfrom
elzuzu:d3d11-swapchain-multithread

Conversation

@elzuzu

@elzuzu elzuzu commented Sep 5, 2026

Copy link
Copy Markdown

Disclosure up front: the investigation, the instrumentation and this patch were done by an AI assistant (Claude Fable 5.1, through Claude Code) running on my machine; I provided the game, the hardware and the decisions, and I ran all the measurements below myself, so I can reproduce anything on request. If AI-assisted contributions are not wanted here, feel free to close this, no hard feelings.

Mass Effect: Andromeda (Frostbite, D3D11) loses its D3D11 device in roughly one launch out of four as soon as ReShade is loaded, showing the game's own "DirectX Error … DXGI_ERROR_DEVICE_REMOVED" dialog a few seconds after start. Without ReShade it never fails. The failure does not depend on add-ons (ReShade alone reproduces it), on the proxy name (dxgi.dll or d3d11.dll), on NVIDIA Smooth Motion, on Windows Auto HDR, on the windowed swap effect upgrade, and it survives a reboot.

An instrumented build (GetDeviceRemovedReason logged after creation and on failure, a 1 ms watchdog, and optionally D3D11_CREATE_DEVICE_DEBUG with the info queue streamed to the log) shows the device is alive right after D3D11CreateDevice and gets removed inside IDXGIFactory::CreateSwapChain (6 ms into the call in one capture) or on the first resource the effect runtime creates right after it, with DXGI_ERROR_DEVICE_REMOVED or DXGI_ERROR_DRIVER_INTERNAL_ERROR. With the debug layer on, the runtime emits a CORRUPTION message about 450 ms after device creation: ID3D11DeviceContext::GetData: Two threads were found to be executing functions associated with the same Device[Context] at the same time. The game polls queries on the immediate context from a worker thread while its main thread is still creating the swap chain; on its own that stays harmless in practice, but ReShade initializes its runtime on the same immediate context during swap chain creation, and the NVIDIA driver then corrupts and removes the device.

This change turns on ID3D11Multithread protection on the immediate context only for the duration of the swap chain creation (the DXGI call plus the runtime initialization it triggers) and restores the previous state afterwards, on the four creation paths. Applications that already enable the protection are untouched, the others pay the critical section for one call only. A variant that enabled the protection permanently at device creation fixed the crash as well, but this scoped version keeps the per-call cost unchanged after start-up for games that never enable it.

Measured on the same machine, back-to-back launches: 8 device removals in 36 launches without the patch (across all the configurations listed above), 0 in 24 launches with the permanent variant, 0 in 24 launches with this scoped version. Windows 11 26200, GeForce RTX 5070, driver 616.64, ReShade 6.8.0.2155 add-on build, Mass Effect: Andromeda 1.10 (EA app), 3440x1440 borderless. Logs from the instrumented runs are available if useful.

🤖 Generated with Claude Code

…tion

Some applications keep driving the D3D11 immediate context from a worker thread
(e.g. polling queries via ID3D11DeviceContext::GetData) while the main thread is
still inside IDXGIFactory::CreateSwapChain. The D3D11 debug layer reports this as
a CORRUPTION severity message ("Two threads were found to be executing functions
associated with the same Device[Context] at the same time"). Without ReShade this
stays harmless in practice, but ReShade initializes its effect runtime on that same
immediate context during swap chain creation, and the NVIDIA driver then removes
the device intermittently (DXGI_ERROR_DEVICE_REMOVED or
DXGI_ERROR_DRIVER_INTERNAL_ERROR, roughly one launch in four).

Turn on ID3D11Multithread protection only for the duration of the swap chain
creation (the DXGI call plus the runtime initialization it triggers) and restore
the previous state afterwards, so applications that never enable it see no
behavior change once the swap chain exists.

Reproduced and measured on Mass Effect: Andromeda (Frostbite, D3D11) with an
RTX 5070 on driver 616.64: 8 device removals in 36 launches before, 0 in 24
launches with the early protection, 0 in 24 launches with this scoped variant.

Analysis, instrumentation and fix by Claude Fable 5.1 (Anthropic), operated by
the submitter.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PRy9ojuHXSA2UDupjrY7by
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant