Buffer views that start in the middle of an element
mtl12 now supports Direct3D 12 buffer views given in bytes, including 12-byte-per-element views that start 4 or 8 bytes into an element, which Metal's texture buffers can't start at.
What changed
A view tells a shader which part of a buffer to read and how: as raw bytes, as an array of structs, or as "typed" elements of a format such as R32G32B32_UINT (three 32-bit numbers). Direct3D 12 has always described a view's range in whole elements. The newer byte-offset views (the OPTIONS22 capability CreateByteOffsetViewsSupported) give an offset and a size in bytes instead, with a size of 0 meaning "to the end of the buffer" (DirectX-Specs, "Revised CreateViews"). mtl12 reported the capability as unsupported until this session, so vkd3d-proton's test_buffer_descriptor_byte_offset skipped.
The function that writes a buffer view into a descriptor (a 64-byte record shaders read to find a resource) now takes bytes, checks the spec's alignment rules, and turns old element-based views into bytes as well.
The interesting part
Raw and struct views were easy: the record already holds a plain address and a length. Typed views go through a Metal texture buffer, whose start must be 16-byte aligned. mtl12 already handles that by pointing the texture buffer at an aligned base and letting the shader add the view's first element.
R32G32B32 was the problem. Metal has no 12-byte texture-buffer format, so mtl12 reads such a view as a buffer of single 32-bit texels, three per element. The spec lets a 12-byte view start at any multiple of 4 bytes. At offset 4, element 0 starts at texel 1, element 1 at texel 4, and so on. No element index lands on those texels, and no aligned base helps: the only 16-byte boundary at or below byte 4 is byte 0.
The fix is one add in the shader. The record already had a word saying "this view is R32G32B32". It now holds 1 plus the shift (0, 1 or 2 texels), and a SPIRV-Cross patch reads element i from texel 3i + word − 1 (patch 0044). Every other format reads the same as before.
Numbers
- Full run: 867 pass, 27 fail, 68 skip of 962, against 865/27/69 of 961 at the end of the last session; 2 newly passing (api/byte_offset_views, new, and vkd3d-proton test_buffer_descriptor_byte_offset, which skipped before), 0 newly failing.
- api/byte_offset_views: 1082 checks. It reads three R32G32B32 views at offsets 4, 8 and 24, struct, raw, R32 and R16 views, writes through three UAVs including a struct counter, and clears a byte-offset UAV.
- Mutations: without the shift, 6 api checks and 2 vkd3d-proton checks fail. Reading the UAV counter offset from the older, shorter description's place fails the counter check.
- pass
- fail
- skip
suite · share of each row's total
- vkd3d-proton (+1)498 pass, 14 fail, 65 skip of 577
- vkd3d178 pass, 9 fail, 3 skip of 190
- api (+1)91 pass, 0 fail, 0 skip of 91
- apps80 pass, 0 fail, 0 skip of 80
- wine-dxgi16 pass, 4 fail, 0 skip of 20
- samples4 pass, 0 fail, 0 skip of 4