From b61ffe2151df2eca1e9af9730cfd712ee43e6bbd Mon Sep 17 00:00:00 2001 From: Boyuan Zhang Date: Sun, 17 Mar 2024 19:57:11 -0400 Subject: [PATCH] radeonsi/vcn: choose rc_per_pic by encode verison Using VCN FW encode version to check if the current FW support the new rate control per picture method (ex). If not, roll back to use the previous rate control per picture method. Fixes: 5ecf83e9adcd652e6159 ("radeonsi/vcn: Implement separate QP for I/P/B frames") Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10793 Signed-off-by: Boyuan Zhang Reviewed-by: Ruijing Dong Part-of: --- src/amd/common/ac_vcn_enc.h | 4 +++ src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 35 ++++++++++++++++--- src/gallium/drivers/radeonsi/radeon_vcn_enc.h | 1 + .../drivers/radeonsi/radeon_vcn_enc_1_2.c | 26 ++++++++++++-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/amd/common/ac_vcn_enc.h b/src/amd/common/ac_vcn_enc.h index 8615f898cd1..ebff3a55b1b 100644 --- a/src/amd/common/ac_vcn_enc.h +++ b/src/amd/common/ac_vcn_enc.h @@ -312,6 +312,10 @@ typedef struct rvcn_enc_rate_ctl_layer_init_s { } rvcn_enc_rate_ctl_layer_init_t; typedef struct rvcn_enc_rate_ctl_per_picture_s { + uint32_t qp; + uint32_t min_qp_app; + uint32_t max_qp_app; + uint32_t max_au_size; uint32_t qp_i; uint32_t qp_p; uint32_t qp_b; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index d9b1beefac5..3d3462cb28d 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -261,6 +261,10 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc, frame_rate_num); } enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rate_ctrl[0].vbv_buf_lv; + enc->enc_pic.rc_per_pic.qp = pic->quant_i_frames; + enc->enc_pic.rc_per_pic.min_qp_app = pic->rate_ctrl[0].min_qp; + enc->enc_pic.rc_per_pic.max_qp_app = pic->rate_ctrl[0].max_qp ? + pic->rate_ctrl[0].max_qp : 51; enc->enc_pic.rc_per_pic.qp_i = pic->quant_i_frames; enc->enc_pic.rc_per_pic.qp_p = pic->quant_p_frames; enc->enc_pic.rc_per_pic.qp_b = pic->quant_b_frames; @@ -291,6 +295,7 @@ static void radeon_vcn_enc_h264_get_rc_param(struct radeon_encoder *enc, default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } + enc->enc_pic.rc_per_pic.max_au_size = pic->rate_ctrl[0].max_au_size; enc->enc_pic.rc_per_pic.max_au_size_i = pic->rate_ctrl[0].max_au_size; enc->enc_pic.rc_per_pic.max_au_size_p = pic->rate_ctrl[0].max_au_size; enc->enc_pic.rc_per_pic.max_au_size_b = pic->rate_ctrl[0].max_au_size; @@ -513,6 +518,9 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc, frame_rate_den, frame_rate_num); enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rc.vbv_buf_lv; + enc->enc_pic.rc_per_pic.qp = pic->rc.quant_i_frames; + enc->enc_pic.rc_per_pic.min_qp_app = pic->rc.min_qp; + enc->enc_pic.rc_per_pic.max_qp_app = pic->rc.max_qp ? pic->rc.max_qp : 51; enc->enc_pic.rc_per_pic.qp_i = pic->rc.quant_i_frames; enc->enc_pic.rc_per_pic.qp_p = pic->rc.quant_p_frames; enc->enc_pic.rc_per_pic.min_qp_i = pic->rc.min_qp; @@ -539,6 +547,7 @@ static void radeon_vcn_enc_hevc_get_rc_param(struct radeon_encoder *enc, default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } + enc->enc_pic.rc_per_pic.max_au_size = pic->rc.max_au_size; enc->enc_pic.rc_per_pic.max_au_size_i = pic->rc.max_au_size; enc->enc_pic.rc_per_pic.max_au_size_p = pic->rc.max_au_size; } @@ -737,6 +746,9 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, frame_rate_num); } enc->enc_pic.rc_session_init.vbv_buffer_level = pic->rc[0].vbv_buf_lv; + enc->enc_pic.rc_per_pic.qp = pic->rc[0].qp; + enc->enc_pic.rc_per_pic.min_qp_app = pic->rc[0].min_qp ? pic->rc[0].min_qp : 1; + enc->enc_pic.rc_per_pic.max_qp_app = pic->rc[0].max_qp ? pic->rc[0].max_qp : 255; enc->enc_pic.rc_per_pic.qp_i = pic->rc[0].qp; enc->enc_pic.rc_per_pic.qp_p = pic->rc[0].qp_inter; min_qp = pic->rc[0].min_qp ? pic->rc[0].min_qp : 1; @@ -764,6 +776,7 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, default: enc->enc_pic.rc_session_init.rate_control_method = RENCODE_RATE_CONTROL_METHOD_NONE; } + enc->enc_pic.rc_per_pic.max_au_size = pic->rc[0].max_au_size; enc->enc_pic.rc_per_pic.max_au_size_i = pic->rc[0].max_au_size; enc->enc_pic.rc_per_pic.max_au_size_p = pic->rc[0].max_au_size; } @@ -1333,14 +1346,28 @@ struct pipe_video_codec *radeon_create_encoder(struct pipe_context *context, goto error; } - if (sscreen->info.vcn_ip_version >= VCN_4_0_0) + enc->enc_pic.use_rc_per_pic_ex = false; + + if (sscreen->info.vcn_ip_version >= VCN_4_0_0) { + if (sscreen->info.vcn_enc_minor_version >= 1) + enc->enc_pic.use_rc_per_pic_ex = true; radeon_enc_4_0_init(enc); - else if (sscreen->info.vcn_ip_version >= VCN_3_0_0) + } + else if (sscreen->info.vcn_ip_version >= VCN_3_0_0) { + if (sscreen->info.vcn_enc_minor_version >= 24) + enc->enc_pic.use_rc_per_pic_ex = true; radeon_enc_3_0_init(enc); - else if (sscreen->info.vcn_ip_version >= VCN_2_0_0) + } + else if (sscreen->info.vcn_ip_version >= VCN_2_0_0) { + if (sscreen->info.vcn_enc_minor_version >= 18) + enc->enc_pic.use_rc_per_pic_ex = true; radeon_enc_2_0_init(enc); - else + } + else { + if (sscreen->info.vcn_enc_minor_version >= 15) + enc->enc_pic.use_rc_per_pic_ex = true; radeon_enc_1_2_init(enc); + } return &enc->base; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index 2c173057086..7fa80e3e97e 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -107,6 +107,7 @@ struct radeon_enc_pic { bool sample_adaptive_offset_enabled_flag; bool pcm_enabled_flag; bool sps_temporal_mvp_enabled_flag; + bool use_rc_per_pic_ex; struct { struct { 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 6df548cdcc4..20efe2ad650 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -25,7 +25,7 @@ #define RENCODE_IB_PARAM_LAYER_SELECT 0x00000005 #define RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT 0x00000006 #define RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT 0x00000007 -#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE 0x0000001d +#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE 0x00000008 #define RENCODE_IB_PARAM_QUALITY_PARAMS 0x00000009 #define RENCODE_IB_PARAM_SLICE_HEADER 0x0000000a #define RENCODE_IB_PARAM_ENCODE_PARAMS 0x0000000b @@ -33,6 +33,7 @@ #define RENCODE_IB_PARAM_ENCODE_CONTEXT_BUFFER 0x0000000d #define RENCODE_IB_PARAM_VIDEO_BITSTREAM_BUFFER 0x0000000e #define RENCODE_IB_PARAM_FEEDBACK_BUFFER 0x00000010 +#define RENCODE_IB_PARAM_RATE_CONTROL_PER_PIC_EX 0x0000001d #define RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU 0x00000020 #define RENCODE_IB_PARAM_QP_MAP 0x00000021 #define RENCODE_IB_PARAM_ENCODE_STATISTICS 0x00000024 @@ -1188,6 +1189,19 @@ static void radeon_enc_intra_refresh(struct radeon_encoder *enc) } static void radeon_enc_rc_per_pic(struct radeon_encoder *enc) +{ + RADEON_ENC_BEGIN(enc->cmd.rc_per_pic); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.qp); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.min_qp_app); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_qp_app); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.max_au_size); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enabled_filler_data); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.skip_frame_enable); + RADEON_ENC_CS(enc->enc_pic.rc_per_pic.enforce_hrd); + RADEON_ENC_END(); +} + +static void radeon_enc_rc_per_pic_ex(struct radeon_encoder *enc) { enc->enc_pic.rc_per_pic.reserved_0xff = 0xFFFFFFFF; @@ -1579,7 +1593,10 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc) enc->bitstream = radeon_enc_bitstream; enc->feedback = radeon_enc_feedback; enc->intra_refresh = radeon_enc_intra_refresh; - enc->rc_per_pic = radeon_enc_rc_per_pic; + if (enc->enc_pic.use_rc_per_pic_ex == true) + enc->rc_per_pic = radeon_enc_rc_per_pic_ex; + else + enc->rc_per_pic = radeon_enc_rc_per_pic; enc->encode_params = radeon_enc_encode_params; enc->op_init = radeon_enc_op_init; enc->op_close = radeon_enc_op_close; @@ -1621,7 +1638,10 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc) enc->cmd.layer_select = RENCODE_IB_PARAM_LAYER_SELECT; enc->cmd.rc_session_init = RENCODE_IB_PARAM_RATE_CONTROL_SESSION_INIT; enc->cmd.rc_layer_init = RENCODE_IB_PARAM_RATE_CONTROL_LAYER_INIT; - enc->cmd.rc_per_pic = RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE; + if (enc->enc_pic.use_rc_per_pic_ex == true) + enc->cmd.rc_per_pic = RENCODE_IB_PARAM_RATE_CONTROL_PER_PIC_EX; + else + enc->cmd.rc_per_pic = RENCODE_IB_PARAM_RATE_CONTROL_PER_PICTURE; enc->cmd.quality_params = RENCODE_IB_PARAM_QUALITY_PARAMS; enc->cmd.nalu = RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU; enc->cmd.slice_header = RENCODE_IB_PARAM_SLICE_HEADER;