From afcff6f33330c8a0850f0fdd1002d334f7145406 Mon Sep 17 00:00:00 2001 From: Thong Thai Date: Thu, 27 Oct 2022 20:09:43 -0400 Subject: [PATCH] radeonsi/vcn/enc: add encoder statistics support Signed-off-by: Thong Thai Reviewed-by: Boyuan Zhang Part-of: --- src/gallium/drivers/radeonsi/radeon_vcn_enc.c | 13 ++++++++ src/gallium/drivers/radeonsi/radeon_vcn_enc.h | 32 +++++++++++++++++++ .../drivers/radeonsi/radeon_vcn_enc_1_2.c | 15 +++++++++ .../drivers/radeonsi/radeon_vcn_enc_2_0.c | 3 ++ .../drivers/radeonsi/radeon_vcn_enc_4_0.c | 4 +++ 5 files changed, 67 insertions(+) diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c index d286e3520d0..6c53d9ba512 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.c @@ -608,6 +608,8 @@ 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; + enc->get_buffer(destination, &enc->bs_handle, NULL); enc->bs_size = destination->width0; @@ -618,6 +620,17 @@ static void radeon_enc_encode_bitstream(struct pipe_video_codec *encoder, return; } + if (vid_buf->base.associated_data) { + enc->get_buffer(vid_buf->base.associated_data, &enc->stats, NULL); + if (enc->stats->size < sizeof(rvcn_encode_stats_type_0_t)) { + RVID_ERR("Encoder statistics output buffer is too small.\n"); + enc->stats = NULL; + } + vid_buf->base.associated_data = NULL; + } + else + enc->stats = NULL; + enc->need_feedback = true; enc->encode(enc); } diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h index 991b3a58788..f3c56f3d236 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc.h @@ -133,6 +133,9 @@ #define RENCODE_FEEDBACK_BUFFER_MODE_LINEAR 0 #define RENCODE_FEEDBACK_BUFFER_MODE_CIRCULAR 1 +#define RENCODE_STATISTICS_TYPE_NONE 0 +#define RENCODE_STATISTICS_TYPE_0 1 + #define RENCODE_MAX_NUM_TEMPORAL_LAYERS 4 #define PIPE_H265_ENC_CTB_SIZE 64 @@ -417,6 +420,31 @@ typedef struct rvcn_enc_feedback_buffer_s { uint32_t feedback_data_size; } rvcn_enc_feedback_buffer_t; +typedef struct rvcn_encode_stats_type_0_s +{ + uint32_t qp_frame; + uint32_t qp_avg_ctb; + uint32_t qp_max_ctb; + uint32_t qp_min_ctb; + uint32_t pix_intra; + uint32_t pix_inter; + uint32_t pix_skip; + uint32_t bitcount_residual; + uint32_t bitcount_all_minus_header; + uint32_t bitcount_motion; + uint32_t bitcount_inter; + uint32_t bitcount_intra; + uint32_t mv_x_frame; + uint32_t mv_y_frame; +} rvcn_encode_stats_type_0_t; + +typedef struct rvcn_encode_stats_s +{ + uint32_t encode_stats_type; + uint32_t encode_stats_buffer_address_hi; + uint32_t encode_stats_buffer_address_lo; +} rvcn_enc_stats_t; + typedef struct rvcn_enc_cmd_s { uint32_t session_info; uint32_t task_info; @@ -444,6 +472,7 @@ typedef struct rvcn_enc_cmd_s { uint32_t deblocking_filter_h264; uint32_t input_format; uint32_t output_format; + uint32_t enc_statistics; } rvcn_enc_cmd_t; typedef struct rvcn_enc_quality_modes_s @@ -543,6 +572,7 @@ struct radeon_enc_pic { rvcn_enc_feedback_buffer_t fb_buf; rvcn_enc_intra_refresh_t intra_ref; rvcn_enc_encode_params_t enc_params; + rvcn_enc_stats_t enc_statistics; }; struct radeon_encoder { @@ -586,6 +616,7 @@ struct radeon_encoder { void (*encode_headers)(struct radeon_encoder *enc); void (*input_format)(struct radeon_encoder *enc); void (*output_format)(struct radeon_encoder *enc); + void (*encode_statistics)(struct radeon_encoder *enc); /* mq is used for preversing multiple queue ibs */ void (*mq_begin)(struct radeon_encoder *enc); void (*mq_encode)(struct radeon_encoder *enc); @@ -610,6 +641,7 @@ struct radeon_encoder { struct rvid_buffer *fb; struct rvid_buffer *dpb; struct radeon_enc_pic enc_pic; + struct pb_buffer *stats; rvcn_enc_cmd_t cmd; unsigned alignment; 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 6ccc884ecc7..9ca28cca3b8 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_1_2.c @@ -53,6 +53,7 @@ #define RENCODE_IB_PARAM_VIDEO_BITSTREAM_BUFFER 0x0000000e #define RENCODE_IB_PARAM_FEEDBACK_BUFFER 0x00000010 #define RENCODE_IB_PARAM_DIRECT_OUTPUT_NALU 0x00000020 +#define RENCODE_IB_PARAM_ENCODE_STATISTICS 0x00000024 #define RENCODE_HEVC_IB_PARAM_SLICE_CONTROL 0x00100001 #define RENCODE_HEVC_IB_PARAM_SPEC_MISC 0x00100002 @@ -1243,6 +1244,18 @@ static void radeon_enc_encode_params_h264(struct radeon_encoder *enc) RADEON_ENC_END(); } +static void radeon_enc_encode_statistics(struct radeon_encoder *enc) +{ + if (!enc->stats) return; + + enc->enc_pic.enc_statistics.encode_stats_type = RENCODE_STATISTICS_TYPE_0; + + RADEON_ENC_BEGIN(enc->cmd.enc_statistics); + RADEON_ENC_CS(enc->enc_pic.enc_statistics.encode_stats_type); + RADEON_ENC_WRITE(enc->stats, RADEON_DOMAIN_GTT, 0); + RADEON_ENC_END(); +} + static void radeon_enc_op_init(struct radeon_encoder *enc) { RADEON_ENC_BEGIN(RENCODE_IB_OP_INITIALIZE); @@ -1493,6 +1506,7 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc) enc->op_preset = radeon_enc_op_preset; enc->encode_params = radeon_enc_encode_params; enc->session_init = radeon_enc_session_init; + enc->encode_statistics = radeon_enc_encode_statistics; enc->nalu_aud = radeon_enc_nalu_aud; if (u_reduce_video_profile(enc->base.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { @@ -1540,6 +1554,7 @@ void radeon_enc_1_2_init(struct radeon_encoder *enc) enc->cmd.spec_misc_h264 = RENCODE_H264_IB_PARAM_SPEC_MISC; enc->cmd.enc_params_h264 = RENCODE_H264_IB_PARAM_ENCODE_PARAMS; enc->cmd.deblocking_filter_h264 = RENCODE_H264_IB_PARAM_DEBLOCKING_FILTER; + enc->cmd.enc_statistics = RENCODE_IB_PARAM_ENCODE_STATISTICS; enc->enc_pic.session_info.interface_version = ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) | 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 72606b8d82c..1dc5c859f9e 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_2_0.c @@ -54,6 +54,7 @@ #define RENCODE_IB_PARAM_ENCODE_CONTEXT_BUFFER 0x00000011 #define RENCODE_IB_PARAM_VIDEO_BITSTREAM_BUFFER 0x00000012 #define RENCODE_IB_PARAM_FEEDBACK_BUFFER 0x00000015 +#define RENCODE_IB_PARAM_ENCODE_STATISTICS 0x00000019 #define RENCODE_HEVC_IB_PARAM_SLICE_CONTROL 0x00100001 #define RENCODE_HEVC_IB_PARAM_SPEC_MISC 0x00100002 @@ -513,6 +514,7 @@ static void encode(struct radeon_encoder *enc) enc->ctx(enc); enc->bitstream(enc); enc->feedback(enc); + enc->encode_statistics(enc); enc->intra_refresh(enc); enc->input_format(enc); enc->output_format(enc); @@ -563,6 +565,7 @@ void radeon_enc_2_0_init(struct radeon_encoder *enc) enc->cmd.spec_misc_h264 = RENCODE_H264_IB_PARAM_SPEC_MISC; enc->cmd.enc_params_h264 = RENCODE_H264_IB_PARAM_ENCODE_PARAMS; enc->cmd.deblocking_filter_h264 = RENCODE_H264_IB_PARAM_DEBLOCKING_FILTER; + enc->cmd.enc_statistics = RENCODE_IB_PARAM_ENCODE_STATISTICS; enc->enc_pic.session_info.interface_version = ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) | 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 0ec5869f22a..4015d0af48a 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_enc_4_0.c @@ -37,6 +37,8 @@ #define RENCODE_FW_INTERFACE_MAJOR_VERSION 1 #define RENCODE_FW_INTERFACE_MINOR_VERSION 0 +#define RENCODE_IB_PARAM_ENCODE_STATISTICS 0x0000001a + static void radeon_enc_sq_begin(struct radeon_encoder *enc) { rvcn_sq_header(&enc->cs, &enc->sq, true); @@ -109,6 +111,8 @@ void radeon_enc_4_0_init(struct radeon_encoder *enc) enc->encode = radeon_enc_sq_encode; enc->destroy = radeon_enc_sq_destroy; + enc->cmd.enc_statistics = RENCODE_IB_PARAM_ENCODE_STATISTICS; + enc->enc_pic.session_info.interface_version = ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) | (RENCODE_FW_INTERFACE_MINOR_VERSION << RENCODE_IF_MINOR_VERSION_SHIFT));