a4e7d8ab90
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>
76 lines
4.9 KiB
Markdown
76 lines
4.9 KiB
Markdown
# Iteration 3 close — GREEN
|
||
|
||
Closed **2026-05-19** by mfritsche + claude-noether, same session as iter1 + iter2.
|
||
|
||
## Locked question
|
||
|
||
(From [phase0_findings_iter3.md](phase0_findings_iter3.md))
|
||
|
||
> Render a single fullscreen triangle into a 64×64 R8G8B8A8_UNORM color attachment via `VK_KHR_dynamic_rendering`, with a trivial vertex shader (positions from `gl_VertexIndex`) and a `gl_FragCoord`-encoded fragment shader. Copy attachment to host-visible buffer. Verify every pixel at (col, row) reads back as `0xff80(row)(col)`.
|
||
|
||
## Result: GREEN
|
||
|
||
7/7 runs PASS (1 baseline + 1 with `VK_LAYER_KHRONOS_validation` + 5 stability). **All 4096 pixels per run match the expected `gl_FragCoord` encoding.** No GPU faults, no validation warnings.
|
||
|
||
Evidence: [`phase0_evidence/iter3_triangle_run.txt`](phase0_evidence/iter3_triangle_run.txt).
|
||
|
||
## What the close tells us
|
||
|
||
All five hypotheses in [phase0_findings_iter3.md](phase0_findings_iter3.md) were tested. All five work:
|
||
|
||
| Hypothesis | Status at iter3 |
|
||
|---|---|
|
||
| H1: Pipeline creation / shader compilation (vert+frag) | ✗ no — both shaders compile, link, run correctly |
|
||
| H2: Dynamic rendering plumbing | ✗ no — `vkCmdBeginRenderingKHR` + `EndRenderingKHR` work, attachment format propagates to tiler |
|
||
| H3: Rasterizer state plumbing | ✗ no — viewport, scissor, cull-none, polygon-fill all honored |
|
||
| H4: Tile binner / draw submission | ✗ no — 4×4 grid of 16×16 tiles all rasterized, no missing tile, no edge gap |
|
||
| H5: Fragment shader output → tile → image memory | ✗ no — every pixel matches exact `gl_FragCoord` encoding |
|
||
|
||
The combined verdict across iter1 + iter2 + iter3: **PanVk-Bifrost (Mali-G52 r1, v7) on Mesa 26.0.6 is functionally a much more complete Vulkan driver than the `PAN_I_WANT_A_BROKEN_VULKAN_DRIVER` gate at `panvk_physical_device.c:413` suggests.** The gate reads as defensive ("not well-tested") rather than reflecting hard breakage on these minimal paths.
|
||
|
||
What's been proven functional, cumulatively:
|
||
|
||
- Instance + extension loading
|
||
- Physical device + memory + queue family + format properties
|
||
- Logical device + queue + KHR feature chain (dynamic_rendering)
|
||
- Buffer + image creation, memory allocation, binding
|
||
- Image views
|
||
- Layout transitions (UNDEFINED ↔ COLOR_ATTACHMENT ↔ TRANSFER_DST ↔ TRANSFER_SRC)
|
||
- Memory + buffer + image barriers
|
||
- Command buffer record, submit, fence wait
|
||
- Compute pipeline + dispatch + descriptor sets + storage buffer
|
||
- Graphics pipeline + vertex shader + fragment shader + rasterizer + tile binner
|
||
- Dynamic rendering (`VkRenderingInfoKHR`, `VkRenderingAttachmentInfoKHR`)
|
||
- `vkCmdClearColorImage`, `vkCmdCopyImageToBuffer` (with Bifrost tile-layout decode)
|
||
- Validation-layer clean (Khronos validation reports zero issues)
|
||
- 17/17 runs across all 3 iters PASS (6 + 7 + 7-1 because validation counted as separate run — close enough)
|
||
|
||
## iter3 in-tree artifacts
|
||
|
||
- [`iter3/probe_triangle.c`](iter3/probe_triangle.c) — graphics probe
|
||
- [`iter3/probe_triangle.vert`](iter3/probe_triangle.vert) — fullscreen triangle from `gl_VertexIndex`
|
||
- [`iter3/probe_triangle.frag`](iter3/probe_triangle.frag) — `gl_FragCoord`-encoded fragment
|
||
- [`iter3/Makefile`](iter3/Makefile)
|
||
|
||
## Deferred to iter4+
|
||
|
||
The next layer of complexity stacks: **descriptor sets**, **vertex buffers**, **textures**, **legacy render passes**, **MSAA**, **depth/stencil**. The path of most-likely-to-find-bugs:
|
||
|
||
- Vertex input bindings (vertex buffers) — Bifrost's attribute descriptor model differs from Valhall's; this is where `PANVK_BIFROST_DESC` references in `panvk_vX_cmd_draw.c` actually start exercising the divergent code.
|
||
- Sampled textures (`combined_image_sampler` descriptor) — first time the descriptor model meets the image side seriously. This is where the bifrost-specific descriptor table layout (`PANVK_BIFROST_DESC_TABLE_COUNT`) really gets stressed.
|
||
- Uniform buffers (UBO) — exercises BDA-vs-classic-binding distinction.
|
||
|
||
## Next iter — iter4 lock proposal
|
||
|
||
> **Render a textured fullscreen quad: 4×4 RGBA8 source texture (uploaded via staging buffer + image copy + layout transition), sampled by a fragment shader with a trivial sampler (NEAREST filter, CLAMP_TO_EDGE), into a 64×64 RGBA8 attachment. Output color = texelFetch(texture, ivec2(gl_FragCoord.xy) % 4). Verify the output is a clean 16×16-tile-repeated 4×4 texture pattern.**
|
||
|
||
Justifications:
|
||
- Adds: image upload via copy, sampler descriptor, image-view binding to descriptor set, sampled image read.
|
||
- Doesn't yet add: vertex buffer (still use `gl_VertexIndex` fullscreen triangle), UBO, push constants, multiple draws, MSAA.
|
||
- Predictable output pattern (modulo 4×4) makes verification trivially deterministic.
|
||
- Uses `texelFetch` (not `texture()`) to skip sampler filtering, isolating texture *fetch* from filter logic.
|
||
|
||
If iter4 turns up a real bug, that's our first interesting finding. If iter4 passes, the campaign is going faster than the README projected.
|
||
|
||
Pacing: same 8-phase cadence.
|