MOOR security

Dieser Eintrag ist auf Englisch verfasst.

Video formats, honest format caps, and the 1024th sampler

Entry 015508 of 782 tests pass

Apple's GPU lets you create more samplers than shaders can use, and says nothing: sampler 1024 and later return garbage.

What changed

mtl12 translates Direct3D 12 (Microsoft's low-level graphics API) to Apple's Metal, so Windows games can run under Wine on Apple Silicon. This session added four things:

  • Heaps over existing memory. A heap can now be opened over memory the application already owns. A review found that the file-mapping version aliased pages it didn't own; it now keeps its own alias of those pages.
  • Residency calls. They now complete immediately, because Metal already keeps the memory resident.
  • Video formats. NV12, P010 and P016 store brightness at full size and colour at half size. Each part (a "plane") now becomes its own Metal texture.
  • Format caps. The driver now reports what each format can do: sampling, blending, multisampling, and shader writes.

The last change mattered more than it sounds. Test suites check these capability bits and quietly skip what the driver says it can't do. One vkd3d-proton UAV-clear test went from 9 checks to 33,437 (a UAV is a shader-writable view). That surfaced a real bug: clearing a 16-bit float texture to a very large but finite value wrote infinity. D3D12 wants the largest finite value.

Scene samplers: 2048 samplers in one heap, each with its own border colour on a ramp
Gallery scene samplers: 2048 samplers in one heap, each with its own border colour on a ramp. All scenes in the gallery

The interesting part

D3D12 lets a shader index a table of up to 2048 samplers (a sampler is the object that says how a texture is filtered and addressed). Metal reports a budget of 1024 unique samplers for argument buffers, its equivalent of those tables, on an M1 Max.

An earlier spike (a throwaway experiment) had created 4096 samplers without any error, and I took that as good news. It wasn't. The new test uses 2048 samplers that each give a different result. Samplers 0–1022 return the right values, and from index 1023 on they return garbage such as 0, 147 and 323. Metal gives no error and no validation message.

The same test showed a second detail: Metal rounds a sampler's minimum level of detail to 1/64 steps. My first test design used 1/256 steps, so samplers that D3D12 considers different looked identical.

The fix isn't done. The plan is to move the level-of-detail clamps out of the Metal sampler and into the shader, so fewer distinct Metal samplers are needed. For now the driver logs an error once the budget is exceeded, and the test stays red on purpose.

2048 distinct samplers against a budget of 1024 samplers per argument buffer.D3D12 sampler heap 2048 distinct samplers → 2048 unique Metal samplers (created without an error); 2048 unique Metal samplers (created without an error) → maxArgumentBufferSamplerCount = 1024 on the M1 Max; maxArgumentBufferSamplerCount = 1024 on the M1 Max → read the right value ✔ (samplers 0–1022); maxArgumentBufferSamplerCount = 1024 on the M1 Max → read 0 or unrelated values, nothing logged ✘ (sampler 1023 and later)D3D12 sampler heap2048 distinct samplers2048 unique Metal samplers(created without an error)maxArgumentBufferSamplerCount= 1024 on the M1 Maxread the right value ✔read 0 or unrelated values,nothing logged ✘samplers 0–1022sampler 1023 and later
2048 distinct samplers against a budget of 1024 samplers per argument buffer. (Mermaid source)

Numbers

  • Full run: 508 pass, 92 fail, 182 skip of 782 tests. In the previous full run (entry 014): 501/93/184 of 778. 0 newly failing.
  • vkd3d-proton test_clear_unordered_access_view_image: 9 checks with 85 skipped → 33,437 checks with 0 failed.
  • Sampler budget: the device reports maxArgumentBufferSamplerCount = 1024. api/sampler_heap_2048 fails 9 checks.
Tests by suite at the end of entry 015: 508 of 782 pass (data as CSV)
  • pass
  • fail
  • skip

suite · share of each row's total

  1. vkd3d-proton (+4)343 pass, 62 fail, 172 skip of 577
  2. vkd3d151 pass, 29 fail, 10 skip of 190
  3. api (+3)11 pass, 1 fail, 0 skip of 12
  4. samples3 pass, 0 fail, 0 skip of 3