initial seed: retrofit campaign lineage from local working trees

panvk-bifrost campaigns (r1..r4 Vulkan compositor + r5.video1 Vulkan
video decode) shipped before this repo existed; the deliverable
patches live in marfrit-packages, but the reasoning chain, phase docs,
and source-state evidence lived only in local working trees on the
development host.

This retrofit imports:
- mesa-panvk-bifrost/   — r1..r4 era phase docs (iter1..iter18)
                          (libmali stub blobs at iter18/blob/ excluded
                          — 109MB of RE artifacts replaced with a README
                          pointer)
- mesa-panvk-bifrost-video/ — sibling campaign phase docs + probe
- evidence/             — frozen .tgz source snapshots at each milestone
                          (basis for the 0005 patch diff generation)

Future iterations should branch off here from day one, so each iter is
a commit rather than a snapshot. See [[feedback-session-local-process-pins]]
for the process drift this retrofit closes.

Total: 1.9 MB across 124 files.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-23 05:25:37 +02:00
parent 430d0da278
commit a4e7d8ab90
124 changed files with 22551 additions and 1 deletions
@@ -0,0 +1,71 @@
# Iteration 2 close — GREEN
Closed **2026-05-19** by mfritsche + claude-noether, same session as iter1 close.
## Locked question
(From [phase0_findings_iter2.md](phase0_findings_iter2.md))
> Get a minimal Vulkan image-side workload to execute end-to-end on PanVk-Bifrost: create a 4×4 `VK_FORMAT_R8G8B8A8_UNORM` image, transition UNDEFINED → TRANSFER_DST, `vkCmdClearColorImage` to 0x11223344, transition TRANSFER_DST → TRANSFER_SRC, `vkCmdCopyImageToBuffer` to host-visible staging, fence-wait, verify all 16 pixels read back as 0x44332211.
## Result: GREEN
7/7 runs PASS (1 baseline + 1 with `VK_LAYER_KHRONOS_validation` + 5 stability). All 16 pixels match exactly. No GPU faults, no MMU faults, no kernel-side panfrost messages, no validation-layer warnings or errors.
Evidence: [`phase0_evidence/iter2_image_clear_run.txt`](phase0_evidence/iter2_image_clear_run.txt).
## What the close tells us
Four image-side hypotheses from [phase0_findings_iter2.md](phase0_findings_iter2.md) were tested. All four work:
| Hypothesis | Status at iter2 |
|---|---|
| H1: image creation + memory binding | ✗ no — `vkCreateImage` + `vkGetImageMemoryRequirements` + bind work for 4×4 RGBA8 optimal-tiled (4096-byte aligned allocation) |
| H2: layout transitions | ✗ no — UNDEFINED→TRANSFER_DST and TRANSFER_DST→TRANSFER_SRC both clean |
| H3: `vkCmdClearColorImage` lowering | ✗ no — clear lands in image correctly |
| H4: `vkCmdCopyImageToBuffer` + Bifrost tile decode | ✗ no — all 16 pixels round-trip with no shuffling, no rounding error |
The image-side transfer path on PanVk-Bifrost is functional for this minimal case. Combined with iter1, we now know the following work end-to-end:
- Vulkan instance + physical device + logical device + queue
- Buffer create + alloc + bind + map (host-visible)
- Image create + alloc + bind (device-local)
- Image layout transitions via `vkCmdPipelineBarrier`
- `vkCmdClearColorImage` (transfer-op level, not via shader)
- `vkCmdCopyImageToBuffer` with Bifrost tile-layout decode
- Compute pipeline: shader module + pipeline layout + compute pipeline + dispatch
- Command buffer recording + submit + fence wait + memory barriers (memory + image + buffer)
What we still **don't know works**: graphics pipeline (vertex + fragment + rasterizer + render pass / dynamic rendering).
## iter2 in-tree artifacts
- [`iter2/probe_image_clear.c`](iter2/probe_image_clear.c) — ~340 LoC, pure Vulkan 1.0 core
- [`iter2/Makefile`](iter2/Makefile) — `make` builds, `make run` / `make run-validation`
## Deferred to iter3+ (not in iter2 scope)
- Vertex + fragment shaders
- Render pass and/or dynamic rendering
- Graphics pipeline state (rasterizer, viewport, blend, depth)
- Larger images, mipmaps, layered images, MSAA
- Other formats (R32G32B32A32_SFLOAT, BC/ETC2/ASTC compressed, depth/stencil)
- WSI / swapchain (iter4+)
- TuxRacer / Zink-on-PanVk
## Next iter — iter3 lock proposal
Smallest viable graphics workload that exercises the **rasterizer + shaders**:
> **Render a single full-screen triangle into a 64×64 R8G8B8A8_UNORM color attachment via dynamic rendering (`VK_KHR_dynamic_rendering`), using a trivial vertex shader (no vertex buffer — emit positions from `gl_VertexIndex`) and a trivial fragment shader (output constant color `gl_FragCoord`-encoded so we can detect rasterizer correctness). Copy attachment to host-visible buffer. Verify: (a) some pixels are written (not all sentinel), (b) at least one pixel has the encoded `gl_FragCoord` value matching its position.**
Justifications:
- 64×64 (not 4×4) so multiple tiles get exercised — Bifrost is a tile-based rasterizer, so single-tile workloads might side-step real tile binning.
- Dynamic rendering instead of render pass — simpler API surface, no framebuffer object, no subpass dependencies. Render pass / framebuffer can be iter3.5 if needed.
- Fullscreen triangle from `gl_VertexIndex` so no vertex buffer needed — exercises pipeline-state but not vertex-input-state.
- Trivial fragment shader (no textures, no UBO, no SSBO) — exercises rasterization + frag shader output but not descriptor lookups (proven in iter1 anyway).
- `gl_FragCoord`-encoded color so a wrong-rasterization bug (e.g. swapped-Y framebuffer convention, off-by-pixel) is detectable from pixel data.
If iter3 turns up the first real failure, that's the campaign's first interesting bug. If iter3 also passes, iter4 adds vertex buffer + UBO + a texture sample, and we're well into "actually exercising PanVk-Bifrost" territory.
Pacing: same 8-phase cadence. iter3 phase 0 substrate lock when the operator opens.