# Iteration 9 close — GREEN (3-point check complete) Closed **2026-05-20** by mfritsche + claude-noether. **3-point check** (per [`feedback_package_done_means_installable`](file:///home/mfritsche/.claude/projects/-home-mfritsche-src/memory/feedback_package_done_means_installable.md)) all GREEN: 1. ✅ **PR merged to main** — claude-noether/marfrit-packages PR #40, merged 2026-05-20. 2. ✅ **CI green AND artifact present** — Gitea Actions `mesa-panvk-bifrost-aarch64` job succeeded; `mesa-panvk-bifrost-26.0.6.r2-1-aarch64.pkg.tar.xz` at `packages.reauktion.de/arch/aarch64/`, signed, in marfrit.db index. 3. ✅ **Fresh consumer install + run** — `pacman -Ss mesa-panvk-bifrost` on ohm returns the package via the marfrit repo; `pacman -S mesa-panvk-bifrost` installs cleanly; `brave-vulkan https://www.example.com` launches and operator visually confirmed window appearance. Campaign goal — "make Chromium use the Vulkan renderer for output on Bifrost SBCs" + "recreatable on a fresh image via marfrit-packages" — achieved. ## Known cosmetic / iter10-territory items - **`--disable-gpu-sandbox` warning** at Brave launch. The flag is load-bearing for our setup right now — without it, the GPU sandbox filters out `VK_ICD_FILENAMES` and the GPU process falls back to stock Mesa. Two cleanup paths for iter10: - Install lib+ICD at the default loader path (preempt stock Mesa); no env override needed; no sandbox bypass needed. Risk: conflicts with stock mesa, requires care. - Investigate `--vulkan-icd-filename` or equivalent Chromium flag (if it exists in 147). - **WebGL in-page** still doesn't work — `VK_EXT_transform_feedback` unsupported by PanVk-Bifrost; ANGLE can't expose GLES3. Browser chrome + standard rendering work fine. - **VAAPI** `vaInitialize failed: unknown libva error` during GPU startup — separate concern; libva-multiplanar territory. - **`sha256sums=SKIP`** in PKGBUILD — tighten in iter10 by pinning the Mesa tarball hash. ## Locked question > Brave/Chromium GPU process boots against PanVk-Bifrost (Mali-G52 r1 MC1, PineTab2/RK3566) via Vulkan output. Browser window renders successfully — side-stepping the GL stack failures documented in README's "Consumer-side benefit" section. ## Result: GREEN **Operator visual confirmation, 2026-05-20: "Window came up."** This is the first time stock Brave has rendered a window on PineTab2 in this campaign — and (per the README discovery context) the first time it would have done so on Bifrost SBCs at all without the GL-stack workarounds the parallel `chromium-fourier` campaign was carrying. ## What works Stack-up: - Mesa 26.0.6 panfrost vulkan driver, **patched twice**: - iter8 patch: expose `VK_KHR/EXT_robustness2` + `nullDescriptor` feature on Bifrost (PAN_ARCH 6/7). - iter9 patch: `has_vk1_1 = true`, `has_vk1_2 = true` for Bifrost. - Runtime env: `PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1` + `MESA_VK_VERSION_OVERRIDE=1.2` (bypasses `get_api_version`'s `PAN_ARCH >= 10` hardcode at runtime; cleaner than another patch). - Patched lib installed under `LD_LIBRARY_PATH` pattern at `/home/mfritsche/panvk-patched-libs/libvulkan_panfrost.so` with custom `panfrost_icd_patched.json`. - Brave flags: `--use-gl=disabled --enable-features=Vulkan --use-vulkan=native --ozone-platform=x11 --no-sandbox --disable-gpu-sandbox --ignore-gpu-blocklist`. The runtime signals all line up: - PanVk "not a conformant" warning fires **once** per GPU process startup (previously: 10× = 5 crash-retries). - No `Exiting GPU process due to errors during initialization`. - No `GLES3 is unsupported` (the README's documented symptom). - No `eglCreateContext ES 3.0 failed`. - No `ANGLE Requires a minimum Vulkan device version of 1.1`. - Single benign sandbox warning (`InitializeSandbox() called with multiple threads in process gpu-process`). - No panfrost / mali / GPU faults in `dmesg` during sustained runs. - 60+ second runs without crashes. - Brave window appears on PineTab2 and renders. ## The failure chain that led to the solution Each iteration of debugging stripped one constraint: | Run | Brave saw | Blocker | Fix | |---|---|---|---| | 1 | iter8-patched lib, default flags | Various downstream errors | Need explicit Vulkan flags | | 2 | `--enable-features=Vulkan --use-vulkan=native --ozone-platform=wayland` | `'--ozone-platform=wayland' is not compatible with Vulkan` (Chromium's message) | Switch to `--ozone-platform=x11` (XWayland) | | 3 | + `--ozone-platform=x11` | `GLES3 is unsupported` (the README symptom) | ANGLE's Vulkan backend not engaging | | 4 | + `--use-gl=angle --use-angle=vulkan` | `ANGLE Requires a minimum Vulkan device version of 1.1` | Need PanVk apiVersion ≥ 1.1 | | 5 | + iter9 patch (has_vk1_1/2 = true) | apiVersion still 1.0 (`has_vk1_x` only controls extensions, not version) | Need to override `get_api_version()` | | 6 | + `MESA_VK_VERSION_OVERRIDE=1.2` | ANGLE init OK, but EGL ES 3.0 context fails (`EGL_BAD_ATTRIBUTE`) | PanVk-Bifrost lacks `VK_EXT_transform_feedback` ⇒ ANGLE can't expose GLES3 | | 7 | + `--use-gl=disabled` | 🎯 **GPU process boots, browser window renders.** | (skip GLES3 info collection entirely; Vulkan compositor is enough for browser chrome rendering) | The campaign value-add: the iter8+iter9 patches make PanVk-Bifrost *Brave-compatible* without modifying Brave or ANGLE. The single-knob runtime override (`MESA_VK_VERSION_OVERRIDE`) avoids a third patch. The `--use-gl=disabled` flag is a Chromium-side workaround that's safe because Brave's compositor uses Vulkan directly anyway. ## What's still unknown / out of scope - **WebGL / WebGL2**: still blocked by ANGLE needing GLES3 (which needs transform feedback, which PanVk-Bifrost doesn't have). Sites using WebGL will likely degrade or refuse. Browser chrome itself renders fine; this gap affects in-page content only. - **chrome://gpu state**: not captured yet — would tell us exactly what Brave thinks of GPU capabilities. - **Sustained navigation testing**: only `https://www.example.com` tested. Heavier pages (JS-heavy, video, CSS animations) untested. - **VAAPI codec**: `vaInitialize failed: unknown libva error` during GPU startup. Separate from the Vulkan compositor; means hardware video decode is unavailable, software decode would be used. Could be addressed by libva-multiplanar campaign carry. - **Skia Graphite vs classic Vulkan**: which Skia backend engaged? Logs don't say. Both work; not material to the boot-success question. - **Conformance / production-readiness**: the patches advertise features (robustness2 nullDescriptor, Vulkan 1.1/1.2) without comprehensive testing of every corner. iter4–6 covered the basics; full conformance is years of work. - **Upstream submission**: per `feedback_no_upstream` (libva-multiplanar memory) — out of scope. ## Cumulative state — nine iters, ~50 runs, one operator-confirmed end-user breakthrough | Iter | Result | Signal | |---|---|---| | 1 | GREEN | minimal compute on PanVk-Bifrost | | 2 | GREEN | image clear + transfer + tile decode | | 3 | GREEN | dynamic rendering + tile binner + fullscreen triangle | | 4 | GREEN | sampled texture + descriptor model | | 5 | GREEN | vertex buffer + UBO + interpolation | | 6 | GREEN | depth test + multi-draw | | 7 | GREEN | vkcube real workload (visible) | | 8 | GREEN (under-scoped patch sufficient, A-step deferred) | Zink loaded; glxgears 250 FPS | | **9** | **GREEN (operator visually confirmed)** | **Brave GPU process boots via Vulkan on PanVk-Bifrost; browser window renders** | ## iter9 in-tree artifacts - [`phase0_findings_iter7.md`](phase0_findings_iter7.md), [`phase0_findings_iter8.md`](phase0_findings_iter8.md) — substrate that led into iter9 (no separate iter9 substrate doc was written; iter9 emerged from the goal pivot). - [`iter9/patches/0001-panvk-expose-vulkan-1.1-1.2-on-bifrost.patch`](iter9/patches/0001-panvk-expose-vulkan-1.1-1.2-on-bifrost.patch) — the version-flag patch (stacks on iter8's robustness2 patch). - [`phase0_evidence/iter9_brave_vulkan_breakthrough.txt`](phase0_evidence/iter9_brave_vulkan_breakthrough.txt) — full debugging trace + the winning combo documented step-by-step. - This close artifact. ## Packaging work landed in this same iter After the visual-confirmation milestone, the operator pointed at the src-wide rule: **goal not reached by manually making one device work; goal reached when fresh image can install via marfrit-packages.** In response, this iter's packaging output lives at: - [`~/src/marfrit-packages/arch/mesa-panvk-bifrost/PKGBUILD`](file:///home/mfritsche/src/marfrit-packages/arch/mesa-panvk-bifrost/PKGBUILD) — sed-based patch application + minimal Mesa build, co-installs at `/usr/lib/panvk-bifrost/` so stock mesa stays untouched. - [`~/src/marfrit-packages/arch/mesa-panvk-bifrost/brave-vulkan`](file:///home/mfritsche/src/marfrit-packages/arch/mesa-panvk-bifrost/brave-vulkan) — launcher script wiring env + Brave flags. - [`~/src/marfrit-packages/arch/mesa-panvk-bifrost/icd.json`](file:///home/mfritsche/src/marfrit-packages/arch/mesa-panvk-bifrost/icd.json) — Vulkan ICD JSON pointing at the patched .so at the custom path (NOT under `/usr/share/vulkan/icd.d/` so the stock loader doesn't pick it up — opt-in via `VK_ICD_FILENAMES`). - [`~/src/marfrit-packages/arch/mesa-panvk-bifrost/README.md`](file:///home/mfritsche/src/marfrit-packages/arch/mesa-panvk-bifrost/README.md) — consumer install + use docs. - [`~/src/marfrit-packages/arch/mesa-panvk-bifrost/0001-*.patch`](file:///home/mfritsche/src/marfrit-packages/arch/mesa-panvk-bifrost/0001-panvk-expose-robustness2-nullDescriptor-bifrost.patch) + `0002-*.patch` — the iter8 + iter9 patches. - New Gitea Actions job `mesa-panvk-bifrost-aarch64` appended to `.gitea/workflows/build.yml` — patterned on `libva-v4l2-request-fourier-aarch64`. ## The actual close criterion — 3-point check Per [feedback_package_done_means_installable](file:///home/mfritsche/.claude/projects/-home-mfritsche-src/memory/feedback_package_done_means_installable.md): 1. **PR merged** to `marfrit-packages` (commit on main, since the repo is a single-branch operator workflow). 2. **CI green** AND `packages.reauktion.de/arch/aarch64/mesa-panvk-bifrost-*.pkg.tar.zst` exists. 3. **`pacman -Ss mesa-panvk-bifrost`** on a fresh consumer host returns the package AND `brave-vulkan` launches successfully (operator visual). iter9 closes when all three pass. ## Next steps 1. **Operator reviews** the PKGBUILD + workflow + supporting files. 2. **Commit + push** to marfrit-packages (operator-owned action). 3. **Watch Gitea CI** — Mesa build is slow on aarch64 (~30-60 min). 4. **Verify artifact** lands on `packages.reauktion.de/arch/aarch64/`. 5. **Test on ohm** (or a fresh ohm-equivalent): `pacman -Sy && pacman -S mesa-panvk-bifrost && brave-vulkan https://www.example.com`. Operator visually confirms. Optionally after iter9 actually closes: - **iter10**: sustained navigation + `chrome://gpu` state capture under the packaged install. - **README update** marking the milestone in the campaign charter. - **Pursue `VK_EXT_transform_feedback` in PanVk-Bifrost** to unlock WebGL via ANGLE-GLES3. Significant Bifrost RE work, months. Out of scope unless re-opened.