radv/video: Add support for VK_KHR_video_encode_intra_refresh

Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36718>
This commit is contained in:
David Rosca 2025-08-11 13:22:50 +02:00 committed by Marge Bot
parent c1610da677
commit f4808ea46f
4 changed files with 65 additions and 5 deletions

View file

@ -5,3 +5,4 @@ GL_KHR_robustness on v3d
VK_ARM_shader_core_builtins on panvk
VK_KHR_shader_untyped_pointers on anv
cl_ext_immutable_memory_objects
VK_KHR_video_encode_intra_refresh on radv

View file

@ -654,6 +654,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device
.KHR_video_encode_h265 = VIDEO_CODEC_H265ENC && pdev->video_encode_enabled,
.KHR_video_encode_av1 =
(radv_video_encode_av1_supported(pdev) && VIDEO_CODEC_AV1ENC && pdev->video_encode_enabled),
.KHR_video_encode_intra_refresh = pdev->video_encode_enabled,
.KHR_video_encode_queue = pdev->video_encode_enabled,
.KHR_vulkan_memory_model = true,
.KHR_workgroup_memory_explicit_layout = true,
@ -1382,6 +1383,9 @@ radv_physical_device_get_features(const struct radv_physical_device *pdev, struc
/* VK_KHR_present_wait2 */
.presentWait2 = true,
/* VK_KHR_video_encode_intra_refresh */
.videoEncodeIntraRefresh = true,
};
}

View file

@ -871,6 +871,8 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
} else {
enc_caps =
(struct VkVideoEncodeCapabilitiesKHR *)vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_CAPABILITIES_KHR);
struct VkVideoEncodeIntraRefreshCapabilitiesKHR *intra_refresh_caps =
vk_find_struct(pCapabilities->pNext, VIDEO_ENCODE_INTRA_REFRESH_CAPABILITIES_KHR);
if (enc_caps) {
enc_caps->flags = 0;
@ -884,6 +886,15 @@ radv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, cons
enc_caps->supportedEncodeFeedbackFlags = VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BUFFER_OFFSET_BIT_KHR |
VK_VIDEO_ENCODE_FEEDBACK_BITSTREAM_BYTES_WRITTEN_BIT_KHR;
}
if (intra_refresh_caps) {
intra_refresh_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;
intra_refresh_caps->maxIntraRefreshCycleDuration = 256;
intra_refresh_caps->maxIntraRefreshActiveReferencePictures = 1;
intra_refresh_caps->partitionIndependentIntraRefreshRegions = true;
intra_refresh_caps->nonRectangularIntraRefreshRegions = false;
}
pCapabilities->minBitstreamBufferOffsetAlignment = 256;
pCapabilities->minBitstreamBufferSizeAlignment = 8;
if (pdev->info.vcn_ip_version >= VCN_5_0_0)

View file

@ -1651,15 +1651,59 @@ radv_enc_feedback(struct radv_cmd_buffer *cmd_buffer, uint64_t feedback_query_va
}
static void
radv_enc_intra_refresh(struct radv_cmd_buffer *cmd_buffer)
radv_enc_intra_refresh(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInfoKHR *enc_info)
{
struct radv_device *device = radv_cmd_buffer_device(cmd_buffer);
const struct radv_physical_device *pdev = radv_device_physical(device);
struct radv_video_session *vid = cmd_buffer->video.vid;
const struct VkVideoEncodeIntraRefreshInfoKHR *intra_refresh =
vk_find_struct_const(enc_info->pNext, VIDEO_ENCODE_INTRA_REFRESH_INFO_KHR);
RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.intra_refresh);
RADEON_ENC_CS(0); // intra refresh mode
RADEON_ENC_CS(0); // intra ref offset
RADEON_ENC_CS(0); // intra region size
if (enc_info->flags & VK_VIDEO_ENCODE_INTRA_REFRESH_BIT_KHR && intra_refresh) {
const uint32_t block_size = vid->vk.op == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR ? 16 : 64;
uint32_t size_in_blocks = 0;
bool overlap = true;
if (vid->vk.op == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) {
const struct VkVideoEncodeH264PictureInfoKHR *h264_picture_info =
vk_find_struct_const(enc_info->pNext, VIDEO_ENCODE_H264_PICTURE_INFO_KHR);
const VkVideoEncodeH264NaluSliceInfoKHR *h264_slice = &h264_picture_info->pNaluSliceEntries[0];
const StdVideoEncodeH264SliceHeader *slice = h264_slice->pStdSliceHeader;
overlap = slice->disable_deblocking_filter_idc != STD_VIDEO_H264_DISABLE_DEBLOCKING_FILTER_IDC_DISABLED;
} else if (vid->vk.op == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) {
const struct VkVideoEncodeH265PictureInfoKHR *h265_picture_info =
vk_find_struct_const(enc_info->pNext, VIDEO_ENCODE_H265_PICTURE_INFO_KHR);
const VkVideoEncodeH265NaluSliceSegmentInfoKHR *h265_slice = &h265_picture_info->pNaluSliceSegmentEntries[0];
const StdVideoEncodeH265SliceSegmentHeader *slice = h265_slice->pStdSliceSegmentHeader;
overlap = slice->flags.slice_deblocking_filter_disabled_flag == 0;
} /* AV1 always needs overlap */
switch (vid->vk.intra_refresh_mode) {
case VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_BASED_BIT_KHR:
case VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_ROW_BASED_BIT_KHR:
size_in_blocks = DIV_ROUND_UP(enc_info->srcPictureResource.codedExtent.height, block_size);
RADEON_ENC_CS(RENCODE_INTRA_REFRESH_MODE_CTB_MB_ROWS);
break;
case VK_VIDEO_ENCODE_INTRA_REFRESH_MODE_BLOCK_COLUMN_BASED_BIT_KHR:
size_in_blocks = DIV_ROUND_UP(enc_info->srcPictureResource.codedExtent.width, block_size);
RADEON_ENC_CS(RENCODE_INTRA_REFRESH_MODE_CTB_MB_COLUMNS);
break;
default:
assert(0);
break;
}
const uint32_t region_size = DIV_ROUND_UP(size_in_blocks, intra_refresh->intraRefreshCycleDuration);
RADEON_ENC_CS(region_size * intra_refresh->intraRefreshIndex);
RADEON_ENC_CS(region_size + (overlap ? 1 : 0));
} else {
RADEON_ENC_CS(0);
RADEON_ENC_CS(0);
RADEON_ENC_CS(0);
}
RADEON_ENC_END();
}
@ -2731,7 +2775,7 @@ radv_vcn_encode_video(struct radv_cmd_buffer *cmd_buffer, const VkVideoEncodeInf
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2) {
}
// intra_refresh
radv_enc_intra_refresh(cmd_buffer);
radv_enc_intra_refresh(cmd_buffer, enc_info);
// v2 input format
if (pdev->enc_hw_ver >= RADV_VIDEO_ENC_HW_2) {
radv_enc_input_format(cmd_buffer);