From 10ac8567de5f512d5fc0f90ecc831ebdf1d06870 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Sun, 26 Jan 2025 13:26:09 +0100 Subject: [PATCH] radeonsi/vcn: Support EFC with encode processing Reviewed-by: Ruijing Dong Part-of: --- src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 154 +++++++++++++++--- src/gallium/drivers/radeonsi/radeon_vcn_enc.h | 5 + 2 files changed, 134 insertions(+), 25 deletions(-) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index 90d952b3ab7..6dad8f5187b 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -419,28 +419,23 @@ static void radeon_vcn_enc_h264_get_slice_ctrl_param(struct radeon_encoder *enc, enc->enc_pic.slice_ctrl.num_mbs_per_slice = num_mbs_in_slice; } -static void radeon_vcn_enc_get_output_format_param(struct radeon_encoder *enc, bool full_range) +static void radeon_vcn_enc_get_output_format_param(struct radeon_encoder *enc) { switch (enc->enc_pic.bit_depth_luma_minus8) { case 2: /* 10 bits */ - enc->enc_pic.enc_output_format.output_color_volume = RENCODE_COLOR_VOLUME_G22_BT709; - enc->enc_pic.enc_output_format.output_color_range = full_range ? - RENCODE_COLOR_RANGE_FULL : RENCODE_COLOR_RANGE_STUDIO; - enc->enc_pic.enc_output_format.output_chroma_location = RENCODE_CHROMA_LOCATION_INTERSTITIAL; enc->enc_pic.enc_output_format.output_color_bit_depth = RENCODE_COLOR_BIT_DEPTH_10_BIT; break; default: /* 8 bits */ - enc->enc_pic.enc_output_format.output_color_volume = RENCODE_COLOR_VOLUME_G22_BT709; - enc->enc_pic.enc_output_format.output_color_range = full_range ? - RENCODE_COLOR_RANGE_FULL : RENCODE_COLOR_RANGE_STUDIO; - enc->enc_pic.enc_output_format.output_chroma_location = RENCODE_CHROMA_LOCATION_INTERSTITIAL; enc->enc_pic.enc_output_format.output_color_bit_depth = RENCODE_COLOR_BIT_DEPTH_8_BIT; break; } + + enc->enc_pic.enc_output_format.output_color_volume = enc->output_color_volume; + enc->enc_pic.enc_output_format.output_color_range = enc->output_color_range; + enc->enc_pic.enc_output_format.output_chroma_location = RENCODE_CHROMA_LOCATION_INTERSTITIAL; } -static void radeon_vcn_enc_get_input_format_param(struct radeon_encoder *enc, - struct pipe_picture_desc *pic_base) +static void radeon_vcn_enc_get_input_format_param(struct radeon_encoder *enc) { switch (enc->source->buffer_format) { case PIPE_FORMAT_P010: @@ -486,8 +481,8 @@ static void radeon_vcn_enc_get_input_format_param(struct radeon_encoder *enc, break; } - enc->enc_pic.enc_input_format.input_color_volume = RENCODE_COLOR_VOLUME_G22_BT709; - enc->enc_pic.enc_input_format.input_color_range = RENCODE_COLOR_RANGE_FULL; + enc->enc_pic.enc_input_format.input_color_volume = enc->input_color_volume; + enc->enc_pic.enc_input_format.input_color_range = enc->input_color_range; enc->enc_pic.enc_input_format.input_chroma_location = RENCODE_CHROMA_LOCATION_INTERSTITIAL; } @@ -554,8 +549,8 @@ 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_slice_ctrl_param(enc, pic); - radeon_vcn_enc_get_input_format_param(enc, &pic->base); - radeon_vcn_enc_get_output_format_param(enc, pic->seq.video_full_range_flag); + radeon_vcn_enc_get_input_format_param(enc); + radeon_vcn_enc_get_output_format_param(enc); use_filter = enc->enc_pic.h264_deblock.disable_deblocking_filter_idc != 1; radeon_vcn_enc_get_intra_refresh_param(enc, use_filter, &pic->intra_refresh); @@ -783,8 +778,8 @@ static void radeon_vcn_enc_hevc_get_param(struct radeon_encoder *enc, 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); - radeon_vcn_enc_get_input_format_param(enc, &pic->base); - radeon_vcn_enc_get_output_format_param(enc, pic->seq.video_full_range_flag); + radeon_vcn_enc_get_input_format_param(enc); + radeon_vcn_enc_get_output_format_param(enc); radeon_vcn_enc_get_intra_refresh_param(enc, !(enc->enc_pic.hevc_deblock.deblocking_filter_disabled), &pic->intra_refresh); @@ -1061,8 +1056,8 @@ static void radeon_vcn_enc_av1_get_param(struct radeon_encoder *enc, 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); - radeon_vcn_enc_get_input_format_param(enc, &pic->base); - radeon_vcn_enc_get_output_format_param(enc, pic->seq.color_config.color_range); + radeon_vcn_enc_get_input_format_param(enc); + radeon_vcn_enc_get_output_format_param(enc); /* loop filter enabled all the time */ radeon_vcn_enc_get_intra_refresh_param(enc, true, @@ -1464,10 +1459,17 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder, { struct radeon_encoder *enc = (struct radeon_encoder *)encoder; struct si_screen *sscreen = (struct si_screen *)enc->screen; - struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; + struct vl_video_buffer *vid_buf; unsigned dpb_slots = 0; - enc->source = source; + if (enc->efc_source) { + enc->source = enc->efc_source; + enc->efc_source = NULL; + } else { + enc->source = source; + enc->input_color_volume = enc->output_color_volume = RENCODE_COLOR_VOLUME_G22_BT709; + enc->input_color_range = enc->output_color_range = RENCODE_COLOR_RANGE_FULL; + } enc->need_rate_control = false; enc->need_rc_per_pic = false; @@ -1576,9 +1578,11 @@ static void radeon_enc_begin_frame(struct pipe_video_codec *encoder, } } - if (source->buffer_format == PIPE_FORMAT_NV12 || - source->buffer_format == PIPE_FORMAT_P010 || - source->buffer_format == PIPE_FORMAT_P016) { + vid_buf = (struct vl_video_buffer *)enc->source; + + if (enc->source->buffer_format == PIPE_FORMAT_NV12 || + enc->source->buffer_format == PIPE_FORMAT_P010 || + enc->source->buffer_format == PIPE_FORMAT_P016) { enc->get_buffer(vid_buf->resources[0], &enc->handle, &enc->luma); enc->get_buffer(vid_buf->resources[1], NULL, &enc->chroma); } @@ -1748,7 +1752,7 @@ static void radeon_enc_encode_bitstream(struct pipe_video_codec *encoder, struct pipe_resource *destination, void **fb) { struct radeon_encoder *enc = (struct radeon_encoder *)encoder; - struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)source; + struct vl_video_buffer *vid_buf = (struct vl_video_buffer *)enc->source; if (enc->error) return; @@ -1781,6 +1785,105 @@ static void radeon_enc_encode_bitstream(struct pipe_video_codec *encoder, enc->encode(enc); } +static bool radeon_vcn_enc_efc_supported(struct radeon_encoder *enc, + struct pipe_video_buffer *src, + const struct pipe_vpp_desc *vpp) +{ + struct si_screen *sscreen = (struct si_screen *)enc->screen; + struct si_texture *tex = (struct si_texture *)((struct vl_video_buffer *)src)->resources[0]; + enum pipe_format src_format = src->buffer_format; + enum pipe_format dst_format = vpp->dst->buffer_format; + + if (sscreen->info.vcn_ip_version < VCN_2_0_0 || + sscreen->info.vcn_ip_version == VCN_2_2_0 || + sscreen->multimedia_debug_flags & DBG(NO_EFC)) + return false; + + if (vpp->orientation != PIPE_VIDEO_VPP_ORIENTATION_DEFAULT || + vpp->blend.mode != PIPE_VIDEO_VPP_BLEND_MODE_NONE) + return false; + + if (vpp->src_region.x0 || vpp->src_region.y0 || + vpp->dst_region.x0 || vpp->dst_region.y0 || + vpp->src_region.x1 != vpp->dst_region.x1 || + vpp->src_region.y1 != vpp->dst_region.y1) + return false; + + if (vpp->in_colors_standard != vpp->out_colors_standard || + (vpp->in_colors_standard != PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE && + vpp->in_colors_standard != PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709)) + return false; + + /* DCC not supported */ + if (tex->surface.meta_offset) + return false; + + const bool input_8bit = + src_format == PIPE_FORMAT_B8G8R8A8_UNORM || + src_format == PIPE_FORMAT_B8G8R8X8_UNORM || + src_format == PIPE_FORMAT_R8G8B8A8_UNORM || + src_format == PIPE_FORMAT_R8G8B8X8_UNORM; + + const bool input_10bit = + src_format == PIPE_FORMAT_B10G10R10A2_UNORM || + src_format == PIPE_FORMAT_B10G10R10X2_UNORM || + src_format == PIPE_FORMAT_R10G10B10A2_UNORM || + src_format == PIPE_FORMAT_R10G10B10X2_UNORM; + + /* Unsupported input format */ + if (!input_8bit && !input_10bit) + return false; + + if (input_8bit && dst_format != PIPE_FORMAT_NV12) + return false; + + if (input_10bit && dst_format != PIPE_FORMAT_NV12 && dst_format != PIPE_FORMAT_P010) + return false; + + return true; +} + +static uint32_t radeon_vcn_enc_color_volume(enum pipe_video_vpp_color_standard_type color_standard) +{ + switch (color_standard) { + case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_NONE: + case PIPE_VIDEO_VPP_COLOR_STANDARD_TYPE_BT709: + return RENCODE_COLOR_VOLUME_G22_BT709; + default: + assert(0); + return 0; + } +} + +static uint32_t radeon_vcn_enc_color_range(enum pipe_video_vpp_color_range color_range) +{ + switch (color_range) { + case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED: + return RENCODE_COLOR_RANGE_STUDIO; + case PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL: + default: + return RENCODE_COLOR_RANGE_FULL; + } +} + +static int radeon_enc_process_frame(struct pipe_video_codec *encoder, + struct pipe_video_buffer *source, + const struct pipe_vpp_desc *vpp) +{ + struct radeon_encoder *enc = (struct radeon_encoder *)encoder; + + if (radeon_vcn_enc_efc_supported(enc, source, vpp)) { + enc->efc_source = source; + enc->input_color_volume = radeon_vcn_enc_color_volume(vpp->in_colors_standard); + enc->input_color_range = radeon_vcn_enc_color_range(vpp->in_color_range); + enc->output_color_volume = radeon_vcn_enc_color_volume(vpp->out_colors_standard); + enc->output_color_range = radeon_vcn_enc_color_range(vpp->out_color_range); + return 0; + } + + return 1; +} + static int radeon_enc_end_frame(struct pipe_video_codec *encoder, struct pipe_video_buffer *source, struct pipe_picture_desc *picture) { @@ -1998,6 +2101,7 @@ struct pipe_video_codec *radeon_create_encoder(struct pipe_context *context, enc->base.destroy = radeon_enc_destroy; enc->base.begin_frame = radeon_enc_begin_frame; enc->base.encode_bitstream = radeon_enc_encode_bitstream; + enc->base.process_frame = radeon_enc_process_frame; enc->base.end_frame = radeon_enc_end_frame; enc->base.flush = radeon_enc_flush; enc->base.get_feedback = radeon_enc_get_feedback; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index 31e7331f55c..ce6303fb90e 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -231,6 +231,11 @@ struct radeon_encoder { struct radeon_surf *luma; struct radeon_surf *chroma; struct pipe_video_buffer *source; + struct pipe_video_buffer *efc_source; + unsigned input_color_volume; + unsigned input_color_range; + unsigned output_color_volume; + unsigned output_color_range; struct pb_buffer_lean *bs_handle; unsigned bs_size;