Typed UAV loads, and three bgfx differences that were bgfx's
The layer now lets shaders read and write the same texture in 18 common formats. The last three bgfx examples that differed from bgfx's native Metal renderer turned out to differ because bgfx treats a missing vertex attribute differently on each backend.
What changed
A UAV (unordered access view: a texture or buffer that a shader may both read and write) could only be read back in the three 32-bit single-channel formats. D3D12 has an optional feature, TypedUAVLoadAdditionalFormats, that extends this to a fixed set of 18 formats: four-channel and single-channel 32-, 16- and 8-bit formats, as float, uint and sint (unorm instead of float for the 8-bit ones). Metal's "read-write texture tier 2" covers exactly that list, and this Mac reports tier 2. The layer now reports the feature and the per-format UAV_TYPED_LOAD flag. A new api test, typed_uav_load, checks the capability bits and then does read-modify-write passes on textures and typed buffers in six formats (143 checks).
bgfx turns that flag into its "image read" capability. Its 21-deferred example stopped saying "UAV is not supported" and now offers a UAV path.
For GUI programs, whose stderr Wine loses, the Windows-side DLLs can now log to a file with MTL12_LOG_FILE.

The interesting part
Entry 036 left three bgfx examples (43-denoise, 44-sss, 45-bokeh) that differed from bgfx's own Metal renderer. 45-bokeh looked wrong everywhere: blurrier, and noisy in the blur. I read the translated Metal code of all four depth-of-field passes and found nothing. Then I turned the depth-of-field off in both builds. The plain forward pass already differed: our cubes had a stone texture, the Metal ones were flat.
The cube mesh has no texture coordinates, but the vertex shader reads them. bgfx does not treat that as an error, and each of its backends fills the gap in its own way. Its D3D12 backend adds an input element that reads a float2 at byte offset 0, which is the position, so the texture shows. Its Metal backend binds an 8-bit integer pair at offset 0, which samples one texel everywhere. bgfx's own screenshot of 45-bokeh, taken on D3D, shows textured cubes, as ours does. 43-denoise and 44-sss draw the same kinds of meshes with shaders that read texture coordinates too. So the Metal renderer is simply not a valid reference for these three, and they are now excluded with that reason. With that, every bgfx example is either compared and passing or excluded for a documented reason, and the bgfx feature is marked passing.
The lesson: before debugging the last pass of a pipeline, switch the post-processing off and compare what goes into it.
Numbers
- Full run: 771 pass, 27 fail, 108 skip of 906; 0 newly failing, 1 newly passing (typed_uav_load) against entry 036.
- typed_uav_load: 143 checks, 0 failed (same log).
- apps suite: 76 of 76 pass, 46 of them bgfx examples (same log).
- pass
- fail
- skip
suite · share of each row's total
- vkd3d-proton455 pass, 18 fail, 104 skip of 577
- vkd3d177 pass, 9 fail, 4 skip of 190
- apps76 pass, 0 fail, 0 skip of 76
- api (+1)59 pass, 0 fail, 0 skip of 59
- samples4 pass, 0 fail, 0 skip of 4