diff --git a/src/amd/common/ac_vcn_enc.h b/src/amd/common/ac_vcn_enc.h index af22f2063bf..5bd50dfdee2 100644 --- a/src/amd/common/ac_vcn_enc.h +++ b/src/amd/common/ac_vcn_enc.h @@ -337,6 +337,7 @@ typedef struct rvcn_enc_av1_spec_misc_s { uint32_t cdef_y_sec_strength[RENCODE_AV1_CDEF_MAX_NUM]; uint32_t cdef_uv_pri_strength[RENCODE_AV1_CDEF_MAX_NUM]; uint32_t cdef_uv_sec_strength[RENCODE_AV1_CDEF_MAX_NUM]; + uint32_t disallow_skip_mode; int32_t delta_q_y_dc; int32_t delta_q_u_dc; int32_t delta_q_u_ac; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 1bf0a1f3123..c5a3890072a 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -691,6 +691,8 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, static void radeon_vcn_enc_av1_get_spec_misc_param(struct radeon_encoder *enc, struct pipe_av1_enc_picture_desc *pic) { + struct si_screen *sscreen = (struct si_screen *)enc->screen; + enc->enc_pic.av1_spec_misc.cdef_mode = pic->seq.seq_bits.enable_cdef; enc->enc_pic.av1_spec_misc.disable_cdf_update = pic->disable_cdf_update; enc->enc_pic.av1_spec_misc.disable_frame_end_update_cdf = pic->disable_frame_end_update_cdf; @@ -724,6 +726,15 @@ static void radeon_vcn_enc_av1_get_spec_misc_param(struct radeon_encoder *enc, enc->enc_pic.av1_spec_misc.mv_precision = RENCODE_AV1_MV_PRECISION_FORCE_INTEGER_MV; else enc->enc_pic.av1_spec_misc.mv_precision = RENCODE_AV1_MV_PRECISION_ALLOW_HIGH_PRECISION; + + if (sscreen->info.vcn_ip_version >= VCN_5_0_0) { + enc->enc_pic.av1.skip_mode_allowed = radeon_enc_av1_skip_mode_allowed(enc); + if (enc->enc_pic.av1.compound) { + enc->need_spec_misc = + !enc->enc_pic.av1.skip_mode_allowed != enc->enc_pic.av1_spec_misc.disallow_skip_mode; + enc->enc_pic.av1_spec_misc.disallow_skip_mode = !enc->enc_pic.av1.skip_mode_allowed; + } + } } static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, @@ -759,12 +770,15 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_per_pic.max_qp_app_obs = 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; + enc->enc_pic.rc_per_pic.qp_b = pic->rc[0].qp_inter; min_qp = pic->rc[0].min_qp ? pic->rc[0].min_qp : 1; enc->enc_pic.rc_per_pic.min_qp_i = min_qp; enc->enc_pic.rc_per_pic.min_qp_p = min_qp; + enc->enc_pic.rc_per_pic.min_qp_b = min_qp; max_qp = pic->rc[0].max_qp ? pic->rc[0].max_qp : 255; enc->enc_pic.rc_per_pic.max_qp_i = max_qp; enc->enc_pic.rc_per_pic.max_qp_p = max_qp; + enc->enc_pic.rc_per_pic.max_qp_b = max_qp; enc->enc_pic.rc_per_pic.enabled_filler_data = 0; enc->enc_pic.rc_per_pic.skip_frame_enable = pic->rc[0].skip_frame_enable; enc->enc_pic.rc_per_pic.enforce_hrd = pic->rc[0].enforce_hrd; @@ -793,6 +807,7 @@ static void radeon_vcn_enc_av1_get_rc_param(struct radeon_encoder *enc, enc->enc_pic.rc_per_pic.max_au_size_obs = 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; + enc->enc_pic.rc_per_pic.max_au_size_b = pic->rc[0].max_au_size; } static void radeon_vcn_enc_av1_get_tile_config(struct radeon_encoder *enc, @@ -825,6 +840,7 @@ static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc, { struct si_screen *sscreen = (struct si_screen *)enc->screen; struct radeon_enc_pic *enc_pic = &enc->enc_pic; + enc_pic->av1.desc = pic; enc_pic->frame_type = pic->frame_type; enc_pic->bit_depth_luma_minus8 = enc_pic->bit_depth_chroma_minus8 = @@ -855,6 +871,15 @@ static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc, enc_pic->av1_enc_params.lsm_reference_frame_index[0] = pic->ref_list0[0] == PIPE_H2645_LIST_REF_INVALID_ENTRY ? 0xffffffff : pic->ref_list0[0]; enc_pic->av1_enc_params.lsm_reference_frame_index[1] = 0xffffffff; + enc_pic->av1.compound = false; + + if (pic->ref_list1[0] != PIPE_H2645_LIST_REF_INVALID_ENTRY) { + enc_pic->av1.compound = true; /* BIDIR_COMP */ + enc_pic->av1_enc_params.lsm_reference_frame_index[1] = pic->ref_list1[0]; + } else if (pic->ref_list0[1] != PIPE_H2645_LIST_REF_INVALID_ENTRY) { + enc_pic->av1.compound = true; /* UNIDIR_COMP */ + enc_pic->av1_enc_params.lsm_reference_frame_index[1] = pic->ref_list0[1]; + } } radeon_vcn_enc_av1_get_spec_misc_param(enc, pic); @@ -1302,7 +1327,7 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder, enc->need_rc_per_pic = (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) || - (enc->enc_pic.rc_per_pic.qp_p != pic->rc[0].qp_inter) || + (enc->enc_pic.rc_per_pic.qp_b != pic->rc[0].qp_inter) || (enc->enc_pic.rc_per_pic.max_au_size_i != pic->rc[0].max_au_size) || (enc->enc_pic.rc_per_pic.qvbr_quality_level != pic->rc[0].vbr_quality_factor); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index 62645be81e6..446f8dca630 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -74,6 +74,8 @@ struct radeon_enc_pic { struct pipe_av1_enc_picture_desc *desc; uint32_t coded_width; uint32_t coded_height; + bool compound; + bool skip_mode_allowed; } av1; }; @@ -234,6 +236,7 @@ struct radeon_encoder { bool need_feedback; bool need_rate_control; bool need_rc_per_pic; + bool need_spec_misc; unsigned dpb_size; unsigned dpb_slots; unsigned roi_size; @@ -362,4 +365,7 @@ bool radeon_enc_is_av1_uniform_tile (uint32_t nb_sb, uint32_t nb_tiles, void radeon_enc_av1_tile_layout (uint32_t nb_sb, uint32_t nb_tiles, uint32_t min_nb_sb, struct tile_1d_layout *p); + +bool radeon_enc_av1_skip_mode_allowed(struct radeon_encoder *enc); + #endif // _RADEON_VCN_ENC_H diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c index 9a9f08d44f5..24efc4b4bc3 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c @@ -150,6 +150,9 @@ static void encode(struct radeon_encoder *enc) enc->total_task_size = 0; enc->task_info(enc, enc->need_feedback); + if (enc->need_spec_misc) + enc->spec_misc(enc); + if (enc->need_rate_control || enc->need_rc_per_pic) { i = 0; do { diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c index c7de9a135bb..9c531e73659 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c @@ -81,7 +81,10 @@ static void radeon_enc_encode_params(struct radeon_encoder *enc) break; case PIPE_AV1_ENC_FRAME_TYPE_INTER: case PIPE_AV1_ENC_FRAME_TYPE_SWITCH: - enc->enc_pic.enc_params.pic_type = RENCODE_PICTURE_TYPE_P; + if (enc->enc_pic.av1.compound) + enc->enc_pic.enc_params.pic_type = RENCODE_PICTURE_TYPE_B; + else + enc->enc_pic.enc_params.pic_type = RENCODE_PICTURE_TYPE_P; break; default: assert(0); /* never come to this condition */ @@ -187,7 +190,7 @@ static void radeon_enc_spec_misc_av1(struct radeon_encoder *enc) RADEON_ENC_CS(0); RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.disable_cdf_update); RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.disable_frame_end_update_cdf); - RADEON_ENC_CS(0); + RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.disallow_skip_mode); RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.delta_q_y_dc); RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.delta_q_u_dc); RADEON_ENC_CS(enc->enc_pic.av1_spec_misc.delta_q_u_ac); @@ -721,6 +724,62 @@ static void radeon_enc_av1_quantization_params(struct radeon_encoder *enc) radeon_enc_code_fixed_bits(enc, 0, 1); } +static int32_t radeon_enc_av1_get_relative_dist(struct radeon_encoder *enc, uint32_t a, uint32_t b) +{ + uint32_t diff = a - b; + uint32_t m = 1 << (enc->enc_pic.av1.desc->seq.order_hint_bits - 1); + diff = (diff & (m - 1)) - (diff & m); + return diff; +} + +bool radeon_enc_av1_skip_mode_allowed(struct radeon_encoder *enc) +{ + if (enc->enc_pic.frame_type == PIPE_AV1_ENC_FRAME_TYPE_KEY || + enc->enc_pic.frame_type == PIPE_AV1_ENC_FRAME_TYPE_INTRA_ONLY || + !enc->enc_pic.av1.compound || + !enc->enc_pic.av1.desc->seq.seq_bits.enable_order_hint) + return false; + + int32_t forward_idx = -1, backward_idx = -1; + uint32_t forward_hint, backward_hint; + + for (uint32_t i = 0; i < RENCODE_AV1_REFS_PER_FRAME; i++) { + uint32_t ref_hint = enc->enc_pic.av1.desc->dpb[enc->enc_pic.av1.desc->dpb_ref_frame_idx[i]].order_hint; + int32_t dist = radeon_enc_av1_get_relative_dist(enc, ref_hint, enc->enc_pic.av1.desc->order_hint); + if (dist < 0) { + if (forward_idx < 0 || radeon_enc_av1_get_relative_dist(enc, ref_hint, forward_hint) > 0) { + forward_idx = i; + forward_hint = ref_hint; + } + } else if (dist > 0) { + if (backward_idx < 0 || radeon_enc_av1_get_relative_dist(enc, ref_hint, backward_hint) < 0) { + backward_idx = i; + backward_hint = ref_hint; + } + } + } + + if (forward_idx < 0) + return false; + else if (backward_idx >= 0) + return true; + + int32_t second_forward_idx = -1; + uint32_t second_forward_hint; + + for (uint32_t i = 0; i < RENCODE_AV1_REFS_PER_FRAME; i++) { + uint32_t ref_hint = enc->enc_pic.av1.desc->dpb[enc->enc_pic.av1.desc->dpb_ref_frame_idx[i]].order_hint; + if (radeon_enc_av1_get_relative_dist(enc, ref_hint, forward_hint) < 0) { + if (second_forward_idx < 0 || radeon_enc_av1_get_relative_dist(enc, ref_hint, second_forward_hint) > 0) { + second_forward_idx = i; + second_forward_hint = ref_hint; + } + } + } + + return second_forward_idx >= 0; +} + static void radeon_enc_av1_frame_header(struct radeon_encoder *enc, bool frame_header) { bool frame_is_intra = enc->enc_pic.frame_type == PIPE_AV1_ENC_FRAME_TYPE_KEY || @@ -750,7 +809,11 @@ static void radeon_enc_av1_frame_header(struct radeon_encoder *enc, bool frame_h if (!frame_is_intra) /* reference_select */ - radeon_enc_code_fixed_bits(enc, 0, 1); + radeon_enc_code_fixed_bits(enc, enc->enc_pic.av1.compound, 1); + + if (enc->enc_pic.av1.skip_mode_allowed) + /* skip_mode_present */ + radeon_enc_code_fixed_bits(enc, 1, 1); /* reduced_tx_set */ radeon_enc_code_fixed_bits(enc, 0, 1); diff --git a/src/gallium/drivers/radeonsi/si_get.c b/src/gallium/drivers/radeonsi/si_get.c index 6295ea49bf8..7e94791918d 100644 --- a/src/gallium/drivers/radeonsi/si_get.c +++ b/src/gallium/drivers/radeonsi/si_get.c @@ -842,6 +842,10 @@ static int si_get_video_param(struct pipe_screen *screen, enum pipe_video_profil if (sscreen->info.vcn_ip_version >= VCN_3_0_0) { int refPicList0 = 1; int refPicList1 = codec == PIPE_VIDEO_FORMAT_MPEG4_AVC ? 1 : 0; + if (sscreen->info.vcn_ip_version >= VCN_5_0_0 && codec == PIPE_VIDEO_FORMAT_AV1) { + refPicList0 = 2; + refPicList1 = 1; + } return refPicList0 | (refPicList1 << 16); } else return 1;