From e76a5e69ff2b7b731fe2a1d41390affddd904858 Mon Sep 17 00:00:00 2001 From: Benjamin Cheng Date: Wed, 29 Oct 2025 10:37:41 -0400 Subject: [PATCH] radv/video_enc: Use variable slice mode when possible Reviewed-by: David Rosca Part-of: --- src/amd/vulkan/radv_video_enc.c | 50 +++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/amd/vulkan/radv_video_enc.c b/src/amd/vulkan/radv_video_enc.c index 449900d2dad..5d9107bc485 100644 --- a/src/amd/vulkan/radv_video_enc.c +++ b/src/amd/vulkan/radv_video_enc.c @@ -609,8 +609,30 @@ radv_enc_slice_control(struct radv_cmd_buffer *cmd_buffer, const struct VkVideoE uint32_t height_in_mbs = DIV_ROUND_UP(cmd_buffer->video.enc.coded_height, 16); num_mbs_in_slice = DIV_ROUND_UP(width_in_mbs * height_in_mbs, h264_picture_info->naluSliceEntryCount); + uint32_t slice_control_mode = RENCODE_H264_SLICE_CONTROL_MODE_FIXED_MBS; + + if (ac_vcn_enc_variable_slice_mode_supported(&pdev->info) && + h264_picture_info->naluSliceEntryCount <= RENCODE_MAX_NUM_SLICES) { + uint32_t last_mb = 0; + slice_control_mode = RENCODE_H264_SLICE_CONTROL_MODE_VARIABLE_MBS; + + RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.slice_info_h264); + RADEON_ENC_CS(h264_picture_info->naluSliceEntryCount); + for (uint32_t i = 1; i < h264_picture_info->naluSliceEntryCount; ++i) { + uint32_t slice_size = h264_picture_info->pNaluSliceEntries[i].pStdSliceHeader->first_mb_in_slice - last_mb; + RADEON_ENC_CS(slice_size); + last_mb = h264_picture_info->pNaluSliceEntries[i].pStdSliceHeader->first_mb_in_slice; + + /* Preserve compatibility with apps that simply copy pNaluSliceEntries */ + if (slice_size == 0) + slice_control_mode = RENCODE_H264_SLICE_CONTROL_MODE_FIXED_MBS; + } + RADEON_ENC_CS(width_in_mbs * height_in_mbs - last_mb); + RADEON_ENC_END(); + } + RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.slice_control_h264); - RADEON_ENC_CS(RENCODE_H264_SLICE_CONTROL_MODE_FIXED_MBS); // slice control mode + RADEON_ENC_CS(slice_control_mode); // slice control mode RADEON_ENC_CS(num_mbs_in_slice); // num mbs per slice RADEON_ENC_END(); } @@ -695,8 +717,32 @@ radv_enc_slice_control_hevc(struct radv_cmd_buffer *cmd_buffer, const struct VkV height_in_ctb = DIV_ROUND_UP(cmd_buffer->video.enc.coded_height, 64); num_ctbs_in_slice = DIV_ROUND_UP(width_in_ctb * height_in_ctb, h265_picture_info->naluSliceSegmentEntryCount); + uint32_t slice_control_mode = RENCODE_HEVC_SLICE_CONTROL_MODE_FIXED_CTBS; + if (ac_vcn_enc_variable_slice_mode_supported(&pdev->info) && + h265_picture_info->naluSliceSegmentEntryCount <= RENCODE_MAX_NUM_SLICES) { + uint32_t last_ctb = 0; + slice_control_mode = RENCODE_HEVC_SLICE_CONTROL_MODE_VARIABLE_CTBS; + + RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.slice_info_hevc); + RADEON_ENC_CS(h265_picture_info->naluSliceSegmentEntryCount); + for (uint32_t i = 1; i < h265_picture_info->naluSliceSegmentEntryCount; ++i) { + uint32_t slice_size = + h265_picture_info->pNaluSliceSegmentEntries[i].pStdSliceSegmentHeader->slice_segment_address - last_ctb; + RADEON_ENC_CS(slice_size); + RADEON_ENC_CS(1); // is_independent + last_ctb = h265_picture_info->pNaluSliceSegmentEntries[i].pStdSliceSegmentHeader->slice_segment_address; + + /* Preserve compatibility with apps that simply copy pNaluSliceSegmentEntries */ + if (slice_size == 0) + slice_control_mode = RENCODE_HEVC_SLICE_CONTROL_MODE_FIXED_CTBS; + } + RADEON_ENC_CS(width_in_ctb * height_in_ctb - last_ctb); + RADEON_ENC_CS(1); // is_independent + RADEON_ENC_END(); + } + RADEON_ENC_BEGIN(pdev->vcn_enc_cmds.slice_control_hevc); - RADEON_ENC_CS(RENCODE_HEVC_SLICE_CONTROL_MODE_FIXED_CTBS); + RADEON_ENC_CS(slice_control_mode); RADEON_ENC_CS(num_ctbs_in_slice); // num_ctbs_in_slice RADEON_ENC_CS(num_ctbs_in_slice); // num_ctbs_in_slice_segment RADEON_ENC_END();