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>
88 lines
5.7 KiB
Markdown
88 lines
5.7 KiB
Markdown
# Phase 0 — substrate for iter4
|
||
|
||
Opened **2026-05-19** after [iter3 close GREEN](phase8_iteration3_close.md).
|
||
|
||
## Locked research question — iter4
|
||
|
||
> **Sample a 4×4 R8G8B8A8_UNORM source texture (uploaded via staging buffer + `vkCmdCopyBufferToImage`) in a fragment shader via `texelFetch(sampler, ivec2(gl_FragCoord.xy) % 4, 0)`, into a 64×64 attachment. Verify every output pixel at (col, row) equals the source texel at (col%4, row%4) — a 16×16-tile-repeated 4×4 pattern.**
|
||
>
|
||
> Source texel encoding: `R = 0x10 + 0x40*x`, `G = 0x10 + 0x40*y`, `B = 0x80`, `A = 0xff` → texel(0,0) = `0xff801010`, texel(3,3) = `0xff80d0d0`. 16 unique values, position-identifiable.
|
||
>
|
||
> If GREEN → iter5 adds vertex buffer or UBO. If RED → first interesting bug, characterize against the Bifrost descriptor model.
|
||
|
||
## Why this shape
|
||
|
||
iter1+2+3 closed the compute, image-side, and graphics-pipeline paths. **iter4 is the first iter that exercises the Bifrost-specific descriptor model** (`PANVK_BIFROST_DESC_TABLE_COUNT`, `bifrost/panvk_vX_meta_desc_copy.c`, `panvk_vX_nir_lower_descriptors.c` Bifrost paths). This is the most-likely-to-find-bugs surface area we've encountered so far.
|
||
|
||
What iter4 adds:
|
||
- Source texture image (SAMPLED|TRANSFER_DST, 4×4 RGBA8)
|
||
- Texture upload via staging buffer + `vkCmdCopyBufferToImage`
|
||
- `VkImageView` on the texture (SHADER_READ layout target)
|
||
- `VkSampler` (NEAREST filter, CLAMP_TO_EDGE — sampler attached for descriptor binding but not exercised by `texelFetch`)
|
||
- Descriptor set layout with COMBINED_IMAGE_SAMPLER binding
|
||
- Descriptor pool + allocate set
|
||
- `vkUpdateDescriptorSets` with image+sampler
|
||
- Pipeline layout with descriptor set layout (non-empty)
|
||
- `vkCmdBindDescriptorSets` for graphics bind point
|
||
- Fragment shader with `texelFetch` from descriptor
|
||
|
||
What iter4 does *not* add: vertex buffer (still fullscreen triangle from `gl_VertexIndex`), UBO, push constants, multiple draws, mipmaps, MSAA, depth/stencil, sampler filtering (NEAREST + texelFetch == no filter), legacy render pass.
|
||
|
||
## Why `texelFetch` and not `texture()`
|
||
|
||
`texture(sampler, uv)` exercises filter logic (bilinear sampling, wrapping). Any bug there could mask whether the underlying *fetch* worked. `texelFetch` skips filtering and addressing — it's a direct memory-coordinate read. Isolates the descriptor model + image read from the sampler-state machinery.
|
||
|
||
If iter4 passes with `texelFetch`, iter5 can add `texture()` to test sampler state separately.
|
||
|
||
## Why 4×4 and not 1×1 or larger
|
||
|
||
- 1×1 would side-step any layout/tiling code in the source texture (single texel fits in one byte position).
|
||
- 4×4 fits in the smallest Mali tile (1×1 tile per Mali's accounting) but still has 16 distinct positions to verify against.
|
||
- Larger (8×8, 16×16, etc.) would add more verification work without exercising different code paths until we hit multi-tile boundaries — that's an iter6+ question.
|
||
|
||
## Hypothesis space — where iter4 may fail first
|
||
|
||
1. **Source texture upload (`vkCmdCopyBufferToImage` to TRANSFER_DST).** First time we go buffer→image (iter2 was image-clear, iter3 was image→buffer). Bifrost's tile-layout transform for *writes* into an optimal-tiled image may have bugs the read path didn't exercise.
|
||
|
||
2. **Layout transition TRANSFER_DST → SHADER_READ_ONLY_OPTIMAL.** New layout never used before. Cache-flush behavior between transfer-write and shader-read on Bifrost is implementation-specific.
|
||
|
||
3. **`VkSampler` creation.** First time. Sampler descriptor layout differs across Mali generations; Bifrost's may have stale fields the v7 path doesn't populate correctly.
|
||
|
||
4. **`VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER` descriptor binding.** This is the **headline hypothesis**. Bifrost's descriptor table model (`PANVK_BIFROST_DESC_TABLE_COUNT`) is structurally different from Valhall's. iter1 used `STORAGE_BUFFER` (a simpler descriptor type), iter3 used no descriptors. This is the first test of the descriptor model on the graphics pipeline.
|
||
|
||
5. **NIR lowering for `texelFetch` on Bifrost.** `panvk_vX_nir_lower_descriptors.c` contains Bifrost-conditional paths (per the iter1 grep). If the lowering for sampled-image fetch on Bifrost is broken, we'll get a compile-time or run-time shader failure.
|
||
|
||
6. **Bifrost sampled-image read instruction emission.** Even with correct lowering, the actual ISA emission for `texelFetch` on Bifrost may have bugs. We can't easily distinguish this from H5 without `RADV_DEBUG=...`-style Mesa env vars (PanVk has `PAN_MESA_DEBUG=trace` etc. — out of scope for iter4 unless we hit a failure).
|
||
|
||
## Phase 0 deliverables
|
||
|
||
- This document.
|
||
- iter4 in scope: the textured-quad probe.
|
||
|
||
## In-scope (LOCKED 2026-05-19 for iter4)
|
||
|
||
- Hardware: ohm only.
|
||
- Source texture: 4×4 R8G8B8A8_UNORM, optimal tiling, SAMPLED|TRANSFER_DST.
|
||
- Sampler: NEAREST filter, CLAMP_TO_EDGE (attached for descriptor; not exercised by texelFetch).
|
||
- Pipeline: 1 descriptor set with 1 COMBINED_IMAGE_SAMPLER binding.
|
||
- Fragment shader: `texelFetch(tex, ivec2(gl_FragCoord.xy) % 4, 0)`.
|
||
- Verify: every pixel matches modulo-4 tile-repeated pattern.
|
||
|
||
## Out-of-scope (LOCKED 2026-05-19 for iter4)
|
||
|
||
- Vertex buffer / vertex input.
|
||
- UBO, SSBO, push constants.
|
||
- Sampler filtering (NEAREST + texelFetch == no filter).
|
||
- Mipmaps, layered textures, depth textures.
|
||
- Legacy render pass.
|
||
- MSAA.
|
||
- Multiple textures / multiple descriptor bindings.
|
||
- Image format other than RGBA8 UNORM.
|
||
- Mesa debug env vars (`PAN_MESA_DEBUG`, etc.) — defer until needed.
|
||
|
||
## Reference
|
||
|
||
- [phase0_findings.md](phase0_findings.md) — campaign substrate.
|
||
- [phase8_iteration{1,2,3}_close.md](phase8_iteration1_close.md) — prior iter closes.
|
||
- Mesa source: `src/panfrost/vulkan/panvk_vX_nir_lower_descriptors.c`, `bifrost/panvk_vX_meta_desc_copy.c`, `panvk_vX_cmd_desc_state.c`.
|