hasvk: Partition the picture across slices instead of reading first_mb_in_slice.

Splitting a picture into slices is the implementation's job.  The encoder
instead read first_mb_in_slice out of each entry's slice header and used the
next entry's value as the end of the range, but clients leave that field at
zero on every entry and expect the driver to derive it and write it into the
emitted header.  A multi-slice picture therefore came out as one slice
covering nothing, and vkCmdEncodeVideoKHR failed.

Divide the macroblock rows evenly across the NALU slice entries, which keeps
every slice row-aligned as required while
VK_VIDEO_ENCODE_H264_CAPABILITY_ROW_UNALIGNED_SLICE_BIT_KHR is not
advertised, and reject more slices than there are rows.

This also removes the workaround for ffmpeg passing first_mb_in_slice=1,
which was not a client bug at all: the field was never an input.

Per-picture-partition intra refresh needs nothing beyond this, since the
refreshed partition is just a slice the client marks as an I slice and slices
are already coded by their own slice_type, so offer that mode too.

dEQP-VK.video.encode.h264 goes from 76 to 84 of 120.  The remaining 36 are
honest: quantization maps have no hardware path on gen7, where the only
per-macroblock QP is the one the CPU writes into the PAK object and the only
indirect data a PAK object fetches is motion vectors; B frames and rate
control are not implemented.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
elwrclandClaude Opus 5 committed 2026-08-21 08:06:31 +03:00
1 parent 9cb5c4385b
commit e7142772a7
2 files changed
+17 -28

No files matched your search

+4 -3
View File
@@ -237,11 +237,12 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
if (ir_caps) {
/* Each macroblock's intra/inter decision is made on its own when the
* PAK objects are emitted, so the picture can be split along any of
* these axes. Per-picture-partition mode is not offered: it wants the
* refreshed slice coded as an I slice, header included, rather than as
* intra macroblocks inside a P slice.
* these axes. Per-picture-partition mode needs nothing extra: the
* refreshed partition is a slice the client marks as an I slice, and
* slices are already coded according to their own slice_type.
*/
ir_caps->intraRefreshModes =
VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_PER_PICTURE_PARTITION_BIT_KHR |
VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_BASED_BIT_KHR |
VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_ROW_BASED_BIT_KHR |
VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_COLUMN_BASED_BIT_KHR;