anv: Add support for using layered surfaces in AV1 video decoding

Reviewed-by: Hyunjun Ko <zzoon@igalia.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35651>
This commit is contained in:
Calder Young
2025-06-19 23:19:31 -07:00
committed by Marge Bot
parent 30b763f6e2
commit d0bf3a96f6
2 changed files with 47 additions and 34 deletions
+2 -1
View File
@@ -6695,7 +6695,8 @@ enum anv_vid_mem_av1_types {
};
struct anv_av1_video_refs_info {
const struct anv_image *img;
const struct anv_image_view *iv;
uint32_t array_layer;
uint8_t default_cdf_index;
};
+45 -33
View File
@@ -1335,7 +1335,8 @@ get_relative_dist(const VkVideoDecodeAV1PictureInfoKHR *av1_pic_info,
}
struct av1_refs_info {
const struct anv_image *img;
const struct anv_image_view *iv;
uint32_t array_layer;
uint8_t order_hint;
uint8_t ref_order_hints[STD_VIDEO_AV1_NUM_REF_FRAMES];
uint8_t disable_frame_end_update_cdf;
@@ -1349,20 +1350,23 @@ struct av1_refs_info {
static int
find_cdf_index(const struct anv_video_session *vid,
const struct av1_refs_info *refs_info,
const struct anv_image *img)
const struct anv_image_view *iv,
uint32_t array_layer)
{
for (uint32_t i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; i++) {
if (vid) {
if (!vid->prev_refs[i].img)
if (!vid->prev_refs[i].iv)
continue;
if (vid->prev_refs[i].img == img)
if (vid->prev_refs[i].iv == iv &&
vid->prev_refs[i].array_layer == array_layer)
return vid->prev_refs[i].default_cdf_index;
} else {
if (!refs_info[i].img)
if (!refs_info[i].iv)
continue;
if (refs_info[i].img == img)
if (refs_info[i].iv == iv &&
refs_info[i].array_layer == array_layer)
return refs_info[i].default_cdf_index;
}
}
@@ -1431,6 +1435,9 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
const struct anv_image_view *dpb_iv = frame_info->pSetupReferenceSlot ?
anv_image_view_from_handle(frame_info->pSetupReferenceSlot->pPictureResource->imageViewBinding) :
dst_iv;
const uint32_t dpb_array_layer = frame_info->pSetupReferenceSlot ?
frame_info->pSetupReferenceSlot->pPictureResource->baseArrayLayer :
frame_info->dstPictureResource.baseArrayLayer;
const struct anv_image *dpb_img = dpb_iv->image;
const bool is_10bit = seq_hdr->pColorConfig->BitDepth == 10;
@@ -1438,7 +1445,8 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
int denom = std_pic_info->coded_denom + 9;
unsigned downscaled_width = (frameExtent.width * 8 + denom / 2) / denom;
ref_info[AV1_INTRA_FRAME].img = dpb_img;
ref_info[AV1_INTRA_FRAME].iv = dpb_iv;
ref_info[AV1_INTRA_FRAME].array_layer = dpb_array_layer;
ref_info[AV1_INTRA_FRAME].frame_width = frameExtent.width;
ref_info[AV1_INTRA_FRAME].frame_height = frameExtent.height;
@@ -1457,7 +1465,7 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
if (ref_idx == idx) {
const struct anv_image_view *ref_iv =
anv_image_view_from_handle(frame_info->pReferenceSlots[j].pPictureResource->imageViewBinding);
const struct anv_image *ref_img = ref_iv->image;
const uint32_t ref_array_layer = frame_info->pReferenceSlots[j].pPictureResource->baseArrayLayer;
const struct VkVideoDecodeAV1DpbSlotInfoKHR *dpb_slot =
vk_find_struct_const(frame_info->pReferenceSlots[j].pNext, VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR);
const struct StdVideoDecodeAV1ReferenceInfo *std_ref_info = dpb_slot->pStdReferenceInfo;
@@ -1466,11 +1474,12 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
ref_info[i + 1].frame_type = std_ref_info->frame_type;
ref_info[i + 1].frame_width = frameExtent.width;
ref_info[i + 1].frame_height = frameExtent.height;
ref_info[i + 1].img = ref_img;
ref_info[i + 1].iv = ref_iv;
ref_info[i + 1].array_layer = ref_array_layer;
ref_info[i + 1].order_hint = std_ref_info->OrderHint;
memcpy(ref_info[i + 1].ref_order_hints, std_ref_info->SavedOrderHints, STD_VIDEO_AV1_NUM_REF_FRAMES);
ref_info[i + 1].disable_frame_end_update_cdf = std_ref_info->flags.disable_frame_end_update_cdf;
ref_info[i + 1].default_cdf_index = find_cdf_index(vid, NULL, ref_img);
ref_info[i + 1].default_cdf_index = find_cdf_index(vid, NULL, ref_iv, ref_array_layer);
}
}
}
@@ -1484,13 +1493,13 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
if (!frame_is_key_or_intra(std_pic_info->frame_type)) {
for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) {
if (ref_info[r].img && frame_info->referenceSlotCount) {
if (ref_info[r].iv && frame_info->referenceSlotCount) {
anv_batch_emit(&cmd_buffer->batch, GENX(AVP_SURFACE_STATE), ss) {
ss.SurfaceID = 0x6 + r;
ss.SurfaceFormat = is_10bit ? AVP_P010 : AVP_PLANAR_420_8;
ss.SurfacePitchMinus1 = ref_info[r].img->planes[0].primary_surface.isl.row_pitch_B - 1;
ss.YOffsetforUCb = ref_info[r].img->planes[1].primary_surface.memory_range.offset /
ref_info[r].img->planes[0].primary_surface.isl.row_pitch_B;
ss.SurfacePitchMinus1 = ref_info[r].iv->image->planes[0].primary_surface.isl.row_pitch_B - 1;
ss.YOffsetforUCb = ref_info[r].iv->image->planes[1].primary_surface.memory_range.offset /
ref_info[r].iv->image->planes[0].primary_surface.isl.row_pitch_B;
}
}
}
@@ -1512,23 +1521,23 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
assert(dst_img->planes[0].primary_surface.isl.tiling == ISL_TILING_4);
#endif
anv_batch_emit(&cmd_buffer->batch, GENX(AVP_PIPE_BUF_ADDR_STATE), buf) {
buf.DecodedOutputFrameBufferAddress = anv_image_address(dst_img,
&dst_img->planes[0].primary_surface.memory_range);
buf.DecodedOutputFrameBufferAddress =
anv_image_dpb_address(dst_iv, frame_info->dstPictureResource.baseArrayLayer);
buf.DecodedOutputFrameBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) {
.MOCS = anv_mocs(cmd_buffer->device, buf.DecodedOutputFrameBufferAddress.bo, 0),
#if GFX_VERx10 >= 125
.TiledResourceMode = TRMODE_TILEF,
#endif
};
buf.CurrentFrameMVWriteBufferAddress = anv_image_address(dpb_img,
&dpb_img->vid_dmv_top_surface);
buf.CurrentFrameMVWriteBufferAddress =
anv_image_dmv_top_address(dpb_iv, dpb_array_layer);
buf.CurrentFrameMVWriteBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) {
.MOCS = anv_mocs(cmd_buffer->device, buf.CurrentFrameMVWriteBufferAddress.bo, 0),
};
if (std_pic_info->flags.allow_intrabc) {
buf.IntraBCDecodedOutputFrameBufferAddress =
anv_image_address(dst_img, &dst_img->planes[0].primary_surface.memory_range);
anv_image_dpb_address(dst_iv, frame_info->dstPictureResource.baseArrayLayer);
}
buf.IntraBCDecodedOutputFrameBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) {
@@ -1880,13 +1889,14 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
if (std_pic_info->frame_type != STD_VIDEO_AV1_FRAME_TYPE_KEY) {
for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) {
const struct anv_image *ref_img = ref_info[r].img;
if (ref_img) {
const struct anv_image_view *ref_iv = ref_info[r].iv;
const struct anv_image *ref_img = ref_iv->image;
if (ref_iv) {
buf.ReferencePictureAddress[r] =
anv_image_address(ref_img, &ref_img->planes[0].primary_surface.memory_range);
anv_image_dpb_address(ref_iv, ref_info[r].array_layer);
buf.CollocatedMVTemporalBufferAddress[r] =
anv_image_address(ref_img, &ref_img->vid_dmv_top_surface);
anv_image_dmv_top_address(ref_iv, ref_info[r].array_layer);
if (!ref_bo)
ref_bo = ref_img->bindings[0].address.bo;
@@ -1915,8 +1925,9 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
if (ref_info[std_pic_info->primary_ref_frame + 1].disable_frame_end_update_cdf) {
use_default_cdf = true;
const struct anv_image *ref_img = ref_info[std_pic_info->primary_ref_frame + 1].img;
cdf_index = find_cdf_index(vid, NULL, ref_img);
const struct anv_image_view *ref_iv = ref_info[std_pic_info->primary_ref_frame + 1].iv;
const uint32_t ref_layer = ref_info[std_pic_info->primary_ref_frame + 1].array_layer;
cdf_index = find_cdf_index(vid, NULL, ref_iv, ref_layer);
}
}
@@ -1927,18 +1938,17 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
ref_info[0].default_cdf_index = cdf_index;
} else {
const struct anv_image *ref_img = ref_info[std_pic_info->primary_ref_frame + 1].img;
buf.CDFTablesInitializationBufferAddress = anv_image_address(ref_img,
&ref_img->av1_cdf_table);
const struct anv_image_view *ref_iv = ref_info[std_pic_info->primary_ref_frame + 1].iv;
const uint32_t ref_layer = ref_info[std_pic_info->primary_ref_frame + 1].array_layer;
buf.CDFTablesInitializationBufferAddress = anv_image_av1_table_address(ref_iv, ref_layer);
}
buf.CDFTablesInitializationBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) {
.MOCS = anv_mocs(cmd_buffer->device, buf.CDFTablesInitializationBufferAddress.bo, 0),
};
if (!std_pic_info->flags.disable_frame_end_update_cdf) {
const struct anv_image *ref_img = ref_info[0].img;
buf.CDFTablesBackwardAdaptationBufferAddress = anv_image_address(ref_img,
&ref_img->av1_cdf_table);
buf.CDFTablesBackwardAdaptationBufferAddress =
anv_image_av1_table_address(ref_info[0].iv, ref_info[0].array_layer);
}
buf.CDFTablesBackwardAdaptationBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) {
@@ -2508,10 +2518,12 @@ anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer,
/* Set necessary info from current refs to the prev_refs */
for (int i = 0; i < STD_VIDEO_AV1_NUM_REF_FRAMES; ++i) {
vid->prev_refs[i].img = ref_info[i].img;
vid->prev_refs[i].iv = ref_info[i].iv;
vid->prev_refs[i].array_layer = ref_info[i].array_layer;
vid->prev_refs[i].default_cdf_index =
i == 0 ? ref_info[i].default_cdf_index :
find_cdf_index(NULL, ref_info, ref_info[i].img);
find_cdf_index(NULL, ref_info, ref_info[i].iv,
ref_info[i].array_layer);
}
}