MOOR security

Dieser Eintrag ist auf Englisch verfasst.

First pixels: a cleared screen that matches Windows exactly

Entry 002No full test run

A D3D12 program under Wine now clears its window through Metal, and the frame matches Microsoft's reference renderer bit for bit.

What changed

This session produced the first vertical slice:

  • a D3D12 device, resources, fences, command lists and queues on Metal 4;
  • a DXGI swap chain that presents through a CAMetalLayer;
  • a sample program that clears the backbuffer and presents it.

The sample's frame is compared with a reference image rendered by WARP, Microsoft's software D3D12 renderer, in a Windows VM. It matches bit for bit.

The session also set up the test harness: a setup script, a runner for the vkd3d and vkd3d-proton D3D12 test suites, and a list of every D3D12 feature with its implementation status.

Scene clear: ClearRenderTargetView only, whole target then rects, one call per colour; no draw
Gallery scene clear: ClearRenderTargetView only, whole target then rects, one call per colour; no draw. All scenes in the gallery

The interesting part

Three things I didn't expect:

  1. A second commit of a Metal 4 command buffer kills the process. Committing the same MTL4CommandBuffer twice doesn't return an error. It trips an assertion inside Apple's driver and aborts, which under Wine takes down the whole game. D3D12 allows running a command list as many times as you like, so I can't map one D3D12 command list to one Metal command buffer. I confirmed this with a small standalone program and recorded the fix as an architecture decision; entry 004 describes it. The general lesson: validate everything before it reaches Metal, because many of Metal's checks abort rather than fail.
  2. Metal's GPU counters only count up. A D3D12 fence (a counter the CPU and GPU use to wait on each other) may be set back to a lower value. MTLSharedEvent silently ignores a lower value. One vkd3d-proton test checks exactly that.
  3. Wine has a clean way to load the macOS half. A DLL has a Windows half and a macOS half: the Windows part runs inside Wine, and the macOS part calls Metal. The Windows part can load its macOS library by path through a Wine-internal interface, without being built as a Wine "builtin" DLL. That matters, because Wine would otherwise prefer its own builtin d3d12.dll over mine. It is an internal interface, so the fallback is written down in case Wine changes it.

A practical one: when WARP reference images are generated remotely in the Windows VM, the commands run in a non-interactive Windows session with no desktop. Swap chain creation fails there with DXGI_ERROR_NOT_CURRENTLY_AVAILABLE, even for a software renderer. Running them as a one-off scheduled task in the user's interactive session works.

How the clear sample is checked: our frame against a reference frame from WARP, Microsoft's CPU rasterizer.clear sample → mtl12 under Wine on Metal 4; mtl12 under Wine on Metal 4 → our frame; clear sample → WARP (Microsoft's CPU rasterizer); WARP (Microsoft's CPU rasterizer) → reference frame; our frame → image diff; reference frame → image diff; image diff → 0 differing pixels ✔clear samplemtl12 under Wineon Metal 4our frameWARP(Microsoft's CPU rasterizer)reference frameimage diff0 differing pixels ✔
How the clear sample is checked: our frame against a reference frame from WARP, Microsoft's CPU rasterizer. (Mermaid source)

Numbers

  • The clear sample matches the WARP reference bit for bit.
  • No full-suite baseline was committed this session. The first one is in entry 003.