MOOR security

Dieser Eintrag ist auf Englisch verfasst.

Shaders, pipelines, and the first triangle

Entry 005347 of 771 tests pass

D3D12 shaders now run on Metal: compute dispatches and draws work, a triangle made it to the screen, and passing tests went from 82 to 347.

What changed

This stretch of 30 commits took the layer from "can clear the screen" to "can run shaders".

  • Shader translation. D3D12 shaders are compiled to DXIL or DXBC, Microsoft's GPU bytecode formats. They now go through dxil-spirv (DXIL/DXBC → SPIR-V, the Vulkan shader format), then SPIRV-Cross (SPIR-V → Metal Shading Language), then Metal 4's compiler. Both are open source: dxil-spirv by Hans-Kristian Arntzen, and SPIRV-Cross, hosted by the Khronos Group. I link them as static libraries.
  • Descriptors. A descriptor is D3D12's small record pointing a shader at a texture or buffer. Every descriptor here is a 32-byte record in a GPU buffer that the translated shaders index directly.
  • Compute and graphics pipelines: compute dispatches, then graphics pipelines and draws. After that came depth/stencil, static samplers, MSAA resolves, queries, bundles and pipeline libraries.

The interesting part

Linking shader stages by name. D3D links a vertex shader's outputs to a pixel shader's inputs by semantic, a string name like COLOR. The translator assigns Metal locations by register number, so two shaders that agree on names can still disagree on numbers. The fix translates the pixel shader first, records the location of each named input, and gives each vertex shader output the location of the input with the same name.

The first triangle. The image below is the first frame drawn with a real draw call. It shows one triangle with a colour at each corner, blended across the face, on a 640×360 offscreen target, drawn by Metal on the Mac GPU. For honesty about provenance: the program was run by hand outside the automated tests, against that day's build plus work not yet committed. No test produced that image. The next session turned it into an automated test sample. Its output under the layer matches the image pixel for pixel.

One triangle on a dark background, with a pink, a violet and a teal corner blended smoothly across its face.
The first frame drawn with a real draw call: one triangle on a 640×360 offscreen target, rendered by Metal on the Mac GPU.
The path of a shader from the game's DXIL to a Metal library.DXIL (from the game) → SPIR-V (dxil-spirv); SPIR-V → Metal Shading Language source (SPIRV-Cross); Metal Shading Language source → Metal library (Metal compiler); Metal library → pipeline stateDXIL(from the game)SPIR-VMetal ShadingLanguage sourceMetal librarypipeline statedxil-spirvSPIRV-CrossMetal compiler
The path of a shader from the game's DXIL to a Metal library. (Mermaid source)

Numbers

PassFailSkipTotal
Before (entry 004)82467220769
This stretch (full run at 16:33)347191233771

The last seven commits came after that run, so it doesn't cover them.

Tests by suite at the end of entry 005: 347 of 771 pass (data as CSV)
  • pass
  • fail
  • skip

suite · share of each row's total

  1. vkd3d-proton (+167)220 pass, 136 fail, 221 skip of 577
  2. vkd3d (+96)123 pass, 55 fail, 12 skip of 190
  3. api (+2)3 pass, 0 fail, 0 skip of 3
  4. samples1 pass, 0 fail, 0 skip of 1