radeonsi/vcn: Add UDT support for VCN5

UDT uses decode target buffers directly as references.

Reviewed-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33641>
This commit is contained in:
David Rosca
2025-02-07 12:54:32 +01:00
committed by Marge Bot
parent 826acf5dce
commit fd3f297eb5
3 changed files with 147 additions and 32 deletions
+30
View File
@@ -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];
+111 -31
View File
@@ -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);
@@ -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;