diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 3097f65549a..d286e3520d0 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -194,6 +194,28 @@ static void radeon_vcn_enc_h264_get_vui_param(struct radeon_encoder *enc, enc->enc_pic.vui_info.time_scale = pic->seq.time_scale; } +/* only checking the first slice to get num of mbs in slice to + * determine the number of slices in this frame, only fixed MB mode + * is supported now, the last slice in frame could have less number of + * MBs. + */ +static void radeon_vcn_enc_h264_get_slice_ctrl_param(struct radeon_encoder *enc, + struct pipe_h264_enc_picture_desc *pic) +{ + uint32_t width_in_mb, height_in_mb, num_mbs_in_slice; + + width_in_mb = PIPE_ALIGN_IN_BLOCK_SIZE(enc->base.width, PIPE_H264_MB_SIZE); + height_in_mb = PIPE_ALIGN_IN_BLOCK_SIZE(enc->base.height, PIPE_H264_MB_SIZE); + + if (pic->slices_descriptors[0].num_macroblocks >= width_in_mb * height_in_mb || + pic->slices_descriptors[0].num_macroblocks == 0) + num_mbs_in_slice = width_in_mb * height_in_mb; + else + num_mbs_in_slice = pic->slices_descriptors[0].num_macroblocks; + + enc->enc_pic.slice_ctrl.num_mbs_per_slice = num_mbs_in_slice; +} + static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, struct pipe_h264_enc_picture_desc *pic) { @@ -217,6 +239,7 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, radeon_vcn_enc_h264_get_rc_param(enc, pic); radeon_vcn_enc_h264_get_spec_misc_param(enc, pic); radeon_vcn_enc_h264_get_vui_param(enc, pic); + radeon_vcn_enc_h264_get_slice_ctrl_param(enc, pic); } static void radeon_vcn_enc_hevc_get_cropping_param(struct radeon_encoder *enc, @@ -329,6 +352,34 @@ static void radeon_vcn_enc_hevc_get_vui_param(struct radeon_encoder *enc, enc->enc_pic.vui_info.time_scale = pic->seq.time_scale; } +/* only checking the first slice to get num of ctbs in slice to + * determine the number of slices in this frame, only fixed CTB mode + * is supported now, the last slice in frame could have less number of + * ctbs. + */ +static void radeon_vcn_enc_hevc_get_slice_ctrl_param(struct radeon_encoder *enc, + struct pipe_h265_enc_picture_desc *pic) +{ + uint32_t width_in_ctb, height_in_ctb, num_ctbs_in_slice; + + width_in_ctb = PIPE_ALIGN_IN_BLOCK_SIZE(pic->seq.pic_width_in_luma_samples, + PIPE_H265_ENC_CTB_SIZE); + height_in_ctb = PIPE_ALIGN_IN_BLOCK_SIZE(pic->seq.pic_height_in_luma_samples, + PIPE_H265_ENC_CTB_SIZE); + + if (pic->slices_descriptors[0].num_ctu_in_slice >= width_in_ctb * height_in_ctb || + pic->slices_descriptors[0].num_ctu_in_slice == 0) + num_ctbs_in_slice = width_in_ctb * height_in_ctb; + else + num_ctbs_in_slice = pic->slices_descriptors[0].num_ctu_in_slice; + + enc->enc_pic.hevc_slice_ctrl.fixed_ctbs_per_slice.num_ctbs_per_slice = + num_ctbs_in_slice; + + enc->enc_pic.hevc_slice_ctrl.fixed_ctbs_per_slice.num_ctbs_per_slice_segment = + num_ctbs_in_slice; +} + static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, struct pipe_h265_enc_picture_desc *pic) { @@ -385,6 +436,7 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, radeon_vcn_enc_hevc_get_rc_param(enc, pic); radeon_vcn_enc_hevc_get_rc_param(enc, pic); radeon_vcn_enc_hevc_get_vui_param(enc, pic); + radeon_vcn_enc_hevc_get_slice_ctrl_param(enc, pic); } static void radeon_vcn_enc_get_param(struct radeon_encoder *enc, struct pipe_picture_desc *picture) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index c50c7118084..991b3a58788 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -135,6 +135,11 @@ #define RENCODE_MAX_NUM_TEMPORAL_LAYERS 4 +#define PIPE_H265_ENC_CTB_SIZE 64 +#define PIPE_H264_MB_SIZE 16 + +#define PIPE_ALIGN_IN_BLOCK_SIZE(value, align) (((value) + ((align) - 1))/(align)) + #define RADEON_ENC_CS(value) (enc->cs.current.buf[enc->cs.current.cdw++] = (value)) #define RADEON_ENC_BEGIN(cmd) \ { \ diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c index eceef4f30c0..6ccc884ecc7 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -141,8 +141,6 @@ static void radeon_enc_layer_select(struct radeon_encoder *enc) static void radeon_enc_slice_control(struct radeon_encoder *enc) { enc->enc_pic.slice_ctrl.slice_control_mode = RENCODE_H264_SLICE_CONTROL_MODE_FIXED_MBS; - enc->enc_pic.slice_ctrl.num_mbs_per_slice = - align(enc->base.width, 16) / 16 * align(enc->base.height, 16) / 16; RADEON_ENC_BEGIN(enc->cmd.slice_control_h264); RADEON_ENC_CS(enc->enc_pic.slice_ctrl.slice_control_mode); @@ -153,10 +151,6 @@ static void radeon_enc_slice_control(struct radeon_encoder *enc) static void radeon_enc_slice_control_hevc(struct radeon_encoder *enc) { enc->enc_pic.hevc_slice_ctrl.slice_control_mode = RENCODE_HEVC_SLICE_CONTROL_MODE_FIXED_CTBS; - enc->enc_pic.hevc_slice_ctrl.fixed_ctbs_per_slice.num_ctbs_per_slice = - align(enc->base.width, 64) / 64 * align(enc->base.height, 64) / 64; - enc->enc_pic.hevc_slice_ctrl.fixed_ctbs_per_slice.num_ctbs_per_slice_segment = - enc->enc_pic.hevc_slice_ctrl.fixed_ctbs_per_slice.num_ctbs_per_slice; RADEON_ENC_BEGIN(enc->cmd.slice_control_hevc); RADEON_ENC_CS(enc->enc_pic.hevc_slice_ctrl.slice_control_mode); diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index 449908208eb..84c343bbc01 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -627,20 +627,58 @@ static int si_get_video_param(struct pipe_screen *screen, enum pipe_video_profil return (sscreen->info.family >= CHIP_RAVEN) ? 1 : 0; case PIPE_VIDEO_CAP_ENC_HEVC_FEATURE_FLAGS: - if ((sscreen->info.family >= CHIP_RENOIR) && - (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN || - profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)) { + if ((sscreen->info.family >= CHIP_RAVEN) && + (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN || + profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10)) { union pipe_h265_enc_cap_features pipe_features; pipe_features.value = 0; - pipe_features.bits.sao = PIPE_H265_ENC_FEATURE_SUPPORTED; + pipe_features.bits.amp = PIPE_H265_ENC_FEATURE_SUPPORTED; + pipe_features.bits.strong_intra_smoothing = PIPE_H265_ENC_FEATURE_SUPPORTED; + pipe_features.bits.constrained_intra_pred = PIPE_H265_ENC_FEATURE_SUPPORTED; + pipe_features.bits.deblocking_filter_disable + = PIPE_H265_ENC_FEATURE_SUPPORTED; + if (sscreen->info.family >= CHIP_RENOIR) + pipe_features.bits.sao = PIPE_H265_ENC_FEATURE_SUPPORTED; + return pipe_features.value; } else return 0; + case PIPE_VIDEO_CAP_ENC_HEVC_BLOCK_SIZES: + if (profile == PIPE_VIDEO_PROFILE_HEVC_MAIN || + profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10) { + union pipe_h265_enc_cap_block_sizes pipe_block_sizes; + pipe_block_sizes.value = 0; + + pipe_block_sizes.bits.log2_max_coding_tree_block_size_minus3 = 3; + pipe_block_sizes.bits.log2_min_coding_tree_block_size_minus3 = 3; + pipe_block_sizes.bits.log2_min_luma_coding_block_size_minus3 = 0; + pipe_block_sizes.bits.log2_max_luma_transform_block_size_minus2 = 3; + pipe_block_sizes.bits.log2_min_luma_transform_block_size_minus2 = 0; + + return pipe_block_sizes.value; + } else + return 0; + case PIPE_VIDEO_CAP_ENC_SUPPORTS_ASYNC_OPERATION: return (sscreen->info.family >= CHIP_RAVEN) ? 1 : 0; + case PIPE_VIDEO_CAP_ENC_MAX_SLICES_PER_FRAME: + if (sscreen->info.family >= CHIP_RAVEN) + return 128; + else + return 1; + + case PIPE_VIDEO_CAP_ENC_SLICES_STRUCTURE: + if (sscreen->info.family >= CHIP_RENOIR) { + int value = (PIPE_VIDEO_CAP_SLICE_STRUCTURE_POWER_OF_TWO_ROWS | + PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_ROWS | + PIPE_VIDEO_CAP_SLICE_STRUCTURE_EQUAL_MULTI_ROWS); + return value; + } else + return 0; + default: return 0; }