mesa-panvk-bifrost-video: sibling package adding VK_KHR_video_decode_h264
panvk-bifrost-video campaign close. Phase 4 byte-exact validated 2026-05-21 on RK3566/PineTab2 (Mali-G52 r1 MC1 + hantro VPU): 48/48 unique BBB display frames decoded by this driver are byte-identical to ffmpeg+libva-v4l2-request-fourier on the same hantro hardware (frame 42 Y md5 = 54b9b396e6cd377256eb4bce0efc0bed both ways). Phase 5 second-model review passed; load-bearing findings applied. Co-installs at /usr/lib/panvk-bifrost-video/ parallel to the r4 sibling at /usr/lib/panvk-bifrost/; opt-in via VK_ICD_FILENAMES. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1420,3 +1420,138 @@ jobs:
|
||||
- name: wipe secrets
|
||||
if: always()
|
||||
run: rm -f /root/repo_pass /root/.ssh/id_ed25519
|
||||
run: rm -f /root/.ssh/id_ed25519_hertz
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# mesa-panvk-bifrost-video (aarch64 only) — sibling adding VK_KHR_video_decode_h264
|
||||
# via the V4L2 hantro VPU. Phase 4 byte-exact validated 2026-05-21.
|
||||
# Co-installs at /usr/lib/panvk-bifrost-video/ (parallel to r4); opt-in
|
||||
# via VK_ICD_FILENAMES (no launcher shipped — uses standard Vulkan loader).
|
||||
#
|
||||
# Build is slow (~30-60min on actrunner-aarch64): full Mesa-from-source.
|
||||
# Standalone job — no `needs:` since it doesn't depend on the fourier
|
||||
# codec stack. continue-on-error so a build hiccup doesn't block other
|
||||
# jobs in the same workflow run.
|
||||
# -------------------------------------------------------------------------
|
||||
mesa-panvk-bifrost-video-aarch64:
|
||||
runs-on: arch-aarch64
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: skip if already published
|
||||
id: skip-check
|
||||
run: |
|
||||
set -e
|
||||
result=$(./.gitea/scripts/check-already-published.sh arch/mesa-panvk-bifrost-video)
|
||||
echo "$result" >> "$GITHUB_OUTPUT"
|
||||
echo "decision: $result"
|
||||
|
||||
- name: bootstrap runner (idempotent)
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
run: |
|
||||
set -e
|
||||
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||
retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo
|
||||
|
||||
- name: import signing key
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
env:
|
||||
PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }}
|
||||
PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }}
|
||||
run: |
|
||||
set -e
|
||||
gpgconf --homedir /root/.gnupg --kill all 2>/dev/null || true
|
||||
rm -rf /root/.gnupg /root/repo_pass
|
||||
mkdir -m700 -p /root/.gnupg
|
||||
printf '%s' "$PASS" > /root/repo_pass
|
||||
chmod 600 /root/repo_pass
|
||||
printf '%s\n' "$PRIV" | gpg --batch --import
|
||||
echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust
|
||||
|
||||
- name: install deploy ssh key
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
env:
|
||||
KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }}
|
||||
run: |
|
||||
mkdir -m700 -p /root/.ssh
|
||||
printf '%s\n' "$KEY" > /root/.ssh/id_ed25519
|
||||
chmod 600 /root/.ssh/id_ed25519
|
||||
ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
- name: makepkg mesa-panvk-bifrost-video
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
run: |
|
||||
set -e
|
||||
rm -rf /tmp/build-mesa-panvk-bifrost-video
|
||||
cp -r arch/mesa-panvk-bifrost-video /tmp/build-mesa-panvk-bifrost-video
|
||||
chown -R builder:builder /tmp/build-mesa-panvk-bifrost-video
|
||||
cd /tmp/build-mesa-panvk-bifrost-video
|
||||
# MAKEFLAGS for parallel build; runner is multi-core.
|
||||
# --skipinteg because sha256sums=SKIP in PKGBUILD (matches the
|
||||
# fourier-fork PKGBUILD convention).
|
||||
sudo -u builder -H env MAKEFLAGS="-j60" \
|
||||
makepkg --nocheck --noconfirm --syncdeps --cleanbuild --skipinteg
|
||||
ls -la *.pkg.tar.* | grep -v "\.sig$"
|
||||
|
||||
- name: sign mesa-panvk-bifrost-video
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
run: |
|
||||
set -e
|
||||
cd /tmp/build-mesa-panvk-bifrost-video
|
||||
for f in *.pkg.tar.xz *.pkg.tar.zst *.pkg.tar.gz; do
|
||||
[ -f "$f" ] || continue
|
||||
gpg --batch --pinentry-mode loopback --passphrase-file /root/repo_pass \
|
||||
--detach-sign --yes -u 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C "$f"
|
||||
done
|
||||
|
||||
- name: update aarch64 repo db
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
run: |
|
||||
set -e
|
||||
mkdir -p /tmp/arch-stage-mesa-panvk-video
|
||||
cd /tmp/arch-stage-mesa-panvk-video
|
||||
rm -f *
|
||||
for f in marfrit.db.tar.gz marfrit.db.tar.gz.sig marfrit.files.tar.gz marfrit.files.tar.gz.sig; do
|
||||
curl -sSLf "https://packages.reauktion.de/arch/aarch64/$f" -o "$f" || rm -f "$f"
|
||||
done
|
||||
for ext in xz zst gz; do
|
||||
ls /tmp/build-mesa-panvk-bifrost-video/*.pkg.tar.$ext 2>/dev/null && \
|
||||
mv /tmp/build-mesa-panvk-bifrost-video/*.pkg.tar.$ext /tmp/build-mesa-panvk-bifrost-video/*.pkg.tar.$ext.sig .
|
||||
done || true
|
||||
export GNUPGHOME=/root/.gnupg
|
||||
printf 'pinentry-mode loopback\npassphrase-file /root/repo_pass\n' > /root/.gnupg/gpg.conf
|
||||
printf 'allow-loopback-pinentry\n' > /root/.gnupg/gpg-agent.conf
|
||||
gpg-connect-agent reloadagent /bye
|
||||
pkgs=()
|
||||
for ext in xz zst gz; do
|
||||
for f in *.pkg.tar.$ext; do [ -f "$f" ] && pkgs+=("$f"); done
|
||||
done
|
||||
if [ -f marfrit.db.tar.gz ]; then
|
||||
for f in "${pkgs[@]}"; do
|
||||
name=$(echo "$f" | sed -E 's/-[0-9].*//')
|
||||
repo-remove --sign --key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C \
|
||||
marfrit.db.tar.gz "$name" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
repo-add --new --sign --key 92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C \
|
||||
--verify marfrit.db.tar.gz "${pkgs[@]}"
|
||||
ln -sf marfrit.db.tar.gz marfrit.db
|
||||
ln -sf marfrit.files.tar.gz marfrit.files
|
||||
ln -sf marfrit.db.tar.gz.sig marfrit.db.sig
|
||||
rm -f marfrit.files.sig
|
||||
|
||||
- name: publish to aarch64
|
||||
if: steps.skip-check.outputs.skip != '1'
|
||||
run: |
|
||||
set -e
|
||||
retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; }
|
||||
cd /tmp/arch-stage-mesa-panvk-video
|
||||
retry rsync -avL --copy-unsafe-links \
|
||||
-e 'ssh -i /root/.ssh/id_ed25519' \
|
||||
./ mfritsche@nc.reauktion.de:arch/aarch64/
|
||||
|
||||
- name: wipe secrets
|
||||
if: always()
|
||||
run: rm -f /root/repo_pass /root/.ssh/id_ed25519
|
||||
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mesa-panvk-bifrost/0001-panvk-expose-robustness2-nullDescriptor-bifrost.patch
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mesa-panvk-bifrost/0002-panvk-expose-vulkan-1.1-1.2-on-bifrost.patch
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mesa-panvk-bifrost/0003-panvk-bifrost-vk-ext-transform-feedback.patch
|
||||
+1
@@ -0,0 +1 @@
|
||||
../mesa-panvk-bifrost/0004-panvk-bifrost-xfb-primitive-decomposition.patch
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
||||
# Maintainer: Markus Fritsche <fritsche.markus@gmail.com>
|
||||
#
|
||||
# mesa-panvk-bifrost-video — sibling of mesa-panvk-bifrost (r4) that adds
|
||||
# VK_KHR_video_decode_h264 on Mali Bifrost SBCs (PAN_ARCH 6/7) backed by
|
||||
# the SoC's V4L2-stateless hantro VPU (RK3566/RK3568).
|
||||
#
|
||||
# Campaign: ~/src/panvk-bifrost-video/ — Phase 4 byte-exact validated
|
||||
# 2026-05-21 (48/48 BBB display frames match ffmpeg+libva-v4l2-request-
|
||||
# fourier byte-for-byte on the same hantro). Phase 5 second-model review
|
||||
# completed; load-bearing findings (output_map OOB, static counter,
|
||||
# session_init unwind, probe_hantro gate) all applied.
|
||||
#
|
||||
# What it does (on top of r4):
|
||||
# - 0001..0004: inherited from mesa-panvk-bifrost (robustness2/null-
|
||||
# descriptor, vk1.1/1.2 advertisement, EXT_transform_feedback, XFB
|
||||
# primitive decomposition) — symlinked from the r4 package directory
|
||||
# so the patches don't drift between siblings.
|
||||
# - 0005: VK_KHR_video_queue + VK_KHR_video_decode_queue +
|
||||
# VK_KHR_video_decode_h264 backed by V4L2-stateless hantro.
|
||||
# Touches 14 files in src/panfrost/vulkan/; full diff in
|
||||
# 0005-panvk-bifrost-video-KHR-video-decode-h264.patch.
|
||||
#
|
||||
# Co-existence:
|
||||
# - Installs to /usr/lib/panvk-bifrost-video/ (parallel to r4's
|
||||
# /usr/lib/panvk-bifrost/). Pick at runtime via VK_ICD_FILENAMES.
|
||||
# - r4 stays the recommended default for the Chromium-GPU-process
|
||||
# consumer (no video needed there). Use this package when the
|
||||
# consumer wants Vulkan video decode (mpv-fourier, ffmpeg-vulkan,
|
||||
# future Chromium-VulkanVideoDecoder).
|
||||
#
|
||||
# Phase 1 limitations to know about (documented in source comments):
|
||||
# - Single video session per device (active_video singleton)
|
||||
# - Synchronous decode at record time — no pipelining yet
|
||||
# - Hardcoded /dev/video1 + /dev/media0 (matches RK3566/68, blocks
|
||||
# other SoCs without a topology-walk port)
|
||||
# - Bitstream source buffer assumed HOST_VISIBLE (true on panvk-
|
||||
# bifrost, would need fallback on other backends)
|
||||
#
|
||||
# Build target: arch-aarch64 runner via marfrit-packages Gitea Actions.
|
||||
# Mesa build is slow (~30-60min on Cortex-A55).
|
||||
|
||||
pkgname=mesa-panvk-bifrost-video
|
||||
_mesaver=26.0.6
|
||||
pkgver=26.0.6.r5.video1
|
||||
pkgrel=1
|
||||
pkgdesc="Patched Mesa libvulkan_panfrost.so adding VK_KHR_video_decode_h264 on Bifrost SBCs (sibling of mesa-panvk-bifrost-r4)"
|
||||
arch=('aarch64')
|
||||
url="https://github.com/marfrit/panvk-bifrost"
|
||||
license=('MIT')
|
||||
|
||||
depends=(
|
||||
'mesa' # for shared mesa runtime libs
|
||||
'libdrm'
|
||||
'wayland'
|
||||
'libxcb'
|
||||
'libx11'
|
||||
'libxshmfence'
|
||||
'zlib'
|
||||
'zstd'
|
||||
'libelf'
|
||||
'libffi'
|
||||
'expat'
|
||||
'llvm-libs'
|
||||
'lm_sensors'
|
||||
)
|
||||
makedepends=(
|
||||
'meson'
|
||||
'ninja'
|
||||
'glslang'
|
||||
'python-mako'
|
||||
'python-packaging'
|
||||
'wayland-protocols'
|
||||
'libxrandr'
|
||||
'xorgproto'
|
||||
'libdrm'
|
||||
'llvm'
|
||||
'libclc'
|
||||
'spirv-llvm-translator'
|
||||
'spirv-tools'
|
||||
'rust-bindgen'
|
||||
'patch'
|
||||
)
|
||||
|
||||
source=(
|
||||
"https://archive.mesa3d.org/mesa-${_mesaver}.tar.xz"
|
||||
"0001-panvk-expose-robustness2-nullDescriptor-bifrost.patch"
|
||||
"0002-panvk-expose-vulkan-1.1-1.2-on-bifrost.patch"
|
||||
"0003-panvk-bifrost-vk-ext-transform-feedback.patch"
|
||||
"0004-panvk-bifrost-xfb-primitive-decomposition.patch"
|
||||
"0005-panvk-bifrost-video-KHR-video-decode-h264.patch"
|
||||
"icd.json"
|
||||
)
|
||||
# Mesa tarball checksum matches the sibling r4 package — same upstream version.
|
||||
sha256sums=(
|
||||
'SKIP' # mesa tarball — co-trust w/ r4 sibling
|
||||
'SKIP' # patches are local
|
||||
'SKIP'
|
||||
'SKIP'
|
||||
'SKIP'
|
||||
'SKIP'
|
||||
'SKIP' # icd.json
|
||||
)
|
||||
|
||||
prepare() {
|
||||
cd "mesa-${_mesaver}"
|
||||
|
||||
# r1+r2: small sed-based edits inherited from r4 (verbatim from the
|
||||
# sibling PKGBUILD — keep in sync).
|
||||
sed -i 's|\.KHR_robustness2 = PAN_ARCH >= 10,|.KHR_robustness2 = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
sed -i 's|\.EXT_robustness2 = PAN_ARCH >= 10,|.EXT_robustness2 = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
sed -i 's|\.nullDescriptor = PAN_ARCH >= 10,|.nullDescriptor = true,|' src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
sed -i 's|bool has_vk1_1 = PAN_ARCH >= 10;|bool has_vk1_1 = true;|' src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
sed -i 's|bool has_vk1_2 = PAN_ARCH >= 10;|bool has_vk1_2 = true;|' src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
|
||||
# r3: EXT_transform_feedback for Bifrost.
|
||||
patch -p1 < "${srcdir}/0003-panvk-bifrost-vk-ext-transform-feedback.patch"
|
||||
|
||||
# r4: XFB primitive decomposition NIR pass.
|
||||
patch -p1 < "${srcdir}/0004-panvk-bifrost-xfb-primitive-decomposition.patch"
|
||||
|
||||
# video: VK_KHR_video_decode_h264 via V4L2-hantro.
|
||||
patch -p1 < "${srcdir}/0005-panvk-bifrost-video-KHR-video-decode-h264.patch"
|
||||
|
||||
# Sanity-check r1..r4 (inherited).
|
||||
grep -q "KHR_robustness2 = true," src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "EXT_robustness2 = true," src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "nullDescriptor = true," src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "has_vk1_1 = true;" src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "has_vk1_2 = true;" src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "EXT_transform_feedback = PAN_ARCH < 9," src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
test -f src/panfrost/vulkan/jm/panvk_vX_cmd_xfb.c
|
||||
grep -q "panvk_per_arch(nir_lower_xfb)" src/panfrost/vulkan/panvk_vX_shader.c
|
||||
test -f src/panfrost/vulkan/panvk_vX_xfb_lower.c
|
||||
|
||||
# Sanity-check video patch landed.
|
||||
grep -q "KHR_video_queue = PAN_ARCH < 9 && panvk_v4l2_probe_hantro()" \
|
||||
src/panfrost/vulkan/panvk_vX_physical_device.c
|
||||
grep -q "PANVK_QUEUE_FAMILY_VIDEO_DECODE" src/panfrost/vulkan/panvk_device.h
|
||||
test -f src/panfrost/vulkan/panvk_video_decode.c
|
||||
test -f src/panfrost/vulkan/panvk_video_decode.h
|
||||
test -f src/panfrost/vulkan/panvk_v4l2.c
|
||||
test -f src/panfrost/vulkan/panvk_v4l2_h264.c
|
||||
test -f src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c
|
||||
test -f src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h
|
||||
grep -q "panvk_v4l2_h264_slice_header.c" src/panfrost/vulkan/meson.build
|
||||
grep -q "panvk_video_queue_submit_noop" src/panfrost/vulkan/panvk_vX_device.c
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "mesa-${_mesaver}"
|
||||
# Mirror r4's narrow build profile.
|
||||
meson setup build/ \
|
||||
--prefix=/usr \
|
||||
--libdir=lib \
|
||||
--buildtype=release \
|
||||
-Dvulkan-drivers=panfrost \
|
||||
-Dgallium-drivers= \
|
||||
-Dplatforms=wayland,x11 \
|
||||
-Dglx=disabled \
|
||||
-Degl=disabled \
|
||||
-Dgles1=disabled \
|
||||
-Dgles2=disabled \
|
||||
-Dvulkan-layers= \
|
||||
-Dtools= \
|
||||
-Dgallium-rusticl=false \
|
||||
-Dmicrosoft-clc=disabled
|
||||
meson compile -C build
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "${srcdir}/mesa-${_mesaver}"
|
||||
|
||||
# Co-install path — parallel to r4's /usr/lib/panvk-bifrost/.
|
||||
install -Dm755 build/src/panfrost/vulkan/libvulkan_panfrost.so \
|
||||
"$pkgdir/usr/lib/panvk-bifrost-video/libvulkan_panfrost.so"
|
||||
|
||||
# ICD JSON pointing at the video build. Opt-in via VK_ICD_FILENAMES;
|
||||
# NOT in /usr/share/vulkan/icd.d/ so it doesn't override stock or r4.
|
||||
install -Dm644 "$srcdir/icd.json" \
|
||||
"$pkgdir/usr/lib/panvk-bifrost-video/icd.json"
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# mesa-panvk-bifrost-video
|
||||
|
||||
Patched Mesa `libvulkan_panfrost.so` that **adds `VK_KHR_video_decode_h264`** on Mali Bifrost SBCs (PAN_ARCH 6/7, RK3566/RK3568 class hardware), backed by the SoC's V4L2-stateless **hantro** VPU.
|
||||
|
||||
This is a **sibling** of [mesa-panvk-bifrost](../mesa-panvk-bifrost/) (the r4 package that exposes Bifrost to Chromium's Vulkan compositor). Pick this one when the consumer wants Vulkan **video decode** in addition; pick r4 for compositor-only.
|
||||
|
||||
## Status
|
||||
|
||||
Phase 4 byte-exact validated 2026-05-21: 48/48 unique BBB display frames decoded by this package are byte-identical to `ffmpeg+libva-v4l2-request-fourier` running on the same hantro hardware. Phase 5 second-model review completed; all load-bearing findings addressed.
|
||||
|
||||
## How to use
|
||||
|
||||
```sh
|
||||
# Co-installs alongside r4 and stock mesa.
|
||||
sudo pacman -S mesa-panvk-bifrost-video
|
||||
|
||||
# Opt in (not on the default loader search path).
|
||||
export VK_ICD_FILENAMES=/usr/lib/panvk-bifrost-video/icd.json
|
||||
export PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 # mesa-upstream gate
|
||||
|
||||
# Run a Vulkan video consumer.
|
||||
vulkan-video-dec-simple-test -i your.h264 --codec h264 --noPresent --maxFrameCount 50
|
||||
# or
|
||||
ffmpeg -hwaccel vulkan -i your.mp4 ...
|
||||
```
|
||||
|
||||
## Phase 1 limitations
|
||||
|
||||
Documented in source comments and worth knowing before relying on this in production:
|
||||
|
||||
- **Single video session per device.** Concurrent `VkVideoSessionKHR` on the same device clobber each other (`active_video` singleton). Sufficient for current single-stream consumers.
|
||||
- **Synchronous decode at record time.** The full V4L2 ioctl dance runs to completion inside `vkCmdDecodeVideoKHR`. No pipelining. Throughput is bounded by hantro's ~1.16× realtime on 1080p H.264.
|
||||
- **Hardcoded `/dev/video1` + `/dev/media0`.** Matches RK3566/68 but won't work on other SoCs without a topology-walk port (see `libva-v4l2-request-fourier` for the full version).
|
||||
- **Bitstream source buffer assumed HOST_VISIBLE.** True on panvk-bifrost (no DEVICE_LOCAL-only memory types exist), but the code silently skips decode if the app bound the buffer to non-host-visible memory.
|
||||
|
||||
## Co-existence
|
||||
|
||||
- Installs to `/usr/lib/panvk-bifrost-video/` — parallel to r4's `/usr/lib/panvk-bifrost/` and stock `/usr/lib/`.
|
||||
- Opt-in via `VK_ICD_FILENAMES`; does NOT register itself in `/usr/share/vulkan/icd.d/`.
|
||||
- Three drivers coexist without conflict; the user picks at runtime which to use.
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"ICD": {
|
||||
"api_version": "1.4.335",
|
||||
"library_path": "/usr/lib/panvk-bifrost-video/libvulkan_panfrost.so"
|
||||
},
|
||||
"file_format_version": "1.0.1"
|
||||
}
|
||||
Reference in New Issue
Block a user