Merge pull request 'mesa-panvk-bifrost-video: regenerate 0005 patch from POST-review snapshot' (#84) from claude-noether/marfrit-packages:noether/mesa-panvk-bifrost-video-retrigger into main
build and publish packages / distcc-avahi-aarch64 (push) Successful in 4s
build and publish packages / mesa-panvk-bifrost-aarch64 (push) Successful in 4s
build and publish packages / mesa-panvk-bifrost-video-aarch64 (push) Successful in 5m35s
build and publish packages / lmcp-any (push) Successful in 4s
build and publish packages / lmcp-debian (push) Successful in 4s
build and publish packages / claude-his-any (push) Successful in 4s
build and publish packages / ffmpeg-v4l2-request-aarch64 (push) Successful in 3s
build and publish packages / claude-his-debian (push) Successful in 3s
build and publish packages / ffmpeg-v4l2-request-debian (push) Successful in 3s
build and publish packages / libva-v4l2-request-fourier-aarch64 (push) Successful in 3s
build and publish packages / daedalus-v4l2-debian (push) Successful in 3s
build and publish packages / mpv-fourier-aarch64 (push) Successful in 4s
build and publish packages / libva-v4l2-request-fourier-debian (push) Successful in 3s
build and publish packages / daedalus-v4l2-dkms-debian (push) Successful in 3s
build and publish packages / mpv-fourier-debian (push) Successful in 3s

Reviewed-on: #84
This commit was merged in pull request #84.
This commit is contained in:
2026-05-22 08:20:34 +00:00
@@ -1,6 +1,6 @@
diff -urN a/src/panfrost/vulkan/jm/panvk_cmd_buffer.h b/src/panfrost/vulkan/jm/panvk_cmd_buffer.h 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 --- 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 @@ @@ -88,8 +88,18 @@
struct panvk_cmd_compute_state compute; struct panvk_cmd_compute_state compute;
struct panvk_push_constant_state push_constants; 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 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 --- 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 @@ @@ -41,6 +41,10 @@
'panvk_device_memory.c', 'panvk_device_memory.c',
'panvk_host_copy.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', 'panvk_physical_device.c',
diff -urN a/src/panfrost/vulkan/panvk_buffer.c b/src/panfrost/vulkan/panvk_buffer.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 --- 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 @@ @@ -88,6 +88,8 @@
*bind_status->pResult = VK_SUCCESS; *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 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 --- 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 @@ @@ -14,8 +14,14 @@
struct panvk_priv_bo; 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, 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 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 --- 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 @@ @@ -45,6 +45,8 @@
enum panvk_queue_family { enum panvk_queue_family {
PANVK_QUEUE_FAMILY_GPU, PANVK_QUEUE_FAMILY_GPU,
@@ -102,7 +102,7 @@ diff -urN a/src/panfrost/vulkan/panvk_device.h b/src/panfrost/vulkan/panvk_devic
struct { struct {
diff -urN a/src/panfrost/vulkan/panvk_physical_device.c b/src/panfrost/vulkan/panvk_physical_device.c 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 --- 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 @@ @@ -577,12 +577,22 @@
.queueFlags = VK_QUEUE_SPARSE_BINDING_BIT, .queueFlags = VK_QUEUE_SPARSE_BINDING_BIT,
.queueCount = 1, .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 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 --- 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 +++ b/src/panfrost/vulkan/panvk_v4l2.c 2026-05-22 10:17:41.214043265 +0200
@@ -0,0 +1,569 @@ @@ -0,0 +1,615 @@
+/* +/*
+ * panvk-bifrost-video Phase 4 commit 3: + * 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_video_decode.h"
+#include "panvk_device.h" +#include "panvk_device.h"
+ +
+#include "util/macros.h"
+#include "vk_alloc.h" +#include "vk_alloc.h"
+#include "vk_log.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)); + mesa_loge("panvk_v4l2: REQBUFS OUTPUT failed: %s", strerror(errno));
+ return -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; + vs->output_next = 0;
+ +
+ /* CAPTURE: MMAP — kernel-allocated, mmap to CPU for copy-out path. */ + /* 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)); + mesa_loge("panvk_v4l2: REQBUFS CAPTURE failed: %s", strerror(errno));
+ return -errno; + return -errno;
+ } + }
+ vs->num_capture_buffers = rb.count; + vs->num_capture_buffers = MIN2(rb.count, 18);
+ vs->capture_next = 0; + vs->capture_next = 0;
+ +
+ return 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, + struct vk_device *vk_dev,
+ const VkAllocationCallbacks *alloc) + 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) { + if (vs->request_fds) {
+ for (unsigned i = 0; i < vs->num_request_fds; i++) + for (unsigned i = 0; i < vs->num_request_fds; i++)
+ if (vs->request_fds[i] >= 0) + 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 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 --- 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 @@ @@ -0,0 +1,478 @@
+/* +/*
+ * panvk-bifrost-video Phase 4: Vulkan StdVideo H.264 → V4L2 stateless H.264 + * 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 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 --- 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 @@ @@ -0,0 +1,314 @@
+/* +/*
+ * H.264 slice header bit-parser implementation. + * 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 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 --- 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 @@ @@ -0,0 +1,94 @@
+/* +/*
+ * H.264 slice header bit-parser for panvk-bifrost-video / V4L2 stateless + * 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 */ +#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 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 --- 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 +++ b/src/panfrost/vulkan/panvk_video_decode.c 2026-05-22 10:17:41.214043265 +0200
@@ -0,0 +1,362 @@ @@ -0,0 +1,380 @@
+/* +/*
+ * panvk-bifrost-video Phase 4 commit 7b: + * panvk-bifrost-video: Vulkan video decode entrypoints (H.264).
+ * Vulkan-side decode dispatch wired to V4L2 hantro via dmabuf.
+ * + *
+ * Phase 1 simplification: cmd_buffer state tracking via DEVICE-level + * Drives the V4L2 stateless hantro VPU backend (panvk_v4l2.c) from
+ * active_video struct (under a mutex). Per-cmdbuf state hand-off is + * Vulkan vkCmdDecodeVideoKHR. Decode is synchronous at record time —
+ * Phase >>1 once arch-agnostic source can access per-arch cmd_buffer + * the full V4L2 ioctl dance runs to completion inside the command-
+ * structs without the include-path gymnastics. This works for + * recording call before returning to the application. The queue-side
+ * single-session decode workloads (mpv, ffmpeg, vk-video-samples). + * `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 + * 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 + * `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 + * 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 + * 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)++vs->ts_counter) * 1000ULL;
+ const uint64_t output_ts = ((uint64_t)++panvk_video_ts_counter) * 1000ULL;
+ uint32_t dst_dpb_slot = pDecodeInfo->pSetupReferenceSlot + uint32_t dst_dpb_slot = pDecodeInfo->pSetupReferenceSlot
+ ? (uint32_t) pDecodeInfo->pSetupReferenceSlot->slotIndex : 0u; + ? (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 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 --- 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 +++ b/src/panfrost/vulkan/panvk_video_decode.h 2026-05-22 10:17:41.214043265 +0200
@@ -0,0 +1,114 @@ @@ -0,0 +1,124 @@
+/* +/*
+ * panvk-bifrost-video Phase 4 commit 3: extended for V4L2 state. + * 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_output;
+ struct v4l2_format fmt_capture; + 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; + 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; + unsigned num_request_fds;
+ uint32_t request_fd_next; /* round-robin index */ + 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) */ + /* DPB slotIndex → V4L2 reference_ts mapping (Phase 1 D5) */
+ struct { + struct {
+ bool valid; + 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 */ +#endif /* PANVK_VIDEO_DECODE_H */
diff -urN a/src/panfrost/vulkan/panvk_vX_device.c b/src/panfrost/vulkan/panvk_vX_device.c 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 --- 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 @@ @@ -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 = qf->queues =
diff -urN a/src/panfrost/vulkan/panvk_vX_physical_device.c b/src/panfrost/vulkan/panvk_vX_physical_device.c 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 --- 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 +++ b/src/panfrost/vulkan/panvk_vX_physical_device.c 2026-05-22 10:17:41.214043265 +0200
@@ -170,6 +170,9 @@ @@ -12,6 +12,7 @@
#include <sys/sysmacros.h>
#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_queue_family_foreign = true,
.EXT_robustness2 = true, .EXT_robustness2 = true,
.EXT_transform_feedback = PAN_ARCH < 9, /* iter13: JM-class only for now */ .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 */ + /* Video extensions are advertised only when (a) we're on a Bifrost
+ .KHR_video_decode_queue = PAN_ARCH < 9, /* hantro V4L2-stateless backend */ + * arch (PAN_ARCH < 9) AND (b) a hantro VPU is reachable on the
+ .KHR_video_decode_h264 = PAN_ARCH < 9, /* H.264 only initially */ + * 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_sampler_filter_minmax = PAN_ARCH >= 10,
.EXT_scalar_block_layout = true, .EXT_scalar_block_layout = true,
.EXT_separate_stencil_usage = true, .EXT_separate_stencil_usage = true,