Chapter 63 Windows II: Wine and Engagement Gates
Cross-compilation proves that a Windows-shaped program can be produced. CNA’s Wine apparatus asks the harder question: when that program runs, did the intended DirectX implementation actually handle it? The answer cannot be inferred from exit code alone, because Wine can fall back to another DLL stack and still draw a plausible image.
63.1 Six prefixes isolate incompatible runtime stacks
The audited machine carries six named Wine prefixes:
- ~/.wine
-
the Direct2D Wine path;
- ~/.wine-cna-dx1
-
shared by DirectX1/2/3/5/6/7 and Wine’s builtin DirectDraw;
- ~/.wine-cna-dx8
-
the D8VK path;
- ~/.wine-cna-d3d10
-
the Direct3D 10 path;
- ~/.wine-cna-d3d11
-
shared by D3D9 and D3D11 DXVK lanes; and
- ~/.wine-cna-d3d12
-
the vkd3d-proton lane.
Direct2D’s fresh-prefix suite also creates throwaway directories. Other special-purpose prefixes hold Microsoft’s d3dcompiler_47.dll and a real 32-bit XNA 4.0 installation for the D3D9 oracle. Counting only three because three roles are memorable would lose the actual runtime isolation on disk.
A prefix is mutable system state: DLL overrides, bitness, registry entries, installed runtimes, and first-run initialization all live there. Reusing a personal prefix for an automated experiment can change it irreversibly. Both Proton launchers hard-refuse ~/.wine; that guard was added after a Proton/Wine version mismatch half-upgraded a personal prefix and hung for 9.5 hours installing Mono. Bootstrap steps are now timeout-bounded.
63.2 Which translation runtime owns each renderer
The renderer name does not uniquely identify the runtime implementation under Linux:
| Renderer | Runtime path |
|---|---|
| DIRECTX1/2/3/5/6/7 | Wine builtin ddraw.dll; DXVK does not translate DirectDraw. |
| DIRECTX8 | D8VK d3d8; dxgi deliberately remains builtin. |
| DIRECTX9 | DXVK d3d9. |
| DIRECTX10 | Wine d3d10/d3d10_1 front, DXVK d3d10core+dxgi. |
| DIRECTX11 | DXVK d3d11+dxgi. |
| DIRECTX12 | vkd3d-proton d3d12/d3d12core. |
| DIRECT2D | Wine builtin d2d1; WineD3D or a Proton/DXVK experiment below it. |
| GDI | Wine’s gdi32; no dedicated wrapper script. |
| GLIDE | External x86 glide3x.dll, loaded dynamically. |
The same CNA test executable may therefore traverse Wine builtin code, a DXVK component, vkd3d-proton, or an external compatibility DLL. A generic “ran under Wine” label hides the very implementation the test is meant to validate.
63.3 An engagement gate turns logs into a verdict
Each DirectDraw launcher greps its captured output for a :ddraw: trace. DX8/9/10/11 launchers require a DXVK: marker. D3D12 requires vkd3d-proton - applicationVersion:. If the expected marker is absent, the wrapper exits with status 3 and names the likely silent fallback.
Some wrappers also expose an allow-WineD3D diagnostic switch. That is a requested change of oracle, not an equivalent passing configuration. The log gate’s transferable design is simple: identify an implementation-specific positive marker, capture the entire child run, and fail closed when the marker is absent.
Direct2D is the important exception. Its launcher has no d2d1 engagement marker, and Direct2D CTest registrations disable an inherited DXVK gate. A mis-provisioned prefix could therefore produce a result without proving which Direct2D path ran. GDI has no wrapper at all. The engagement method is strong where implemented, not a universal property of every Windows identity.
63.4 Environment-specific workarounds are part of the evidence
The DX8 lane can force DXVK_FILTER_DEVICE_NAME=llvmpipe because the RADV path lost its surface on a second Present. Direct3D 10 needs the real DISPLAY=:0; its DXGI EDID path crashes under Xvfb. Direct2D has an isolated-Xvfb runner and a fresh-prefix suite. These controls describe the environment in which a result holds. They should not be silently generalized into renderer behavior on genuine Windows.
The hardware-backed DXVK/vkd3d results use an AMD Radeon 780M with Mesa RADV. Logs explicitly skip llvmpipe unless a lane deliberately selects it. Naming the adapter prevents a Vulkan software implementation from being mistaken for hardware proof.
63.5 D3D12 and Proton require matched ownership
Plain Wine’s DXGI and a separately overridden vkd3d-proton d3d12.dll did not share the command-queue ABI needed by swap-chain creation. The successful lane launches end-to-end through Proton, keeping its Wine, DXGI, and vkd3d pieces matched. It reached a real CreateSwapChainForHwnd success on 2026-07-14.
The two Proton scripts do not yet share the same version discipline. Direct2D consults a pin file preferring Proton 9.0 Beta then 8.0 and rejects Experimental unless allowed; the D3D12 script still defaults to Proton - Experimental. That moving target is an unresolved reproducibility asymmetry. The Direct2D Proton result also used a fabricated Steam tree and has no surviving prefix, whereas the D3D12 prefix remains.
63.6 The D3D9 oracle controls both sides
One tool runs Microsoft’s unmodified stock-effect .fx sources through genuine d3dcompiler_47.dll under Wine. Sixty-one of 66 resulting variants match FNA’s shipped Microsoft bytecode exactly; the five PixelLighting vertex differences were narrowed to compiler version rather than optimization flags. Wine’s builtin compiler is not an adequate substitute: it fails a real alpha-test ternary and once expanded a roughly 2,160-byte skinning shader to about 1.4 MiB because relative addressing was unavailable.
The pixel oracle renders one declarative scene through two independent programs: real XNA 4.0 inside its dedicated 32-bit prefix and CNA’s MinGW D3D9 renderer. Both run through the same DXVK-verified path so the comparison does not accidentally measure two driver stacks. A mutation-tested image comparator proves that changed pixels are actually detected at the configured tolerance.
This loop also exposed a genuine D3D9 restriction. A8B8G8R8 is legal for textures but not for a primary swap-chain back buffer. CNA substitutes A8R8G8B8 only at back-buffer creation and retains the natural format for ordinary textures; readback handles both byte orders.
63.7 What translated execution cannot prove
DXVK synthesizes legacy D3DCAPS9 fields from a modern Vulkan device. CNA’s logic can be proven to query and interpret those fields correctly, and its output can match XNA through the same DXVK path, but the returned capability numbers are not observations from period Windows drivers. D3D11 and D3D12 query modern surfaces closer to what native applications use, yet they still execute through translation rather than genuine Windows.
The remaining high-value check requires human hardware: native Windows, authentic device-loss events, fullscreen transitions, real XNA 4.0, and a rerun of the oracle outside Wine. Until then, the strongest precise claim is “pixel-verified against XNA through the same engaged DXVK path on this recorded GPU,” not “validated on Windows hardware.” The engagement gates make the first claim unusually strong by ensuring it is not secretly a result from the wrong runtime.