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 <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29055>
(cherry picked from commit 47b6ca47d0)
This commit is contained in:
David Rosca 2024-05-04 14:28:51 +02:00 committed by Eric Engestrom
parent 36b162f629
commit 7adccd14fa
3 changed files with 45 additions and 14 deletions

View file

@ -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

View file

@ -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);

View file

@ -121,6 +121,7 @@ struct radeon_decoder {
} bts;
uint8_t index;
unsigned ref_size;
unsigned num_refs;
uint8_t ref_list[16];
} ref_codec;