iter5 vertex+UBO probe — captured 2026-05-19 on ohm
(PineTab2 v2.0, RK3566, Mali-G52 r1 MC1, Mesa 26.0.6, kernel 7.0.0-danctnix1-6)

Source: panvk-bifrost/iter5/{probe_vbo_ubo.c, .vert, .frag, Makefile}
Deployed to: /tmp/panvk-iter5/

===== RUN #1 (baseline) =====
[step] vkCreateInstance
WARNING: panvk is not a conformant Vulkan implementation, testing use only.
[info] gpu='Mali-G52 r1 MC1'
[step] vkCreateDevice
[step] vkCreateBuffer vertex buffer
[step] vkCreateBuffer UBO
[step] vkCreateDescriptorSetLayout (UBO @ vertex)
[step] vkCreatePipelineLayout + shaders
[step] vkCreateGraphicsPipelines
[step] record cmd buffer
[step] submit + wait
[step] verify
[info] center (32,28) = 0xff5d564c  (R=4c G=56 B=5d)
[info] TL=0x00000000 TR=0x00000000
[info] covered (non-clear) pixels = 338 / 4096
[PASS]

===== RUN #2 (VK_LAYER_KHRONOS_validation) =====
[no validation warnings]
covered = 338   [PASS]

===== STABILITY: 5 reruns =====
covered = 338   [PASS]   x5

7/7 PASS after coverage-range fix.

===== INITIAL FAILURE NOTE =====

First run reported "coverage out of range: 338 (want 800..1600)" — that was a
verification-side arithmetic error on my (claude-noether's) part, not a driver
issue. Triangle area = 0.5 * 0.8 * 0.8 = 0.32 sq units in NDC; viewport area
is 4 sq units, so 8% coverage = ~328 pixels. The driver produced exactly 338,
which matches the expected coverage within edge-rule tolerance.

Substantive PASS criteria (interpolated center color, clear corners) were
satisfied on the first run; only the loose coverage-range check needed
calibration. Fixed in-tree at `iter5/probe_vbo_ubo.c`.

===== KEY OBSERVATIONS =====

1. Vertex input binding works:
     binding 0: stride 32, INPUT_RATE_VERTEX
     attribute 0: R32G32_SFLOAT, offset 0 (pos)
     attribute 1: R32G32B32_SFLOAT, offset 16 (color)
   GPU correctly fetched both attributes from the bound vertex buffer.

2. UBO binding at vertex stage works:
     mat4 transform with scale 0.8 in x/y was correctly applied.
     Triangle vertices at NDC (-0.5,-0.5)/(0.5,-0.5)/(0,0.5) scaled to
     (-0.4,-0.4)/(0.4,-0.4)/(0,0.4) — visible from the 338-pixel coverage
     (matches 0.8-scaled area, NOT unscaled 0.5-scaled area which would be
     ~500 pixels).

3. Varying interpolation works:
     center pixel at (32, 28) has R=0x4c G=0x56 B=0x5d. All three vertex
     colors (red/green/blue) contributed via barycentric interpolation —
     none of the channels are zero, none are saturated, all are in a
     reasonable middle-of-range value.

4. Bifrost vertex-side descriptor model handles UBO + vertex-stage shader
   correctly (the headline hypothesis for this iter — that vertex-stage
   descriptor binding would fail on Bifrost — did not materialize).

5. Deterministic across runs: identical 338 covered pixels each time.

No GPU faults, no validation warnings, all 7 runs identical.
