diff --git a/src/amd/common/ac_vcn_dec.h b/src/amd/common/ac_vcn_dec.h index 8ee00ad10a5..a87533d0638 100644 --- a/src/amd/common/ac_vcn_dec.h +++ b/src/amd/common/ac_vcn_dec.h @@ -41,6 +41,7 @@ #define RDECODE_IB_PARAM_UMD_COPY_MEMORY (0x00000008) #define RDECODE_IB_PARAM_UMD_WRITE_MEMORY (0x00000009) #define RDECODE_IB_PARAM_FEEDBACK_BUFFER (0x0000000A) +#define RDECODE_IB_PARAM_DYNAMIC_REFLIST_BUFFER (0x0000000C) #define RDECODE_CMDBUF_FLAGS_MSG_BUFFER (0x00000001) #define RDECODE_CMDBUF_FLAGS_DPB_BUFFER (0x00000002) @@ -63,6 +64,7 @@ #define RDECODE_CMDBUF_FLAGS_RESERVED_SIZE_INFO_BUFFER (0x00040000) #define RDECODE_CMDBUF_FLAGS_LUMA_HIST_BUFFER (0x00080000) #define RDECODE_CMDBUF_FLAGS_SESSION_CONTEXT_BUFFER (0x00100000) +#define RDECODE_CMDBUF_FLAGS_REF_BUFFER (0x00200000) #define RDECODE_CMD_MSG_BUFFER 0x00000000 #define RDECODE_CMD_DPB_BUFFER 0x00000001 @@ -155,6 +157,7 @@ #define RDECODE_FLAGS_USE_DYNAMIC_DPB_MASK 0x00000001 #define RDECODE_FLAGS_USE_PAL_MASK 0x00000008 #define RDECODE_FLAGS_DPB_RESIZE_MASK 0x00000100 +#define RDECODE_FLAGS_UNIFIED_DT_MASK 0x00000200 #define mmUVD_JPEG_CNTL 0x0200 #define mmUVD_JPEG_CNTL_BASE_IDX 1 @@ -593,6 +596,33 @@ typedef struct rvcn_dec_message_dynamic_dpb_t2_s { unsigned int dpbAddrHi[16]; } rvcn_dec_message_dynamic_dpb_t2_t; +typedef struct rvcn_dec_ref_buffer_s +{ + unsigned int index; + unsigned int y_pitch; + unsigned int y_aligned_height; + unsigned int y_aligned_size; + unsigned int y_ref_buffer_address_hi; + unsigned int y_ref_buffer_address_lo; + unsigned int uv_pitch; + unsigned int uv_aligned_height; + unsigned int uv_aligned_size; + unsigned int uv_ref_buffer_address_hi; + unsigned int uv_ref_buffer_address_lo; + unsigned int v_pitch; + unsigned int v_aligned_height; + unsigned int v_aligned_size; + unsigned int v_ref_buffer_address_hi; + unsigned int v_ref_buffer_address_lo; +} rvcn_dec_ref_buffer_t; + +typedef struct rvcn_dec_ref_buffers_header_s +{ + unsigned int size; + unsigned int num_bufs; + rvcn_dec_ref_buffer_t pBufs[]; +} rvcn_dec_ref_buffers_header_t; + typedef struct rvcn_dec_message_hevc_direct_ref_list_s { unsigned int num_direct_reflist; unsigned char multi_direct_reflist[128][2][15]; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c index a395a076068..dc5b5ce98cc 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c @@ -75,7 +75,7 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, struct pipe_h264_picture_desc *pic) { rvcn_dec_message_avc_t result; - unsigned i, j, k; + unsigned i, j, k, num_refs = 0; memset(&result, 0, sizeof(result)); switch (pic->base.profile) { @@ -104,7 +104,7 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, result.sps_info_flags |= pic->pps->sps->mb_adaptive_frame_field_flag << 1; result.sps_info_flags |= pic->pps->sps->frame_mbs_only_flag << 2; result.sps_info_flags |= pic->pps->sps->delta_pic_order_always_zero_flag << 3; - result.sps_info_flags |= ((dec->dpb_type == DPB_DYNAMIC_TIER_2) ? 0 : 1) + result.sps_info_flags |= ((dec->dpb_type >= DPB_DYNAMIC_TIER_2) ? 0 : 1) << RDECODE_SPS_INFO_H264_EXTENSION_SUPPORT_FLAG_SHIFT; result.chroma_format = pic->pps->sps->chroma_format_idc; @@ -150,7 +150,7 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, result.non_existing_frame_flags = 0; result.used_for_reference_flags = 0; - if (dec->dpb_type != DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type < DPB_DYNAMIC_TIER_2) { result.decoded_pic_idx = pic->frame_num; goto end; } @@ -203,6 +203,8 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, result.ref_frame_list[i] |= 0x80; result.curr_pic_ref_frame_num++; + dec->ref_codec.bufs[num_refs].buf = pic->ref[i]; + dec->ref_codec.bufs[num_refs++].index = result.ref_frame_list[i]; for (j = 0; j < ARRAY_SIZE(dec->h264_valid_ref_num); j++) { if ((dec->h264_valid_ref_num[j] != (unsigned)-1) @@ -258,11 +260,11 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, pic->field_pic_flag && !pic->bottom_field_flag ? (unsigned) -1 : result.curr_field_order_cnt_list[1]; - if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type >= DPB_DYNAMIC_TIER_2) { dec->ref_codec.bts = CODEC_8_BITS; dec->ref_codec.index = result.decoded_pic_idx; dec->ref_codec.ref_size = 16; - dec->ref_codec.num_refs = result.curr_pic_ref_frame_num; + dec->ref_codec.num_refs = num_refs; STATIC_ASSERT(sizeof(dec->ref_codec.ref_list) == sizeof(result.ref_frame_list)); memcpy(dec->ref_codec.ref_list, result.ref_frame_list, sizeof(result.ref_frame_list)); } @@ -399,7 +401,8 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, if (ref) { ref_pic = (uintptr_t)vl_video_buffer_get_associated_data(ref, &dec->base); - num_refs++; + dec->ref_codec.bufs[num_refs].buf = pic->ref[i]; + dec->ref_codec.bufs[num_refs++].index = ref_pic; } else ref_pic = 0x7F; result.ref_pic_list[i] = ref_pic; @@ -449,7 +452,7 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, } } - if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type >= DPB_DYNAMIC_TIER_2) { dec->ref_codec.bts = (pic->base.profile == PIPE_VIDEO_PROFILE_HEVC_MAIN_10) ? CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_idx; @@ -630,7 +633,8 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, uintptr_t ref_frame; if (pic->ref[i]) { ref_frame = (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base); - num_refs++; + dec->ref_codec.bufs[num_refs].buf = pic->ref[i]; + dec->ref_codec.bufs[num_refs++].index = ref_frame; } else ref_frame = 0x7f; result.ref_frame_map[i] = ref_frame; @@ -654,7 +658,7 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, } } - if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type >= DPB_DYNAMIC_TIER_2) { dec->ref_codec.bts = (pic->base.profile == PIPE_VIDEO_PROFILE_VP9_PROFILE2) ? CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_pic_idx; @@ -939,7 +943,8 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, uintptr_t ref_frame; if (pic->ref[i]) { ref_frame = (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base); - num_refs++; + dec->ref_codec.bufs[num_refs].buf = pic->ref[i]; + dec->ref_codec.bufs[num_refs++].index = ref_frame; } else ref_frame = 0x7f; result.ref_frame_map[i] = ref_frame; @@ -1087,13 +1092,19 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, result.tile_info[i].size = pic->slice_parameter.slice_data_size[i]; } - if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type >= DPB_DYNAMIC_TIER_2) { dec->ref_codec.bts = pic->picture_parameter.bit_depth_idx; dec->ref_codec.index = result.curr_pic_idx; dec->ref_codec.ref_size = 8; dec->ref_codec.num_refs = num_refs; memset(dec->ref_codec.ref_list, 0x7f, sizeof(dec->ref_codec.ref_list)); memcpy(dec->ref_codec.ref_list, result.ref_frame_map, sizeof(result.ref_frame_map)); + + /* Film grain is applied to decode target only. */ + if (dec->dpb_type == DPB_DYNAMIC_TIER_3 && pic->film_grain_target) { + dec->ref_codec.bufs[dec->ref_codec.num_refs].buf = target; + dec->ref_codec.bufs[dec->ref_codec.num_refs++].index = result.curr_pic_idx; + } } return result; @@ -1468,6 +1479,22 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn return 0; } +static bool rvcn_dec_can_use_udt(struct pipe_video_buffer *target, struct pipe_picture_desc *picture) +{ + struct si_texture *luma = (struct si_texture *)((struct vl_video_buffer *)target)->resources[0]; + + /* UDT requires tiling */ + if (luma->surface.is_linear) + return false; + + /* UDT can't be used with 12bit AV1 */ + if (u_reduce_video_profile(picture->profile) == PIPE_VIDEO_FORMAT_AV1 && + ((struct pipe_av1_picture_desc *)picture)->picture_parameter.bit_depth_idx == 2) + return false; + + return true; +} + static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec, struct pipe_video_buffer *target, struct pipe_picture_desc *picture) @@ -1492,6 +1519,16 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec rvcn_dec_message_dynamic_dpb_t2_t *dynamic_dpb_t2 = NULL; rvcn_dec_message_hevc_direct_ref_list_t *hevc_reflist = NULL; bool dpb_resize = false; + + if (dec->stream_type == RDECODE_CODEC_AV1) + rvcn_dec_av1_film_grain_surface(&out_surf, (struct pipe_av1_picture_desc *)picture); + + luma = (struct si_texture *)((struct vl_video_buffer *)out_surf)->resources[0]; + chroma = (struct si_texture *)((struct vl_video_buffer *)out_surf)->resources[1]; + + if (dec->frame_number == 1 && dec->dpb_type == DPB_DYNAMIC_TIER_3 && !rvcn_dec_can_use_udt(out_surf, picture)) + dec->dpb_type = DPB_DYNAMIC_TIER_2; + header = dec->msg; sizes += sizeof(rvcn_dec_message_header_t); @@ -1503,7 +1540,7 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec sizes += sizeof(rvcn_dec_message_index_t); } - if (dec->dpb_type >= DPB_DYNAMIC_TIER_1) { + if (dec->dpb_type == DPB_DYNAMIC_TIER_1 || dec->dpb_type == DPB_DYNAMIC_TIER_2) { index_dynamic_dpb = (void*)header + sizes; sizes += sizeof(rvcn_dec_message_index_t); } @@ -1523,7 +1560,7 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec sizes += sizeof(rvcn_dec_message_drm_t); } - if (dec->dpb_type >= DPB_DYNAMIC_TIER_1) { + if (dec->dpb_type == DPB_DYNAMIC_TIER_1 || dec->dpb_type == DPB_DYNAMIC_TIER_2) { offset_dynamic_dpb = sizes; if (dec->dpb_type == DPB_DYNAMIC_TIER_1) { dynamic_dpb = (void*)header + sizes; @@ -1570,7 +1607,7 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec ++header->num_buffers; } - if (dec->dpb_type >= DPB_DYNAMIC_TIER_1) { + if (dec->dpb_type == DPB_DYNAMIC_TIER_1 || dec->dpb_type == DPB_DYNAMIC_TIER_2) { index_dynamic_dpb->message_id = RDECODE_MESSAGE_DYNAMIC_DPB; index_dynamic_dpb->offset = offset_dynamic_dpb; index_dynamic_dpb->filled = 0; @@ -1594,9 +1631,12 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec decode->width_in_samples = dec->base.width; decode->height_in_samples = dec->base.height; + if (dec->dpb_type == DPB_DYNAMIC_TIER_3) + decode->decode_flags = RDECODE_FLAGS_UNIFIED_DT_MASK; + decode->bsd_size = align(dec->bs_size, 128); - if (dec->dpb_type != DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type < DPB_DYNAMIC_TIER_2) { bool r; if (!dec->dpb.res && dec->dpb_size) { if (encrypted) { @@ -1710,13 +1750,7 @@ static struct pb_buffer_lean *rvcn_dec_message_decode(struct radeon_decoder *dec dec->ws->cs_flush(&dec->cs, RADEON_FLUSH_TOGGLE_SECURE_SUBMISSION, NULL); } - if (dec->stream_type == RDECODE_CODEC_AV1) - rvcn_dec_av1_film_grain_surface(&out_surf, (struct pipe_av1_picture_desc *)picture); - - luma = (struct si_texture *)((struct vl_video_buffer *)out_surf)->resources[0]; - chroma = (struct si_texture *)((struct vl_video_buffer *)out_surf)->resources[1]; - - decode->dpb_size = (dec->dpb_type != DPB_DYNAMIC_TIER_2) ? dec->dpb.res->buf->size : 0; + decode->dpb_size = (dec->dpb_type < DPB_DYNAMIC_TIER_2) ? dec->dpb.res->buf->size : 0; /* When texture being created, the bo will be created with total size of planes, * and all planes point to the same buffer */ @@ -2500,6 +2534,50 @@ static void radeon_dec_decode_bitstream(struct pipe_video_codec *decoder, } } +static void send_ref_buffers(struct radeon_decoder *dec) +{ + uint32_t size = sizeof(rvcn_dec_ref_buffers_header_t) + + sizeof(rvcn_dec_ref_buffer_t) * dec->ref_codec.num_refs; + rvcn_decode_ib_package_t *ib_header = + (rvcn_decode_ib_package_t *)&(dec->cs.current.buf[dec->cs.current.cdw]); + + ib_header->package_size = size + sizeof(rvcn_decode_ib_package_t); + ib_header->package_type = RDECODE_IB_PARAM_DYNAMIC_REFLIST_BUFFER; + + dec->cs.current.cdw += 2; + + rvcn_dec_ref_buffers_header_t *refs = + (rvcn_dec_ref_buffers_header_t *)&(dec->cs.current.buf[dec->cs.current.cdw]); + + dec->cs.current.cdw += size / 4; + + refs->size = size; + refs->num_bufs = dec->ref_codec.num_refs; + + for (uint32_t i = 0; i < refs->num_bufs; i++) { + struct vl_video_buffer *buf = (struct vl_video_buffer *)dec->ref_codec.bufs[i].buf; + struct si_texture *y = (struct si_texture *)buf->resources[0]; + struct si_texture *uv = (struct si_texture *)buf->resources[1]; + uint64_t y_addr = y->buffer.gpu_address + y->surface.u.gfx9.surf_offset; + uint64_t uv_addr = uv->buffer.gpu_address + uv->surface.u.gfx9.surf_offset; + rvcn_dec_ref_buffer_t *ref = &refs->pBufs[i]; + ref->index = dec->ref_codec.bufs[i].index; + ref->y_pitch = y->surface.u.gfx9.surf_pitch; + ref->y_aligned_height = y->surface.u.gfx9.surf_height; + ref->y_aligned_size = y->surface.u.gfx9.surf_slice_size; + ref->y_ref_buffer_address_hi = y_addr >> 32; + ref->y_ref_buffer_address_lo = y_addr; + ref->uv_pitch = uv->surface.u.gfx9.surf_pitch; + ref->uv_aligned_height = uv->surface.u.gfx9.surf_height; + ref->uv_aligned_size = uv->surface.u.gfx9.surf_slice_size; + ref->uv_ref_buffer_address_hi = uv_addr >> 32; + ref->uv_ref_buffer_address_lo = uv_addr; + dec->ws->cs_add_buffer(&dec->cs, y->buffer.buf, RADEON_USAGE_READWRITE | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_VRAM); + } + + dec->decode_buffer->valid_buf_flag |= RDECODE_CMDBUF_FLAGS_REF_BUFFER; +} + /** * send cmd for vcn dec */ @@ -2523,7 +2601,7 @@ bool send_cmd_dec(struct radeon_decoder *dec, struct pipe_video_buffer *target, rvcn_dec_message_feedback(dec); send_msg_buf(dec); - if (dec->dpb_type != DPB_DYNAMIC_TIER_2) + if (dec->dpb_type < DPB_DYNAMIC_TIER_2) send_cmd(dec, RDECODE_CMD_DPB_BUFFER, dec->dpb.res->buf, 0, RADEON_USAGE_READWRITE, RADEON_DOMAIN_VRAM); if (dec->ctx.res) @@ -2541,6 +2619,9 @@ bool send_cmd_dec(struct radeon_decoder *dec, struct pipe_video_buffer *target, send_cmd(dec, RDECODE_CMD_PROB_TBL_BUFFER, msg_fb_it_probs_buf->res->buf, FB_BUFFER_OFFSET + FB_BUFFER_SIZE, RADEON_USAGE_READ, RADEON_DOMAIN_GTT); + if (dec->dpb_type == DPB_DYNAMIC_TIER_3) + send_ref_buffers(dec); + if (dec->vcn_dec_sw_ring == false) set_reg(dec, dec->reg.cntl, 1); @@ -2850,7 +2931,9 @@ struct pipe_video_codec *radeon_create_decoder(struct pipe_context *context, } } - if ((sctx->vcn_ip_ver >= VCN_3_0_0) && + if (sctx->vcn_ip_ver >= VCN_5_0_0) + dec->dpb_type = DPB_DYNAMIC_TIER_3; + else if ((sctx->vcn_ip_ver >= VCN_3_0_0) && (stream_type == RDECODE_CODEC_VP9 || stream_type == RDECODE_CODEC_AV1 || ((stream_type == RDECODE_CODEC_H265) && templ->expect_chunked_decode) || @@ -2874,7 +2957,7 @@ struct pipe_video_codec *radeon_create_decoder(struct pipe_context *context, dec->db_alignment = 64; } - if (dec->dpb_type != DPB_DYNAMIC_TIER_2) + if (dec->dpb_type < DPB_DYNAMIC_TIER_2) dec->dpb_size = calc_dpb_size(dec); if (!si_vid_create_buffer(dec->screen, &dec->sessionctx, RDECODE_SESSION_CONTEXT_SIZE, @@ -3009,11 +3092,8 @@ struct pipe_video_codec *radeon_create_decoder(struct pipe_context *context, else dec->send_cmd = send_cmd_dec; - - if (dec->dpb_type == DPB_DYNAMIC_TIER_2) { - list_inithead(&dec->dpb_ref_list); - list_inithead(&dec->dpb_unref_list); - } + list_inithead(&dec->dpb_ref_list); + list_inithead(&dec->dpb_unref_list); dec->tmz_ctx = sctx->vcn_ip_ver < VCN_2_2_0 && sctx->vcn_ip_ver != VCN_UNKNOWN; @@ -3040,7 +3120,7 @@ error: FREE(dec->bs_buffers); } - if (dec->dpb_type != DPB_DYNAMIC_TIER_2) + if (dec->dpb_type < DPB_DYNAMIC_TIER_2) si_vid_destroy_buffer(&dec->dpb); si_vid_destroy_buffer(&dec->ctx); si_vid_destroy_buffer(&dec->sessionctx); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h index 8b064252557..118063d571c 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h @@ -117,7 +117,8 @@ struct radeon_decoder { enum { DPB_MAX_RES = 0, DPB_DYNAMIC_TIER_1, - DPB_DYNAMIC_TIER_2 + DPB_DYNAMIC_TIER_2, + DPB_DYNAMIC_TIER_3, } dpb_type; struct { @@ -130,6 +131,10 @@ struct radeon_decoder { unsigned ref_size; unsigned num_refs; uint8_t ref_list[16]; + struct { + uint8_t index; + struct pipe_video_buffer *buf; + } bufs[16]; } ref_codec; struct list_head dpb_ref_list;