ExecuteIndirect, and timeouts that were really assertions
This session added Execute
What changed
ExecuteIndirect lets the GPU write the arguments of draws and dispatches, including the draw count and per-draw root constants (small values passed straight to shaders). Before each barrier-free segment of a command list, a compute pass expands the argument buffer into one record per command: the Metal indirect arguments followed by a copy of the root data. Replay then encodes one Metal indirect draw or dispatch per possible command, and commands past the count get zeroed records.
A typed buffer view (a buffer read through a texel format) used to be its own Metal texture. Now its descriptor holds an element offset and a count into one texture buffer per large region, and the shader applies them. A test creating 13.5 million views stopped timing out.
Destroyed resources now stay alive until the GPU finishes work submitted before the destroy, because Metal 4 command buffers don't retain what they use. Overlapping buffer copies get a barrier between them, which fixed a flaky test.
![Scene indirect: ExecuteIndirect, 48 records of [root constants | draw] making three rings](/wissen/mtl12/media/gallery/indirect.png)
The interesting part
Five tests timed out. None of them was slow. Each had tripped a Metal validation assertion, for example a blend state on an integer render target. Under Wine such an assertion doesn't end the process: the failing call never returns normally, so any lock held around it stays held, and the next call that takes that lock blocks forever. The test runner then reports a timeout, not a crash. The fix is to reject those cases on the D3D12 side before Metal sees them.
A smaller surprise: D3D12 step rate 0 means every instance reads the same vertex attribute, starting at the draw's first instance. Metal's matching "constant" step function ignores that first instance, so I use a per-instance step rate of 2^32−1 instead.
Numbers
- Final full run of the session: 430 of 772 tests pass, up from 408, with 0 newly failing. 22 tests newly pass, among them 6 ExecuteIndirect tests, 3 instance-ID tests (the step-rate fix) and the 5 former assertion timeouts.
- Timeouts went from 9 to 1; the remaining one needs shared fences, which aren't implemented.
- test_copy_buffer_overlap had 7,663 to 19,702 failed checks per run across 14 runs today. After the overlap fix it passed 3 of 3 targeted runs and the final full run.
- pass
- fail
- skip
suite · share of each row's total
- vkd3d-proton (+19)285 pass, 113 fail, 179 skip of 577
- vkd3d (+3)141 pass, 38 fail, 11 skip of 190
- api3 pass, 0 fail, 0 skip of 3
- samples1 pass, 1 fail, 0 skip of 2