From 7ecbcb3c1bd515e213ce3c41425e1f80c099d681 Mon Sep 17 00:00:00 2001 From: Markus Fritsche Date: Fri, 22 May 2026 10:18:11 +0200 Subject: [PATCH] mesa-panvk-bifrost-video: regenerate 0005 patch from POST-review snapshot The original 0005 patch was generated from the pre-Phase-5-review source snapshot (phase5_review_input_2026-05-21.tgz), missing the four load-bearing review fixes that landed in the post-review snapshot: - probe_hantro gate on KHR_video_* extension advertisement - per-session ts_counter (was process-global static) - panvk_v4l2_session_finish full unwind (munmap + STREAMOFF + REQBUFS=0) - MIN2(rb.count, 18) clamp on num_*_buffers Run #162 (job 17032) failed in prepare() because the PKGBUILD sanity check 'grep -q "KHR_video_queue = PAN_ARCH < 9 && panvk_v4l2_probe_hantro()"' didn't match the actual patched output (which still had the pre-review 'KHR_video_queue = PAN_ARCH < 9,'). This patch (regenerated from phase5_post_review_2026-05-21.tgz) carries all four review fixes. Validated locally: vanilla mesa-26.0.6 + r1..r4 + this patch reproduces prepare()-OK byte-for-byte. Co-Authored-By: Claude Opus 4.7 --- ...-bifrost-video-KHR-video-decode-h264.patch | 157 ++++++++++++++---- 1 file changed, 122 insertions(+), 35 deletions(-) diff --git a/arch/mesa-panvk-bifrost-video/0005-panvk-bifrost-video-KHR-video-decode-h264.patch b/arch/mesa-panvk-bifrost-video/0005-panvk-bifrost-video-KHR-video-decode-h264.patch index e00b3c48a4..c75c692d04 100644 --- a/arch/mesa-panvk-bifrost-video/0005-panvk-bifrost-video-KHR-video-decode-h264.patch +++ b/arch/mesa-panvk-bifrost-video/0005-panvk-bifrost-video-KHR-video-decode-h264.patch @@ -1,6 +1,6 @@ diff -urN a/src/panfrost/vulkan/jm/panvk_cmd_buffer.h b/src/panfrost/vulkan/jm/panvk_cmd_buffer.h --- a/src/panfrost/vulkan/jm/panvk_cmd_buffer.h 2026-05-21 22:46:57.477785029 +0200 -+++ b/src/panfrost/vulkan/jm/panvk_cmd_buffer.h 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/jm/panvk_cmd_buffer.h 2026-05-22 10:17:41.214043265 +0200 @@ -88,8 +88,18 @@ struct panvk_cmd_compute_state compute; struct panvk_push_constant_state push_constants; @@ -22,7 +22,7 @@ diff -urN a/src/panfrost/vulkan/jm/panvk_cmd_buffer.h b/src/panfrost/vulkan/jm/p diff -urN a/src/panfrost/vulkan/meson.build b/src/panfrost/vulkan/meson.build --- a/src/panfrost/vulkan/meson.build 2026-05-21 22:46:59.277811484 +0200 -+++ b/src/panfrost/vulkan/meson.build 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/meson.build 2026-05-22 10:17:41.214043265 +0200 @@ -41,6 +41,10 @@ 'panvk_device_memory.c', 'panvk_host_copy.c', @@ -36,7 +36,7 @@ diff -urN a/src/panfrost/vulkan/meson.build b/src/panfrost/vulkan/meson.build 'panvk_physical_device.c', diff -urN a/src/panfrost/vulkan/panvk_buffer.c b/src/panfrost/vulkan/panvk_buffer.c --- a/src/panfrost/vulkan/panvk_buffer.c 2026-05-21 22:46:57.485785147 +0200 -+++ b/src/panfrost/vulkan/panvk_buffer.c 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_buffer.c 2026-05-22 10:17:41.214043265 +0200 @@ -88,6 +88,8 @@ *bind_status->pResult = VK_SUCCESS; @@ -48,7 +48,7 @@ diff -urN a/src/panfrost/vulkan/panvk_buffer.c b/src/panfrost/vulkan/panvk_buffe } diff -urN a/src/panfrost/vulkan/panvk_buffer.h b/src/panfrost/vulkan/panvk_buffer.h --- a/src/panfrost/vulkan/panvk_buffer.h 2026-05-21 22:46:57.485785147 +0200 -+++ b/src/panfrost/vulkan/panvk_buffer.h 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_buffer.h 2026-05-22 10:17:41.214043265 +0200 @@ -14,8 +14,14 @@ struct panvk_priv_bo; @@ -66,7 +66,7 @@ diff -urN a/src/panfrost/vulkan/panvk_buffer.h b/src/panfrost/vulkan/panvk_buffe VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_buffer, vk.base, VkBuffer, diff -urN a/src/panfrost/vulkan/panvk_device.h b/src/panfrost/vulkan/panvk_device.h --- a/src/panfrost/vulkan/panvk_device.h 2026-05-21 22:46:57.489785206 +0200 -+++ b/src/panfrost/vulkan/panvk_device.h 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_device.h 2026-05-22 10:17:41.214043265 +0200 @@ -45,6 +45,8 @@ enum panvk_queue_family { PANVK_QUEUE_FAMILY_GPU, @@ -102,7 +102,7 @@ diff -urN a/src/panfrost/vulkan/panvk_device.h b/src/panfrost/vulkan/panvk_devic struct { diff -urN a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c --- a/src/panfrost/vulkan/panvk_physical_device.c 2026-05-21 22:46:57.497785323 +0200 -+++ b/src/panfrost/vulkan/panvk_physical_device.c 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_physical_device.c 2026-05-22 10:17:41.214043265 +0200 @@ -577,12 +577,22 @@ .queueFlags = VK_QUEUE_SPARSE_BINDING_BIT, .queueCount = 1, @@ -234,8 +234,8 @@ diff -urN a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/pa +} diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c --- a/src/panfrost/vulkan/panvk_v4l2.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_v4l2.c 2026-05-21 22:47:09.189957157 +0200 -@@ -0,0 +1,569 @@ ++++ b/src/panfrost/vulkan/panvk_v4l2.c 2026-05-22 10:17:41.214043265 +0200 +@@ -0,0 +1,615 @@ +/* + * panvk-bifrost-video Phase 4 commit 3: + * @@ -250,6 +250,7 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c +#include "panvk_video_decode.h" +#include "panvk_device.h" + ++#include "util/macros.h" +#include "vk_alloc.h" +#include "vk_log.h" + @@ -417,7 +418,9 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c + mesa_loge("panvk_v4l2: REQBUFS OUTPUT failed: %s", strerror(errno)); + return -errno; + } -+ vs->num_output_buffers = rb.count; ++ /* REQBUFS may round up the count above the request — clamp to our ++ * fixed-size mmap arrays (Phase 5 review: prevents output_map OOB). */ ++ vs->num_output_buffers = MIN2(rb.count, 18); + vs->output_next = 0; + + /* CAPTURE: MMAP — kernel-allocated, mmap to CPU for copy-out path. */ @@ -430,7 +433,7 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c + mesa_loge("panvk_v4l2: REQBUFS CAPTURE failed: %s", strerror(errno)); + return -errno; + } -+ vs->num_capture_buffers = rb.count; ++ vs->num_capture_buffers = MIN2(rb.count, 18); + vs->capture_next = 0; + + return 0; @@ -788,6 +791,49 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c + struct vk_device *vk_dev, + const VkAllocationCallbacks *alloc) +{ ++ /* Unwind in reverse order of session_init. Each step is guarded by ++ * "have we got far enough to need this" so the function is safe to ++ * call on partially-initialised sessions (the session_init failure ++ * paths jump here via `goto fail`). */ ++ ++ /* munmap CAPTURE + OUTPUT (no-op for entries left at NULL by an ++ * earlier-failed mmap loop). */ ++ for (unsigned i = 0; i < 18; i++) { ++ if (vs->capture_map[i]) { ++ munmap(vs->capture_map[i], vs->capture_map_size[i]); ++ vs->capture_map[i] = NULL; ++ vs->capture_map_size[i] = 0; ++ } ++ if (vs->output_map[i]) { ++ munmap(vs->output_map[i], vs->output_map_size[i]); ++ vs->output_map[i] = NULL; ++ vs->output_map_size[i] = 0; ++ } ++ } ++ ++ if (vs->video_fd >= 0) { ++ /* STREAMOFF (safe to call even if STREAMON never ran — kernel ++ * returns EINVAL which we ignore). */ ++ enum v4l2_buf_type t; ++ t = vs->mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ++ : V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ (void) ioctl(vs->video_fd, VIDIOC_STREAMOFF, &t); ++ t = vs->mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ++ : V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ (void) ioctl(vs->video_fd, VIDIOC_STREAMOFF, &t); ++ ++ /* Release the kernel buffer queues via REQBUFS count=0. */ ++ struct v4l2_requestbuffers rb; ++ memset(&rb, 0, sizeof(rb)); ++ rb.memory = V4L2_MEMORY_MMAP; ++ rb.type = vs->mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ++ : V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ (void) ioctl(vs->video_fd, VIDIOC_REQBUFS, &rb); ++ rb.type = vs->mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ++ : V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ (void) ioctl(vs->video_fd, VIDIOC_REQBUFS, &rb); ++ } ++ + if (vs->request_fds) { + for (unsigned i = 0; i < vs->num_request_fds; i++) + if (vs->request_fds[i] >= 0) @@ -807,7 +853,7 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2.c b/src/panfrost/vulkan/panvk_v4l2.c +} diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264.c b/src/panfrost/vulkan/panvk_v4l2_h264.c --- a/src/panfrost/vulkan/panvk_v4l2_h264.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_v4l2_h264.c 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_v4l2_h264.c 2026-05-22 10:17:41.214043265 +0200 @@ -0,0 +1,478 @@ +/* + * panvk-bifrost-video Phase 4: Vulkan StdVideo H.264 → V4L2 stateless H.264 @@ -1289,7 +1335,7 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264.c b/src/panfrost/vulkan/panvk_v4 +} diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c --- a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c 2026-05-22 10:17:41.214043265 +0200 @@ -0,0 +1,314 @@ +/* + * H.264 slice header bit-parser implementation. @@ -1607,7 +1653,7 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.c b/src/panfrost/vu +} diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h --- a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h 2026-05-22 10:17:41.214043265 +0200 @@ -0,0 +1,94 @@ +/* + * H.264 slice header bit-parser for panvk-bifrost-video / V4L2 stateless @@ -1705,17 +1751,35 @@ diff -urN a/src/panfrost/vulkan/panvk_v4l2_h264_slice_header.h b/src/panfrost/vu +#endif /* PANVK_V4L2_H264_SLICE_HEADER_H */ diff -urN a/src/panfrost/vulkan/panvk_video_decode.c b/src/panfrost/vulkan/panvk_video_decode.c --- a/src/panfrost/vulkan/panvk_video_decode.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_video_decode.c 2026-05-21 22:47:09.189957157 +0200 -@@ -0,0 +1,362 @@ ++++ b/src/panfrost/vulkan/panvk_video_decode.c 2026-05-22 10:17:41.214043265 +0200 +@@ -0,0 +1,380 @@ +/* -+ * panvk-bifrost-video Phase 4 commit 7b: -+ * Vulkan-side decode dispatch wired to V4L2 hantro via dmabuf. ++ * panvk-bifrost-video: Vulkan video decode entrypoints (H.264). + * -+ * Phase 1 simplification: cmd_buffer state tracking via DEVICE-level -+ * active_video struct (under a mutex). Per-cmdbuf state hand-off is -+ * Phase >>1 once arch-agnostic source can access per-arch cmd_buffer -+ * structs without the include-path gymnastics. This works for -+ * single-session decode workloads (mpv, ffmpeg, vk-video-samples). ++ * Drives the V4L2 stateless hantro VPU backend (panvk_v4l2.c) from ++ * Vulkan vkCmdDecodeVideoKHR. Decode is synchronous at record time — ++ * the full V4L2 ioctl dance runs to completion inside the command- ++ * recording call before returning to the application. The queue-side ++ * `driver_submit` is a no-op signal-everything (see panvk_vX_device.c). ++ * ++ * Phase 1 simplifications worth knowing about: ++ * ++ * - Cmd-buffer state lives at the DEVICE level (`active_video`) under ++ * a single mutex, NOT per-cmd-buffer. Concurrent video sessions on ++ * the same device clobber each other. Sufficient for current single- ++ * session consumers (mpv-fourier, ffmpeg-vulkan-h264, vk-video- ++ * samples). Spec-compliant multi-session is a Phase >>1 follow-up. ++ * ++ * - Source bitstream is read via `src_buf->mem->addr.host`, i.e. the ++ * bound VkDeviceMemory's CPU mapping. Works because panvk-bifrost ++ * only exposes HOST_VISIBLE memory types; an app that bound the ++ * bitstream buffer to non-HOST_VISIBLE memory would get a logged ++ * error and a silent decode skip (CmdDecodeVideoKHR is void, so we ++ * have no clean error-return path). VkPhysicalDeviceVideo* ++ * constraints would be the right place to make this contractual. ++ * ++ * - Requires `PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1` (mesa-upstream gate ++ * on panvk-on-Bifrost which is not conformant). + * + * SPDX-License-Identifier: MIT + */ @@ -1929,10 +1993,10 @@ diff -urN a/src/panfrost/vulkan/panvk_video_decode.c b/src/panfrost/vulkan/panvk + * `tv_sec * 1e9 + tv_usec * 1e3`). Sub-microsecond bits are dropped, so + * any high-resolution stamp (e.g. a 64-bit pointer cast) makes the + * lookup miss and P/B frames decode against zero references. Use a -+ * monotonic per-session counter in microseconds (i.e. * 1000 ns). ++ * per-session monotonic counter in microseconds (i.e. * 1000 ns) so ++ * concurrent sessions sharing /dev/video1 don't collide on stamp. + */ -+ static uint32_t panvk_video_ts_counter = 0; -+ const uint64_t output_ts = ((uint64_t)++panvk_video_ts_counter) * 1000ULL; ++ const uint64_t output_ts = ((uint64_t)++vs->ts_counter) * 1000ULL; + uint32_t dst_dpb_slot = pDecodeInfo->pSetupReferenceSlot + ? (uint32_t) pDecodeInfo->pSetupReferenceSlot->slotIndex : 0u; + @@ -2071,8 +2135,8 @@ diff -urN a/src/panfrost/vulkan/panvk_video_decode.c b/src/panfrost/vulkan/panvk +} diff -urN a/src/panfrost/vulkan/panvk_video_decode.h b/src/panfrost/vulkan/panvk_video_decode.h --- a/src/panfrost/vulkan/panvk_video_decode.h 1970-01-01 01:00:00.000000000 +0100 -+++ b/src/panfrost/vulkan/panvk_video_decode.h 2026-05-21 22:47:09.189957157 +0200 -@@ -0,0 +1,114 @@ ++++ b/src/panfrost/vulkan/panvk_video_decode.h 2026-05-22 10:17:41.214043265 +0200 +@@ -0,0 +1,124 @@ +/* + * panvk-bifrost-video Phase 4 commit 3: extended for V4L2 state. + * @@ -2103,12 +2167,22 @@ diff -urN a/src/panfrost/vulkan/panvk_video_decode.h b/src/panfrost/vulkan/panvk + struct v4l2_format fmt_output; + struct v4l2_format fmt_capture; + -+ /* Request fd pool. PANVK_V4L2_REQUEST_FD_COUNT entries. */ ++ /* Request fd pool. PANVK_V4L2_REQUEST_FD_COUNT entries. ++ * Size of request_fd_used[] is bounded by the same compile-time max; ++ * keep them coupled to avoid silent overflow if the pool grows. */ ++#define PANVK_VIDEO_REQUEST_FD_MAX 32 + int *request_fds; -+ bool request_fd_used[32]; /* tracks per-fd "ever queued" → REINIT before reuse */ ++ bool request_fd_used[PANVK_VIDEO_REQUEST_FD_MAX]; + unsigned num_request_fds; + uint32_t request_fd_next; /* round-robin index */ + ++ /* Per-session V4L2 buffer-identity counter. Multiplied by 1000 ns at ++ * QBUF time so the stamp round-trips losslessly through (tv_sec, ++ * tv_usec) — hantro's reflist builder matches dpb[i].reference_ts ++ * against the kernel-side OUTPUT timestamp. Per-session (not process- ++ * global) so concurrent sessions sharing /dev/video1 don't collide. */ ++ uint32_t ts_counter; ++ + /* DPB slotIndex → V4L2 reference_ts mapping (Phase 1 D5) */ + struct { + bool valid; @@ -2189,7 +2263,7 @@ diff -urN a/src/panfrost/vulkan/panvk_video_decode.h b/src/panfrost/vulkan/panvk +#endif /* PANVK_VIDEO_DECODE_H */ diff -urN a/src/panfrost/vulkan/panvk_vX_device.c b/src/panfrost/vulkan/panvk_vX_device.c --- a/src/panfrost/vulkan/panvk_vX_device.c 2026-05-21 22:46:57.505785441 +0200 -+++ b/src/panfrost/vulkan/panvk_vX_device.c 2026-05-21 22:47:09.189957157 +0200 ++++ b/src/panfrost/vulkan/panvk_vX_device.c 2026-05-22 10:17:41.214043265 +0200 @@ -203,6 +203,27 @@ } } @@ -2372,14 +2446,27 @@ diff -urN a/src/panfrost/vulkan/panvk_vX_device.c b/src/panfrost/vulkan/panvk_vX qf->queues = diff -urN a/src/panfrost/vulkan/panvk_vX_physical_device.c b/src/panfrost/vulkan/panvk_vX_physical_device.c --- a/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-21 22:46:59.273811425 +0200 -+++ b/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-21 22:47:09.189957157 +0200 -@@ -170,6 +170,9 @@ ++++ b/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-22 10:17:41.214043265 +0200 +@@ -12,6 +12,7 @@ + #include + + #include "git_sha1.h" ++#include "panvk_video_decode.h" + + #include "vk_android.h" + #include "vk_device.h" +@@ -170,6 +171,14 @@ .EXT_queue_family_foreign = true, .EXT_robustness2 = true, .EXT_transform_feedback = PAN_ARCH < 9, /* iter13: JM-class only for now */ -+ .KHR_video_queue = PAN_ARCH < 9, /* panvk-bifrost-video Phase 4 commit 1 */ -+ .KHR_video_decode_queue = PAN_ARCH < 9, /* hantro V4L2-stateless backend */ -+ .KHR_video_decode_h264 = PAN_ARCH < 9, /* H.264 only initially */ ++ /* Video extensions are advertised only when (a) we're on a Bifrost ++ * arch (PAN_ARCH < 9) AND (b) a hantro VPU is reachable on the ++ * expected V4L2 nodes — otherwise CreateVideoSessionKHR would ++ * succeed at the panvk layer and then fail at v4l2_open_fds, giving ++ * the app a misleading capability claim. */ ++ .KHR_video_queue = PAN_ARCH < 9 && panvk_v4l2_probe_hantro(), ++ .KHR_video_decode_queue = PAN_ARCH < 9 && panvk_v4l2_probe_hantro(), ++ .KHR_video_decode_h264 = PAN_ARCH < 9 && panvk_v4l2_probe_hantro(), .EXT_sampler_filter_minmax = PAN_ARCH >= 10, .EXT_scalar_block_layout = true, .EXT_separate_stencil_usage = true,