Skip to content

gfx-views-raster (2026-11-02, batch r4): stencil cube views, remaining integer views, separate-texture slot masks, viewport swizzles, provoking vertex

Branch claude/gfx-views-raster-2026-11-02-r4 (Mac, Metal, base ed33737). Contract: gfx.md section 13 ("Views and raster state").

What changed

  1. Stencil sampling of cube / cube array depth-stencil views:
  2. Before: the translator refused it ("stencil sampling of a texture of type 3 ...").
  3. Now: the view is declared texturecube<uint> / texturecube_array<uint> and read through StencilTexCube / StencilTexCubeArray. The face and texel come from the direction (cube_face / cube_texel, shared with the integer cube wrappers).
  4. Integer 1D, 1D array, cube array and 2D multisample array textures:
  5. Declared with the matching integer texture type and read through IntTex1D, IntTex1DArray, IntTexCubeArray and IntTex2DMSArray. Only texel buffers and depth comparison keep the float declaration.
  6. The wrappers' calculate_*_lod now return float, as Metal's do. A TMML on a wrapper used to build float2(float2, float2).
  7. Buffer <-> texture copies of a 1D array treat the region's y / height as layers. Metal asserted on the y offset before.
  8. Depth / stencil / integer slot masks for separate textures (the r3 finding):
  9. ShaderKey.sep_*_slots and pipe_key.sep_*[2], filled by sep_slot_masks from the separate texture bindings. Geometry and tess stages get them through stage_key_masks.
  10. The translator applies them to the texture word of a separate pair (sep_masks).
  11. Before: a separate integer or stencil texture was declared float, a Metal validation error.
  12. SetViewportSwizzles:
  13. Recorded as OP_VP_SWIZZLE and applied to the clip position by the last pre-raster stage (ShaderKey.vp_swizzle): vertex, tess eval, and the geometry pass-through function.
  14. It uses viewport 0's swizzle. A program that selects another viewport with different swizzles still gets viewport 0's (logged once).
  15. SetProvokingVertexMode:
  16. Recorded as OP_PROVOKING. Mode 1 (last) re-emits direct draws as lists with each primitive's last vertex first (pv_last_indices).
  17. Mode 0 is Metal's own convention (first vertex, checked on the M5) and stays unchanged.
  18. Indirect draws and draws through the geometry / tess stage paths keep the first vertex (logged once).
  19. The 0 = first / 1 = last mapping is a hypothesis: it follows the Maxwell register, and the NVN enum isn't public.
  20. obj.h: OP_VP_SWIZZLE and OP_PROVOKING appended before OP_COUNT (enum only). mtl_priv.h: pipe_key fields. mtl_stages.inc: one line in stage_key_masks. All three are the orchestrator's approved ownership extension.
  21. TRANSLATOR_VERSION 17 -> 18.

Tests

  • t_stencil_sample: cube and cube array D24S8 textures, each layer-face cleared to its own stencil value, sampled in seven directions.
  • t_int_tex 7-10:
  • 1D;
  • a 1D array with per-layer uploads;
  • a cube array (cube 1, face -Y);
  • a 4x multisample array (layer 1 written by a draw).
  • t_sep_sampler 3-4: an RGBA8UI texture and a stencil view at separate bindings. Without the masks the draw fails Metal validation.
  • t_vp_swizzle (new): identity, -x, x <-> y, back to identity.
  • t_provoking (new): a triangle list, a strip, an indexed strip with a restart and a line list, each in modes 0 and 1.
  • t_xlate: pins for every new wrapper, each compiled by Metal (TEX, TLD4, TMML, TLD.MS.ARRAY).
  • make -C gfx test: ALL TESTS PASSED. The LAS corpus still gives 5767 / 5767 / 5767.

Not verified on a title

None of the four titles reaches these paths in the scenes booted: no stencil cube view, no integer 1D / cube array / MS array view, no separate binding, no viewport swizzle, no provoking mode 1. The boots show no regression (integrator file).