From 7adccd14fa6d086ded549204c15dcc2463faee29 Mon Sep 17 00:00:00 2001 From: David Rosca Date: Sat, 4 May 2024 14:28:51 +0200 Subject: [PATCH] radeonsi/vcn: Ensure DPB has as many buffers as references In case of corrupted streams (or application bugs) the number of references may not be equal to DPB size. This needs to be fixed by filling the missing slots with dummy buffers. Cc: mesa-stable Reviewed-by: Leo Liu Part-of: (cherry picked from commit 47b6ca47d0be9e218a7ca3f47f90de2ed6c174f7) --- .pick_status.json | 2 +- src/gallium/drivers/radeonsi/radeon_vcn_dec.c | 56 ++++++++++++++----- src/gallium/drivers/radeonsi/radeon_vcn_dec.h | 1 + 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index d172db1c845..44666196678 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -564,7 +564,7 @@ "description": "radeonsi/vcn: Ensure DPB has as many buffers as references", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c index 55c907d68c6..9c308c3da98 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.c +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.c @@ -279,7 +279,8 @@ static rvcn_dec_message_avc_t get_h264_msg(struct radeon_decoder *dec, dec->ref_codec.bts = CODEC_8_BITS; dec->ref_codec.index = result.decoded_pic_idx; dec->ref_codec.ref_size = 16; - memset(dec->ref_codec.ref_list, 0xff, sizeof(dec->ref_codec.ref_list)); + dec->ref_codec.num_refs = result.curr_pic_ref_frame_num; + 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)); } @@ -292,7 +293,7 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, struct pipe_h265_picture_desc *pic) { rvcn_dec_message_hevc_t result; - unsigned i, j; + unsigned i, j, num_refs = 0; memset(&result, 0, sizeof(result)); result.sps_info_flags = 0; @@ -413,9 +414,10 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, result.poc_list[i] = pic->PicOrderCntVal[i]; - if (ref) + if (ref) { ref_pic = (uintptr_t)vl_video_buffer_get_associated_data(ref, &dec->base); - else + num_refs++; + } else ref_pic = 0x7F; result.ref_pic_list[i] = ref_pic; } @@ -469,7 +471,8 @@ static rvcn_dec_message_hevc_t get_h265_msg(struct radeon_decoder *dec, CODEC_10_BITS : CODEC_8_BITS; dec->ref_codec.index = result.curr_idx; dec->ref_codec.ref_size = 15; - memset(dec->ref_codec.ref_list, 0x7f, sizeof(dec->ref_codec.ref_list)); + dec->ref_codec.num_refs = num_refs; + STATIC_ASSERT(sizeof(dec->ref_codec.ref_list) == sizeof(result.ref_pic_list)); memcpy(dec->ref_codec.ref_list, result.ref_pic_list, sizeof(result.ref_pic_list)); } return result; @@ -507,7 +510,7 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, struct pipe_vp9_picture_desc *pic) { rvcn_dec_message_vp9_t result; - unsigned i ,j; + unsigned i, j, num_refs = 0; memset(&result, 0, sizeof(result)); @@ -641,9 +644,13 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, get_current_pic_index(dec, target, &result.curr_pic_idx); for (i = 0; i < 8; i++) { - result.ref_frame_map[i] = - (pic->ref[i]) ? (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base) - : 0x7f; + 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++; + } else + ref_frame = 0x7f; + result.ref_frame_map[i] = ref_frame; } result.frame_refs[0] = result.ref_frame_map[pic->picture_parameter.pic_fields.last_ref_frame]; @@ -669,6 +676,7 @@ static rvcn_dec_message_vp9_t get_vp9_msg(struct radeon_decoder *dec, CODEC_10_BITS : CODEC_8_BITS; 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)); } @@ -959,7 +967,7 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, struct pipe_av1_picture_desc *pic) { rvcn_dec_message_av1_t result; - unsigned i, j; + unsigned i, j, num_refs = 0; uint16_t tile_count = pic->picture_parameter.tile_cols * pic->picture_parameter.tile_rows; memset(&result, 0, sizeof(result)); @@ -1151,9 +1159,13 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, result.order_hint_bits = pic->picture_parameter.order_hint_bits_minus_1 + 1; for (i = 0; i < NUM_AV1_REFS; ++i) { - result.ref_frame_map[i] = - (pic->ref[i]) ? (uintptr_t)vl_video_buffer_get_associated_data(pic->ref[i], &dec->base) - : 0x7f; + 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++; + } else + ref_frame = 0x7f; + result.ref_frame_map[i] = ref_frame; } for (i = 0; i < NUM_AV1_REFS_PER_FRAME; ++i) result.frame_refs[i] = result.ref_frame_map[pic->picture_parameter.ref_frame_idx[i]]; @@ -1300,6 +1312,7 @@ static rvcn_dec_message_av1_t get_av1_msg(struct radeon_decoder *dec, dec->ref_codec.bts = pic->picture_parameter.bit_depth_idx ? CODEC_10_BITS : CODEC_8_BITS; 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)); } @@ -1887,6 +1900,23 @@ static unsigned rvcn_dec_dynamic_dpb_t2_message(struct radeon_decoder *dec, rvcn list_addtail(&dpb->list, &dec->dpb_ref_list); } + if (dynamic_dpb_t2->dpbArraySize < dec->ref_codec.num_refs) { + struct rvcn_dec_dynamic_dpb_t2 *d = + list_first_entry(&dec->dpb_ref_list, struct rvcn_dec_dynamic_dpb_t2, list); + addr = dec->ws->buffer_get_virtual_address(d->dpb.res->buf); + if (!addr && dummy) + addr = dec->ws->buffer_get_virtual_address(dummy->dpb.res->buf); + assert(addr); + for (i = 0; i < dec->ref_codec.num_refs; ++i) { + if (dynamic_dpb_t2->dpbAddrLo[i] || dynamic_dpb_t2->dpbAddrHi[i]) + continue; + dynamic_dpb_t2->dpbAddrLo[i] = addr; + dynamic_dpb_t2->dpbAddrHi[i] = addr >> 32; + ++dynamic_dpb_t2->dpbArraySize; + } + assert(dynamic_dpb_t2->dpbArraySize == dec->ref_codec.num_refs); + } + dec->ws->cs_add_buffer(&dec->cs, dpb->dpb.res->buf, RADEON_USAGE_READWRITE | RADEON_USAGE_SYNCHRONIZED, RADEON_DOMAIN_VRAM); addr = dec->ws->buffer_get_virtual_address(dpb->dpb.res->buf); diff --git a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h index a8d099d28ad..3a3d4e36144 100644 --- a/src/gallium/drivers/radeonsi/radeon_vcn_dec.h +++ b/src/gallium/drivers/radeonsi/radeon_vcn_dec.h @@ -121,6 +121,7 @@ struct radeon_decoder { } bts; uint8_t index; unsigned ref_size; + unsigned num_refs; uint8_t ref_list[16]; } ref_codec;