From 764b316623d1db32028de5210069288cc20abffa Mon Sep 17 00:00:00 2001 From: David Rosca Date: Tue, 5 Nov 2024 09:23:03 +0100 Subject: [PATCH] radeonsi/vcn: Rework encode padding and session init params Move the session init params into common code, instead of having the same code copied for each VCN version. Change the padding logic to enforce minimum padding required for input surface (in case the input surface is smaller than aligned coded size) and also avoid setting the padding above supported maximum. Reviewed-by: Ruijing Dong Part-of: --- src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 155 +++++++++++++++--- src/gallium/drivers/radeonsi/radeon_vcn_enc.h | 5 +- .../drivers/radeonsi/radeon_vcn_enc_1_2.c | 14 -- .../drivers/radeonsi/radeon_vcn_enc_3_0.c | 14 -- .../drivers/radeonsi/radeon_vcn_enc_4_0.c | 59 ------- .../drivers/radeonsi/radeon_vcn_enc_5_0.c | 49 ------ 6 files changed, 132 insertions(+), 164 deletions(-) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 7fdf7bcdd15..552b144c992 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -216,20 +216,44 @@ static void radeon_vcn_enc_get_latency_param(struct radeon_encoder *enc) sscreen->debug_flags & DBG(LOW_LATENCY_ENCODE) ? 1000 : 0; } -static void radeon_vcn_enc_h264_get_cropping_param(struct radeon_encoder *enc, - struct pipe_h264_enc_picture_desc *pic) +static void radeon_vcn_enc_h264_get_session_param(struct radeon_encoder *enc, + struct pipe_h264_enc_picture_desc *pic) { + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + uint32_t align_width = PIPE_H264_MB_SIZE; + uint32_t align_height = PIPE_H264_MB_SIZE; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; + enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, align_height); + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + if (pic->seq.enc_frame_cropping_flag) { - enc->enc_pic.crop_left = pic->seq.enc_frame_crop_left_offset; - enc->enc_pic.crop_right = pic->seq.enc_frame_crop_right_offset; - enc->enc_pic.crop_top = pic->seq.enc_frame_crop_top_offset; - enc->enc_pic.crop_bottom = pic->seq.enc_frame_crop_bottom_offset; - } else { - enc->enc_pic.crop_left = 0; - enc->enc_pic.crop_right = 0; - enc->enc_pic.crop_top = 0; - enc->enc_pic.crop_bottom = 0; + uint32_t pad_w = + (pic->seq.enc_frame_crop_left_offset + pic->seq.enc_frame_crop_right_offset) * 2; + uint32_t pad_h = + (pic->seq.enc_frame_crop_top_offset + pic->seq.enc_frame_crop_bottom_offset) * 2; + padding_width = CLAMP(pad_w, padding_width, max_padding_width); + padding_height = CLAMP(pad_h, padding_height, max_padding_height); } + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; } static void radeon_vcn_enc_h264_get_dbk_param(struct radeon_encoder *enc, @@ -490,7 +514,7 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, } } - radeon_vcn_enc_h264_get_cropping_param(enc, pic); + radeon_vcn_enc_h264_get_session_param(enc, pic); radeon_vcn_enc_h264_get_dbk_param(enc, pic); radeon_vcn_enc_h264_get_rc_param(enc, pic); radeon_vcn_enc_h264_get_spec_misc_param(enc, pic); @@ -505,20 +529,44 @@ static void radeon_vcn_enc_h264_get_param(struct radeon_encoder *enc, radeon_vcn_enc_quality_modes(enc, &pic->quality_modes); } -static void radeon_vcn_enc_hevc_get_cropping_param(struct radeon_encoder *enc, - struct pipe_h265_enc_picture_desc *pic) +static void radeon_vcn_enc_hevc_get_session_param(struct radeon_encoder *enc, + struct pipe_h265_enc_picture_desc *pic) { + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + uint32_t align_width = PIPE_H265_ENC_CTB_SIZE; + uint32_t align_height = 16; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; + enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, align_height); + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + if (pic->seq.conformance_window_flag) { - enc->enc_pic.crop_left = pic->seq.conf_win_left_offset; - enc->enc_pic.crop_right = pic->seq.conf_win_right_offset; - enc->enc_pic.crop_top = pic->seq.conf_win_top_offset; - enc->enc_pic.crop_bottom = pic->seq.conf_win_bottom_offset; - } else { - enc->enc_pic.crop_left = 0; - enc->enc_pic.crop_right = 0; - enc->enc_pic.crop_top = 0; - enc->enc_pic.crop_bottom = 0; + uint32_t pad_w = + (pic->seq.conf_win_left_offset + pic->seq.conf_win_right_offset) * 2; + uint32_t pad_h = + (pic->seq.conf_win_top_offset + pic->seq.conf_win_bottom_offset) * 2; + padding_width = CLAMP(pad_w, padding_width, max_padding_width); + padding_height = CLAMP(pad_h, padding_height, max_padding_height); } + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; } static void radeon_vcn_enc_hevc_get_dbk_param(struct radeon_encoder *enc, @@ -696,7 +744,7 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, } } - radeon_vcn_enc_hevc_get_cropping_param(enc, pic); + radeon_vcn_enc_hevc_get_session_param(enc, pic); radeon_vcn_enc_hevc_get_dbk_param(enc, pic); radeon_vcn_enc_hevc_get_rc_param(enc, pic); radeon_vcn_enc_hevc_get_slice_ctrl_param(enc, pic); @@ -711,6 +759,63 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, radeon_vcn_enc_quality_modes(enc, &pic->quality_modes); } +static void radeon_vcn_enc_av1_get_session_param(struct radeon_encoder *enc, + struct pipe_av1_enc_picture_desc *pic) +{ + struct si_screen *sscreen = (struct si_screen *)enc->screen; + + if (enc->enc_pic.session_init.aligned_picture_width) + return; + + enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; + + uint32_t width = enc->enc_pic.pic_width_in_luma_samples; + uint32_t height = enc->enc_pic.pic_height_in_luma_samples; + uint32_t align_width, align_height; + + if (sscreen->info.vcn_ip_version < VCN_5_0_0) { + align_width = PIPE_AV1_ENC_SB_SIZE; + align_height = 16; + enc->enc_pic.session_init.aligned_picture_width = align(width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(height, align_height); + if (!(height % 8) && (height % 16)) + enc->enc_pic.session_init.aligned_picture_height = height + 2; + enc->enc_pic.av1.coded_width = enc->enc_pic.session_init.aligned_picture_width; + enc->enc_pic.av1.coded_height = enc->enc_pic.session_init.aligned_picture_height; + if (sscreen->info.vcn_ip_version == VCN_4_0_2 || + sscreen->info.vcn_ip_version == VCN_4_0_5 || + sscreen->info.vcn_ip_version == VCN_4_0_6) + enc->enc_pic.session_init.WA_flags = 1; + } else { + align_width = 8; + align_height = 2; + enc->enc_pic.session_init.aligned_picture_width = align(width, align_width); + enc->enc_pic.session_init.aligned_picture_height = align(height, align_height); + enc->enc_pic.av1.coded_width = width; + enc->enc_pic.av1.coded_height = height; + } + + uint32_t padding_width = 0; + uint32_t padding_height = 0; + uint32_t max_padding_width = align_width - 2; + uint32_t max_padding_height = align_height - 2; + + if (enc->enc_pic.session_init.aligned_picture_width > enc->source->width) + padding_width = enc->enc_pic.session_init.aligned_picture_width - enc->source->width; + if (enc->enc_pic.session_init.aligned_picture_height > enc->source->height) + padding_height = enc->enc_pic.session_init.aligned_picture_height - enc->source->height; + + /* Input surface can be smaller if the difference is within padding bounds. */ + if (padding_width > max_padding_width || padding_height > max_padding_height) + RADEON_ENC_ERR("Input surface size doesn't match aligned size\n"); + + padding_width = MAX2(padding_width, enc->enc_pic.session_init.aligned_picture_width - width); + padding_height = MAX2(padding_height, enc->enc_pic.session_init.aligned_picture_height - height); + + enc->enc_pic.session_init.padding_width = padding_width; + enc->enc_pic.session_init.padding_height = padding_height; +} + static void radeon_vcn_enc_av1_get_spec_misc_param(struct radeon_encoder *enc, struct pipe_av1_enc_picture_desc *pic) { @@ -919,6 +1024,7 @@ static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc, } } + radeon_vcn_enc_av1_get_session_param(enc, pic); radeon_vcn_enc_av1_get_spec_misc_param(enc, pic); radeon_vcn_enc_av1_get_rc_param(enc, pic); radeon_vcn_enc_av1_get_tile_config(enc, pic); @@ -1326,6 +1432,7 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder, struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; unsigned dpb_slots = 0; + enc->source = source; enc->need_rate_control = false; enc->need_rc_per_pic = false; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index c637f768c65..8db56f3ba32 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -93,10 +93,6 @@ struct radeon_enc_pic { } av1; }; - unsigned crop_left; - unsigned crop_right; - unsigned crop_top; - unsigned crop_bottom; unsigned pic_width_in_luma_samples; unsigned pic_height_in_luma_samples; unsigned bit_depth_luma_minus8; @@ -237,6 +233,7 @@ struct radeon_encoder { struct pb_buffer_lean *handle; struct radeon_surf *luma; struct radeon_surf *chroma; + struct pipe_video_buffer *source; struct pb_buffer_lean *bs_handle; unsigned bs_size; 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 f466040bc1c..b1ec27ed7ea 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -44,20 +44,6 @@ static void radeon_enc_task_info(struct radeon_encoder *enc, bool need_feedback) static void radeon_enc_session_init(struct radeon_encoder *enc) { - if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - } else if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - } - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; enc->enc_pic.session_init.pre_encode_chroma_enabled = !!(enc->enc_pic.quality_modes.pre_encode_mode); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c index 77782572232..b9af7bc7538 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_3_0.c @@ -162,20 +162,6 @@ static void radeon_enc_ctx(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - } else if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_HEVC) { - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - } - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c index 462c9ae5903..33b0eed8fd3 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c @@ -60,65 +60,6 @@ static void radeon_enc_op_preset(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - struct si_screen *sscreen = (struct si_screen *)enc->screen; - uint32_t av1_height = enc->enc_pic.pic_height_in_luma_samples; - - switch (u_reduce_video_profile(enc->base.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_HEVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_AV1: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; - enc->enc_pic.session_init.aligned_picture_width = - align(enc->enc_pic.pic_width_in_luma_samples, 64); - enc->enc_pic.session_init.aligned_picture_height = - align(enc->enc_pic.pic_height_in_luma_samples, 16); - if (!(av1_height % 8) && (av1_height % 16) && !(enc->enc_pic.enable_render_size)) - enc->enc_pic.session_init.aligned_picture_height = av1_height + 2; - - enc->enc_pic.av1.coded_width = enc->enc_pic.session_init.aligned_picture_width; - enc->enc_pic.av1.coded_height = enc->enc_pic.session_init.aligned_picture_height; - - enc->enc_pic.session_init.padding_width = - enc->enc_pic.session_init.aligned_picture_width - - enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.session_init.padding_height = - enc->enc_pic.session_init.aligned_picture_height - av1_height; - - if (enc->enc_pic.enable_render_size) - enc->enc_pic.enable_render_size = - (enc->enc_pic.session_init.aligned_picture_width != - enc->enc_pic.render_width) || - (enc->enc_pic.session_init.aligned_picture_height != - enc->enc_pic.render_height); - - if (sscreen->info.vcn_ip_version == VCN_4_0_2 || - sscreen->info.vcn_ip_version == VCN_4_0_5 || - sscreen->info.vcn_ip_version == VCN_4_0_6) - enc->enc_pic.session_init.WA_flags = 1; - - break; - default: - assert(0); - break; - } - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode; 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 c5beec49731..b2d1a9b8b18 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_5_0.c @@ -959,55 +959,6 @@ static void radeon_enc_obu_instruction(struct radeon_encoder *enc) static void radeon_enc_session_init(struct radeon_encoder *enc) { - switch (u_reduce_video_profile(enc->base.profile)) { - case PIPE_VIDEO_FORMAT_MPEG4_AVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_H264; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 16); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_HEVC: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_HEVC; - enc->enc_pic.session_init.aligned_picture_width = align(enc->base.width, 64); - enc->enc_pic.session_init.aligned_picture_height = align(enc->base.height, 16); - enc->enc_pic.session_init.padding_width = - (enc->enc_pic.crop_left + enc->enc_pic.crop_right) * 2; - enc->enc_pic.session_init.padding_height = - (enc->enc_pic.crop_top + enc->enc_pic.crop_bottom) * 2; - break; - case PIPE_VIDEO_FORMAT_AV1: - enc->enc_pic.session_init.encode_standard = RENCODE_ENCODE_STANDARD_AV1; - enc->enc_pic.session_init.aligned_picture_width = - align(enc->enc_pic.pic_width_in_luma_samples, 8); - enc->enc_pic.session_init.aligned_picture_height = - align(enc->enc_pic.pic_height_in_luma_samples, 2); - - enc->enc_pic.av1.coded_width = enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.av1.coded_height = enc->enc_pic.pic_height_in_luma_samples; - - enc->enc_pic.session_init.padding_width = - enc->enc_pic.session_init.aligned_picture_width - - enc->enc_pic.pic_width_in_luma_samples; - enc->enc_pic.session_init.padding_height = - enc->enc_pic.session_init.aligned_picture_height - - enc->enc_pic.pic_height_in_luma_samples; - - if (enc->enc_pic.enable_render_size) - enc->enc_pic.enable_render_size = - (enc->enc_pic.session_init.aligned_picture_width != - enc->enc_pic.render_width) || - (enc->enc_pic.session_init.aligned_picture_height != - enc->enc_pic.render_height); - break; - default: - assert(0); - break; - } - enc->enc_pic.session_init.slice_output_enabled = 0; enc->enc_pic.session_init.display_remote = 0; enc->enc_pic.session_init.pre_encode_mode = enc->enc_pic.quality_modes.pre_encode_mode;