hasvk: Add VK_KHR_video_encode_intra_refresh for gen7.

Each macroblock's intra/inter decision is already made on its own when the
PAK objects are emitted, so refreshing a region is a matter of coding the
macroblocks it covers the way an I slice codes them.  Regions divide the
picture evenly along rows, columns or raster order, which leaves the block,
block-row and block-column modes supported and gives empty regions for free
when the cycle is longer than the split axis.

Two things needed care.  PAK keeps the I slice numbering for MbType5Bits
inside a P slice, where H.264 itself offsets intra mb_types by 5; handing it
the offset value hangs the MFC.  And under constrained intra prediction a
neighbour only counts as available if it is in the refresh region too,
because prediction may not cross into an inter macroblock.

Nothing constrains motion away from not-yet-refreshed regions, which is
sound only because there is no motion estimation: every vector is zero, so a
macroblock reads its own co-located block and never leaves its region.
Motion estimation will have to honour VkVideoReferenceIntraRefreshInfoKHR's
dirty region count.

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.

dEQP-VK.video.encode.h264.intra_refresh_* goes from 44 NotSupported to 12
Pass; all three modes pass in the variants that can run.  The other 32 stop
at a CTS precondition, maxDpbSlots >= GOP frame count, which the driver's
two slots do not meet.  Raising that needs real DPB slot tracking and is
what gates B frames and ffmpeg's encoder too.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
elwrclandClaude Opus 5 committed 2026-08-21 07:35:13 +03:00
1 parent 113661753e
commit 0716678e70
6 files changed
+126 -12

No files matched your search

+28 -4
View File
@@ -222,15 +222,39 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
enc_caps->maxQualityLevels = 1;
enc_caps->encodeInputPictureGranularity.width = ANV_MB_WIDTH;
enc_caps->encodeInputPictureGranularity.height = ANV_MB_HEIGHT;
/* Both flags are required by the ffmpeg h264_vulkan encoder. Note
* that bytes-written currently reports the full dstBufferRange rather
* than the real encoded size; reading back the MFC bit counter is not
* yet implemented. */
/* Bytes written comes from the MFC bitstream byte counter; see the
* feedback query write in anv_h264_encode_video(). */
enc_caps->supportedEncodeFeedbackFlags =
VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR |
VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
}
struct VkVideoEncodeIntraRefreshCapabilitiesKHR *ir_caps =
(struct VkVideoEncodeIntraRefreshCapabilitiesKHR *)
vk_find_struct(pCapabilities->pNext,
VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR);
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.
*/
ir_caps->intraRefreshModes =
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;
/* Down to one region per macroblock at the largest coded extent. */
ir_caps->maxIntraRefreshCycleDuration =
(4096 / ANV_MB_WIDTH) * (4096 / ANV_MB_HEIGHT);
ir_caps->maxIntraRefreshActiveReferencePictures = 1;
/* Regions are macroblock ranges that owe nothing to slice boundaries,
* and a block-based one is not rectangular.
*/
ir_caps->partitionIndependentIntraRefreshRegions = VK_TRUE;
ir_caps->nonRectangularIntraRefreshRegions = VK_TRUE;
}
struct VkVideoEncodeH264CapabilitiesKHR *h264_enc_ext =
(struct VkVideoEncodeH264CapabilitiesKHR *)
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_H264_CAPABILITIES_KHR);