From 30a89323ad660d6a30dcf1a7a037893358f3060c Mon Sep 17 00:00:00 2001 From: SureshGuttula Date: Mon, 27 Feb 2023 14:53:17 +0530 Subject: [PATCH] radeonsi: Add support for DPB resize This patch will add support for dpb resize when low to high resolution change/ svc use-cases. With DPB tier1 type,vp9 svc decoder use cases are failed. This Change will fix this[VCN1/VCN2]. Signed-off-by: SureshGuttula Reviewed-by: Leo Liu Reviewed-by: Boyuan Zhang Part-of: --- src/amd/common/ac_vcn_dec.h | 5 ++++ src/gallium/drivers/radeonsi/radeon_uvd.c | 2 +- src/gallium/drivers/radeonsi/radeon_vcn_dec.c | 40 +++++++++++++++++++++------ src/gallium/drivers/radeonsi/radeon_vcn_dec.h | 2 ++ src/gallium/drivers/radeonsi/radeon_video.c | 20 ++++++++++---- src/gallium/drivers/radeonsi/radeon_video.h | 10 ++++++- 6 files changed, 64 insertions(+), 15 deletions(-) diff --git a/src/amd/common/ac_vcn_dec.h b/src/amd/common/ac_vcn_dec.h index 0cc2775..a58e0ff 100644 --- a/src/amd/common/ac_vcn_dec.h +++ b/src/amd/common/ac_vcn_dec.h @@ -160,6 +160,11 @@ #define RDECODE_VP9_PROBS_DATA_SIZE 2304 +/* *** decode flags *** */ +#define RDECODE_FLAGS_USE_DYNAMIC_DPB_MASK 0x00000001 +#define RDECODE_FLAGS_USE_PAL_MASK 0x00000008 +#define RDECODE_FLAGS_DPB_RESIZE_MASK 0x00000100 + #define mmUVD_JPEG_CNTL 0x0200 #define mmUVD_JPEG_CNTL_BASE_IDX 1 #define mmUVD_JPEG_RB_BASE 0x0201 diff --git a/src/gallium/drivers/radeonsi/radeon_uvd.c b/src/gallium/drivers/radeonsi/radeon_uvd.c index f9dc4dc..4d41b2c 100644 --- a/src/gallium/drivers/radeonsi/radeon_uvd.c +++ b/src/gallium/drivers/radeonsi/radeon_uvd.c @@ -1059,7 +1059,7 @@ static void ruvd_decode_bitstream(struct pipe_video_codec *decoder, if (new_size > buf->res->buf->size) { dec->ws->buffer_unmap(dec->ws, buf->res->buf); - if (!si_vid_resize_buffer(dec->screen, &dec->cs, buf, new_size)) { + if (!si_vid_resize_buffer(dec->screen, &dec->cs, buf, new_size, NULL)) { RVID_ERR("Can't resize bitstream buffer!"); return; } diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c index c6b69db..be4b040 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c @@ -1958,7 +1958,7 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, rvcn_dec_message_drm_t *drm = NULL; rvcn_dec_message_dynamic_dpb_t *dynamic_dpb = NULL; rvcn_dec_message_dynamic_dpb_t2_t *dynamic_dpb_t2 = NULL; - + bool dpb_resize = false; header = dec->msg; sizes += sizeof(rvcn_dec_message_header_t); @@ -2044,9 +2044,9 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, decode->bsd_size = align(dec->bs_size, 128); - if (!dec->dpb.res && dec->dpb_type != DPB_DYNAMIC_TIER_2) { + if (dec->dpb_type != DPB_DYNAMIC_TIER_2) { bool r; - if (dec->dpb_size) { + if (!dec->dpb.res && dec->dpb_size) { if (encrypted) { r = si_vid_create_tmz_buffer(dec->screen, &dec->dpb, dec->dpb_size, PIPE_USAGE_DEFAULT); } else { @@ -2058,6 +2058,25 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, return NULL; } si_vid_clear_buffer(dec->base.context, &dec->dpb); + } else if (dec->dpb_type == DPB_DYNAMIC_TIER_1 && dec->dpb.res && + (dec->max_width < dec->base.width || dec->max_height < dec->base.height)) { + struct rvid_buf_offset_info buf_offset_info; + + buf_offset_info.num_units = (NUM_VP9_REFS + 1); + buf_offset_info.old_offset = (align(dec->max_width, dec->db_alignment) * + align(dec->max_height, dec->db_alignment) * 3 / 2); + buf_offset_info.new_offset = (align(dec->base.width, dec->db_alignment) * + align(dec->base.height, dec->db_alignment) * 3 / 2); + + dec->dpb_size = calc_dpb_size(dec); + r = si_vid_resize_buffer(dec->screen, &dec->cs, &dec->dpb, dec->dpb_size, &buf_offset_info); + if (!r) { + RVID_ERR("Can't resize dpb.\n"); + return NULL; + } + dec->max_width = dec->base.width; + dec->max_height = dec->base.height; + dpb_resize = true; } } @@ -2202,10 +2221,14 @@ static struct pb_buffer *rvcn_dec_message_decode(struct radeon_decoder *dec, } if (dec->dpb_type == DPB_DYNAMIC_TIER_1) { - decode->decode_flags = 1; + decode->decode_flags |= (RDECODE_FLAGS_USE_DYNAMIC_DPB_MASK | RDECODE_FLAGS_USE_PAL_MASK); + // Add decode flag for RESIZE_DPB ,when we do resize + if (dpb_resize == true) + decode->decode_flags |= RDECODE_FLAGS_DPB_RESIZE_MASK; + dynamic_dpb->dpbArraySize = NUM_VP9_REFS + 1; - dynamic_dpb->dpbLumaPitch = align(decode->width_in_samples, dec->db_alignment); - dynamic_dpb->dpbLumaAlignedHeight = align(decode->height_in_samples, dec->db_alignment); + dynamic_dpb->dpbLumaPitch = align(dec->max_width, dec->db_alignment); + dynamic_dpb->dpbLumaAlignedHeight = align(dec->max_height, dec->db_alignment); dynamic_dpb->dpbLumaAlignedSize = dynamic_dpb->dpbLumaPitch * dynamic_dpb->dpbLumaAlignedHeight; dynamic_dpb->dpbChromaPitch = dynamic_dpb->dpbLumaPitch >> 1; @@ -2846,7 +2869,7 @@ static void radeon_dec_decode_bitstream(struct pipe_video_codec *decoder, if (new_size > buf->res->buf->size) { dec->ws->buffer_unmap(dec->ws, buf->res->buf); dec->bs_ptr = NULL; - if (!si_vid_resize_buffer(dec->screen, &dec->cs, buf, new_size)) { + if (!si_vid_resize_buffer(dec->screen, &dec->cs, buf, new_size, NULL)) { RVID_ERR("Can't resize bitstream buffer!"); return; } @@ -3021,7 +3044,8 @@ struct pipe_video_codec *radeon_create_decoder(struct pipe_context *context, dec->base.context = context; dec->base.width = width; dec->base.height = height; - + dec->max_width = width; + dec->max_height = height; dec->base.destroy = radeon_dec_destroy; dec->base.begin_frame = radeon_dec_begin_frame; dec->base.decode_macroblock = radeon_dec_decode_macroblock; diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h index 3a586a2..7abcf17 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h @@ -51,6 +51,8 @@ struct radeon_decoder { unsigned dpb_size; unsigned last_width; unsigned last_height; + unsigned max_width; + unsigned max_height; unsigned addr_gfx_mode; struct pipe_screen *screen; diff --git a/src/gallium/drivers/radeonsi/radeon_video.c b/src/gallium/drivers/radeonsi/radeon_video.c index 378e279..cfc6d56 100644 --- a/src/gallium/drivers/radeonsi/radeon_video.c +++ b/src/gallium/drivers/radeonsi/radeon_video.c @@ -87,7 +87,8 @@ void si_vid_destroy_buffer(struct rvid_buffer *buffer) /* reallocate a buffer, preserving its content */ bool si_vid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs, - struct rvid_buffer *new_buf, unsigned new_size) + struct rvid_buffer *new_buf, unsigned new_size, + struct rvid_buf_offset_info *buf_ofst_info) { struct si_screen *sscreen = (struct si_screen *)screen; struct radeon_winsys *ws = sscreen->ws; @@ -106,11 +107,20 @@ bool si_vid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs, if (!dst) goto error; - memcpy(dst, src, bytes); - if (new_size > bytes) { - new_size -= bytes; - dst += bytes; + if (buf_ofst_info) { memset(dst, 0, new_size); + for(int i =0; i < buf_ofst_info->num_units; i++) { + memcpy(dst, src, buf_ofst_info->old_offset); + dst += buf_ofst_info->new_offset; + src += buf_ofst_info->old_offset; + } + } else { + memcpy(dst, src, bytes); + if (new_size > bytes) { + new_size -= bytes; + dst += bytes; + memset(dst, 0, new_size); + } } ws->buffer_unmap(ws, new_buf->res->buf); ws->buffer_unmap(ws, old_buf.res->buf); diff --git a/src/gallium/drivers/radeonsi/radeon_video.h b/src/gallium/drivers/radeonsi/radeon_video.h index 3f39f1e..0905a4a 100644 --- a/src/gallium/drivers/radeonsi/radeon_video.h +++ b/src/gallium/drivers/radeonsi/radeon_video.h @@ -42,6 +42,13 @@ struct rvid_buffer { struct si_resource *res; }; +/* video buffer offset info representation */ +struct rvid_buf_offset_info { + unsigned num_units; + unsigned old_offset; + unsigned new_offset; +}; + /* generate an stream handle */ unsigned si_vid_alloc_stream_handle(void); @@ -58,7 +65,8 @@ void si_vid_destroy_buffer(struct rvid_buffer *buffer); /* reallocate a buffer, preserving its content */ bool si_vid_resize_buffer(struct pipe_screen *screen, struct radeon_cmdbuf *cs, - struct rvid_buffer *new_buf, unsigned new_size); + struct rvid_buffer *new_buf, unsigned new_size, + struct rvid_buf_offset_info *buf_ofst_info); /* clear the buffer with zeros */ void si_vid_clear_buffer(struct pipe_context *context, struct rvid_buffer *buffer); -- 2.7.4