hasvk: Initial layered DPB support and plenty of debug output.

Assisted-by: Claude
This commit is contained in:
dancingmirrors authored and elwrcl committed 2026-07-21 22:25:27 +03:00
1 parent 72177c94e1
commit 4204b5ff5b
3 files changed
+327 -44

No files matched your search

+122 -3
View File
@@ -711,8 +711,10 @@ add_video_buffers(struct anv_device *device,
if (device->info->ver == 7) { if (device->info->ver == 7) {
/* However for frames wider than 128 MBs we need to make sure we /* However for frames wider than 128 MBs we need to make sure we
* don't overrun and silently corrupt the buffer. * don't overrun and silently corrupt the buffer.
*
* Also a guard row that mirrors the VA-API driver.
*/ */
size = h_mb * MAX2(w_mb, 128u) * 64; size = (h_mb + 1) * MAX2(w_mb, 128u) * 64;
} else { } else {
/* XXX: Is this correct for Broadwell? */ /* XXX: Is this correct for Broadwell? */
size = w_mb * h_mb * 128; size = w_mb * h_mb * 128;
@@ -723,16 +725,34 @@ add_video_buffers(struct anv_device *device,
if (size == 0) if (size == 0)
return VK_SUCCESS; return VK_SUCCESS;
unsigned top_size = size;
if (image->vk.array_layers > 1) {
image->vid_dmv_top_surface_pitch_B = align(size, 64);
top_size = image->vid_dmv_top_surface_pitch_B *
(image->vk.array_layers - 1) + size;
} else {
image->vid_dmv_top_surface_pitch_B = size;
}
result = result =
image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE, image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE,
ANV_OFFSET_IMPLICIT, size, 65536, ANV_OFFSET_IMPLICIT, top_size, 65536,
&image->vid_dmv_top_surface); &image->vid_dmv_top_surface);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
return result; return result;
unsigned bottom_size = size;
if (image->vk.array_layers > 1) {
image->vid_dmv_bottom_surface_pitch_B = align(size, 64);
bottom_size = image->vid_dmv_bottom_surface_pitch_B *
(image->vk.array_layers - 1) + size;
} else {
image->vid_dmv_bottom_surface_pitch_B = size;
}
result = result =
image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE, image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE,
ANV_OFFSET_IMPLICIT, size, 65536, ANV_OFFSET_IMPLICIT, bottom_size, 65536,
&image->vid_dmv_bottom_surface); &image->vid_dmv_bottom_surface);
return result; return result;
} }
@@ -997,6 +1017,94 @@ check_drm_format_mod(const struct anv_device *device,
return VK_SUCCESS; return VK_SUCCESS;
} }
/* Layered DPB needs every array slice to be a self-contained frame addressable
* with a single chroma offset. The default layout puts all luma slices first
* and all chroma slices after, so we can't use a fixed YOffsetforUCb.
* Like ANV, we ask ISL to interleave the plane slices instead.
*/
static VkResult
add_all_surfaces_implicit_interleaved_arrays_layout(
struct anv_device *device,
struct anv_image *image,
const VkImageFormatListCreateInfo *format_list_info,
isl_tiling_flags_t isl_tiling_flags,
isl_surf_usage_flags_t isl_extra_usage_flags)
{
const struct intel_device_info *devinfo = device->info;
const struct vk_format_ycbcr_info *ycbcr_info =
vk_format_get_ycbcr_info(image->vk.format);
VkResult result;
VkImageAspectFlagBits aspects[3];
unsigned num_aspects = 0;
u_foreach_bit(b, image->vk.aspects) {
assert(num_aspects < 3);
aspects[num_aspects++] = 1 << b;
}
uint32_t surfs_offsets[3];
struct isl_surf *surfs[3];
struct isl_surf_init_info infos[3];
struct anv_format_plane plane_format[3];
for (unsigned i = 0; i < num_aspects; i++) {
VkImageAspectFlagBits aspect = aspects[i];
const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
plane_format[i] =
anv_get_format_plane(devinfo, image->vk.format, plane,
image->vk.tiling);
assert(plane_format[i].isl_format != ISL_FORMAT_UNSUPPORTED);
VkImageUsageFlags vk_usage = vk_image_usage(&image->vk, aspect);
isl_surf_usage_flags_t isl_usage =
choose_isl_surf_usage(image->vk.create_flags, vk_usage,
isl_extra_usage_flags, aspect);
uint32_t width = image->vk.extent.width;
uint32_t height = image->vk.extent.height;
if (ycbcr_info) {
assert(plane < ycbcr_info->n_planes);
width /= ycbcr_info->planes[plane].denominator_scales[0];
height /= ycbcr_info->planes[plane].denominator_scales[1];
}
surfs[i] = &image->planes[plane].primary_surface.isl;
infos[i] = (struct isl_surf_init_info) {
.dim = vk_to_isl_surf_dim[image->vk.image_type],
.format = plane_format[i].isl_format,
.width = width,
.height = height,
.depth = image->vk.extent.depth,
.levels = image->vk.mip_levels,
.array_len = image->vk.array_layers,
.samples = image->vk.samples,
.min_alignment_B = 0,
.row_pitch_B = 0,
.usage = isl_usage,
.tiling_flags = isl_tiling_flags,
};
}
if (!isl_surf_init_interleaved_arrays(&device->isl_dev, num_aspects, surfs,
surfs_offsets, infos))
return vk_errorf(device, VK_ERROR_UNKNOWN,
"Unable to create interleaved arrayed image");
for (unsigned i = 0; i < num_aspects; i++) {
const uint32_t plane = anv_image_aspect_to_plane(image, aspects[i]);
image->planes[plane].aux_usage = ISL_AUX_USAGE_NONE;
result = add_surface(device, image,
&image->planes[plane].primary_surface,
ANV_IMAGE_MEMORY_BINDING_PLANE_0 + plane,
surfs_offsets[i]);
if (result != VK_SUCCESS)
return result;
}
return VK_SUCCESS;
}
/** /**
* Use when the app does not provide * Use when the app does not provide
* VkImageDrmFormatModifierExplicitCreateInfoEXT. * VkImageDrmFormatModifierExplicitCreateInfoEXT.
@@ -1013,6 +1121,17 @@ add_all_surfaces_implicit_layout(
const struct intel_device_info *devinfo = device->info; const struct intel_device_info *devinfo = device->info;
VkResult result; VkResult result;
/* XXX: Based on what I could glean from !35651. */
if (devinfo->ver == 8 && image->n_planes > 1 && !image->disjoint &&
image->vk.array_layers > 1 &&
(image->vk.usage & (VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR |
VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR))) {
assert(stride == 0);
return add_all_surfaces_implicit_interleaved_arrays_layout(
device, image, format_list_info, isl_tiling_flags,
isl_extra_usage_flags);
}
u_foreach_bit(b, image->vk.aspects) { u_foreach_bit(b, image->vk.aspects) {
VkImageAspectFlagBits aspect = 1 << b; VkImageAspectFlagBits aspect = 1 << b;
const uint32_t plane = anv_image_aspect_to_plane(image, aspect); const uint32_t plane = anv_image_aspect_to_plane(image, aspect);
+63
View File
@@ -3299,6 +3299,10 @@ struct anv_image {
struct anv_image_memory_range vid_dmv_top_surface; struct anv_image_memory_range vid_dmv_top_surface;
struct anv_image_memory_range vid_dmv_bottom_surface; struct anv_image_memory_range vid_dmv_bottom_surface;
/* array_layers > 1 */
uint32_t vid_dmv_top_surface_pitch_B;
uint32_t vid_dmv_bottom_surface_pitch_B;
}; };
static inline bool static inline bool
@@ -3590,6 +3594,65 @@ enum anv_image_view_state_flags {
ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL = (1 << 1), ANV_IMAGE_VIEW_STATE_TEXTURE_OPTIMAL = (1 << 1),
}; };
/* Address of the luma plane for a given DPB array layer. */
static inline struct anv_address MUST_CHECK
anv_image_dpb_address(const struct anv_image_view *iv,
uint32_t arrayLayer)
{
assert(iv->vk.base_mip_level == 0);
assert(iv->vk.layer_count > arrayLayer);
struct anv_address addr =
anv_image_address(iv->image,
&iv->image->planes[0].primary_surface.memory_range);
if (anv_address_is_null(addr))
return addr;
uint64_t offset_B;
uint32_t x_offset_sa = 0, y_offset_sa = 0;
isl_surf_get_image_offset_B_tile_sa(&iv->image->planes[0].primary_surface.isl,
0,
iv->vk.base_array_layer + arrayLayer,
0,
&offset_B,
&x_offset_sa,
&y_offset_sa);
if (x_offset_sa || y_offset_sa)
mesa_logw_once("QPitch restrictions on gen7 can result in corruption.");
return anv_address_add(addr, offset_B);
}
static inline struct anv_address MUST_CHECK
anv_image_dmv_top_address(const struct anv_image_view *iv,
uint32_t arrayLayer)
{
struct anv_address addr =
anv_image_address(iv->image, &iv->image->vid_dmv_top_surface);
if (anv_address_is_null(addr))
return addr;
return anv_address_add(addr, iv->image->vid_dmv_top_surface_pitch_B *
((uint64_t)iv->vk.base_array_layer + arrayLayer));
}
static inline struct anv_address MUST_CHECK
anv_image_dmv_bottom_address(const struct anv_image_view *iv,
uint32_t arrayLayer)
{
struct anv_address addr =
anv_image_address(iv->image, &iv->image->vid_dmv_bottom_surface);
if (anv_address_is_null(addr))
return addr;
return anv_address_add(addr, iv->image->vid_dmv_bottom_surface_pitch_B *
((uint64_t)iv->vk.base_array_layer + arrayLayer));
}
void anv_image_fill_surface_state(struct anv_device *device, void anv_image_fill_surface_state(struct anv_device *device,
const struct anv_image *image, const struct anv_image *image,
VkImageAspectFlagBits aspect, VkImageAspectFlagBits aspect,
+142 -41
View File
@@ -154,6 +154,15 @@ void genX(CmdEndVideoCodingKHR) (VkCommandBuffer commandBuffer,
cmd_buffer->video.params = NULL; cmd_buffer->video.params = NULL;
} }
static inline void
anv_h264_sane_field_pocs(const int32_t poc[2], int32_t *top, int32_t *bottom)
{
int32_t t = poc[0], b = poc[1];
if (t == INT32_MAX) t = b;
if (b == INT32_MAX) b = t;
*top = t; *bottom = b;
}
static void static void
anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
const VkVideoDecodeInfoKHR *frame_info) const VkVideoDecodeInfoKHR *frame_info)
@@ -204,22 +213,45 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
flush.VideoPipelineCacheInvalidate = 1; flush.VideoPipelineCacheInvalidate = 1;
}; };
const bool is_reference = frame_info->pSetupReferenceSlot != NULL;
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_PIPE_MODE_SELECT), sel) { anv_batch_emit(&cmd_buffer->batch, GENX(MFX_PIPE_MODE_SELECT), sel) {
sel.StandardSelect = SS_AVC; sel.StandardSelect = SS_AVC;
sel.CodecSelect = Decode; sel.CodecSelect = Decode;
sel.DecoderShortFormatMode = LongFormatDriverInterface; sel.DecoderShortFormatMode = LongFormatDriverInterface;
sel.PreDeblockingOutputEnable = !is_reference; sel.PreDeblockingOutputEnable = false;
sel.PostDeblockingOutputEnable = is_reference; sel.PostDeblockingOutputEnable = true;
sel.DecoderModeSelect = VLDMode; sel.DecoderModeSelect = VLDMode;
} }
const struct anv_image_view *iv = anv_image_view_from_handle(frame_info->dstPictureResource.imageViewBinding); const struct anv_image_view *iv = anv_image_view_from_handle(frame_info->dstPictureResource.imageViewBinding);
const struct anv_image *img = iv->image; const struct anv_image *img = iv->image;
if (sps->chroma_format_idc == 0) if (INTEL_DEBUG(DEBUG_PERF)) {
const StdVideoDecodeH264PictureInfo *p = h264_pic_info->pStdPictureInfo;
mesa_logw("hasvk/video: VID f_num=%d poc=%d/%d field=%u bot=%u idr=%u ref=%u "
"slices=%u refs=%u dst_layer=%u img=%p layers=%u",
p->frame_num, p->PicOrderCnt[0], p->PicOrderCnt[1],
p->flags.field_pic_flag, p->flags.bottom_field_flag,
p->flags.IdrPicFlag, p->flags.is_reference,
h264_pic_info->sliceCount, frame_info->referenceSlotCount,
frame_info->dstPictureResource.baseArrayLayer,
(void *)img, img->vk.array_layers);
for (uint32_t i = 0; i < frame_info->referenceSlotCount; i++) {
const struct anv_image_view *r =
anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding);
mesa_logw("hasvk/video: ref[%u] slot=%d layer=%u img=%p same_as_dst=%d",
i, frame_info->pReferenceSlots[i].slotIndex,
frame_info->pReferenceSlots[i].pPictureResource->baseArrayLayer,
(void *)r->image, r->image == img);
}
}
/* Conceal as gray in the "non-existing" case. */
anv_video_init_neutral_chroma(cmd_buffer->device, img); anv_video_init_neutral_chroma(cmd_buffer->device, img);
for (uint32_t i = 0; i < frame_info->referenceSlotCount; i++) {
const struct anv_image_view *ref_iv =
anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding);
anv_video_init_neutral_chroma(cmd_buffer->device, ref_iv->image);
}
uint32_t frame_width_mbs = sps->pic_width_in_mbs_minus1 + 1; uint32_t frame_width_mbs = sps->pic_width_in_mbs_minus1 + 1;
uint32_t frame_height_mbs = sps->pic_height_in_map_units_minus1 + 1; uint32_t frame_height_mbs = sps->pic_height_in_map_units_minus1 + 1;
@@ -275,20 +307,13 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
buf.Pipeline = 2; buf.Pipeline = 2;
buf.CommandType = 3; buf.CommandType = 3;
struct anv_address dst_addr = anv_image_address(img, struct anv_address dst_addr =
&img->planes[0].primary_surface.memory_range); anv_image_dpb_address(iv, frame_info->dstPictureResource.baseArrayLayer);
#if GFX_VERx10 == 70 #if GFX_VERx10 == 70
if (is_reference) {
buf.PostDeblockingDestinationAddress = dst_addr; buf.PostDeblockingDestinationAddress = dst_addr;
buf.PostDeblockingDestinationCacheabilityControl = 2; buf.PostDeblockingDestinationCacheabilityControl = 2;
} else {
buf.PreDeblockingDestinationAddress = dst_addr;
}
#else #else
if (is_reference)
buf.PostDeblockingDestinationAddress = dst_addr; buf.PostDeblockingDestinationAddress = dst_addr;
else
buf.PreDeblockingDestinationAddress = dst_addr;
buf.PreDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PreDeblockingDestinationAddress.bo, 0); buf.PreDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PreDeblockingDestinationAddress.bo, 0);
buf.PostDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PostDeblockingDestinationAddress.bo, 0); buf.PostDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PostDeblockingDestinationAddress.bo, 0);
buf.OriginalUncompressedPictureSourceMOCS = anv_mocs(cmd_buffer->device, NULL, 0); buf.OriginalUncompressedPictureSourceMOCS = anv_mocs(cmd_buffer->device, NULL, 0);
@@ -334,8 +359,9 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
if (hw < 0) if (hw < 0)
continue; continue;
const struct anv_image_view *ref_iv = anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding); const struct anv_image_view *ref_iv = anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding);
struct anv_address ref_addr = anv_image_address(ref_iv->image, struct anv_address ref_addr =
&ref_iv->image->planes[0].primary_surface.memory_range); anv_image_dpb_address(ref_iv,
frame_info->pReferenceSlots[i].pPictureResource->baseArrayLayer);
buf.ReferencePictureAddress[hw] = ref_addr; buf.ReferencePictureAddress[hw] = ref_addr;
#if GFX_VERx10 == 70 #if GFX_VERx10 == 70
@@ -454,6 +480,28 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
avc_img.CurrentPictureFrameNumber = h264_pic_info->pStdPictureInfo->frame_num; avc_img.CurrentPictureFrameNumber = h264_pic_info->pStdPictureInfo->frame_num;
} }
if (INTEL_DEBUG(DEBUG_PERF) &&
h264_pic_info->pStdPictureInfo->flags.field_pic_flag) {
const StdVideoDecodeH264PictureInfo *p = h264_pic_info->pStdPictureInfo;
mesa_logw("hasvk/img: field_pic=%u bottom=%u mb_adaptive=%u frame_mbs_only=%u "
"mbaff_frame_flag=%u width_mbs=%u height_mbs=%u chroma_idc=%u entropy=%u "
"8x8=%u chroma_qp=%d/%d init_qp_m26=%d wp=%u wbi=%u frame_num=%u poc=%d/%d "
"constr_intra=%u num_ref=%u nact_l0=%u nact_l1=%u",
p->flags.field_pic_flag, p->flags.bottom_field_flag,
sps->flags.mb_adaptive_frame_field_flag, sps->flags.frame_mbs_only_flag,
(unsigned)(sps->flags.mb_adaptive_frame_field_flag && !p->flags.field_pic_flag),
frame_width_mbs, frame_height_mbs, sps->chroma_format_idc,
pps->flags.entropy_coding_mode_flag, pps->flags.transform_8x8_mode_flag,
pps->chroma_qp_index_offset, pps->second_chroma_qp_index_offset,
pps->pic_init_qp_minus26, pps->flags.weighted_pred_flag,
pps->weighted_bipred_idc, p->frame_num,
p->PicOrderCnt[0], p->PicOrderCnt[1],
pps->flags.constrained_intra_pred_flag,
frame_info->referenceSlotCount,
pps->num_ref_idx_l0_default_active_minus1 + 1,
pps->num_ref_idx_l1_default_active_minus1 + 1);
}
StdVideoH264ScalingLists scaling_lists; StdVideoH264ScalingLists scaling_lists;
vk_video_derive_h264_scaling_list(sps, pps, &scaling_lists); vk_video_derive_h264_scaling_list(sps, pps, &scaling_lists);
anv_batch_emit(&cmd_buffer->batch, GENX(MFX_QM_STATE), qm) { anv_batch_emit(&cmd_buffer->batch, GENX(MFX_QM_STATE), qm) {
@@ -589,16 +637,27 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
vk_find_struct_const(frame_info->pReferenceSlots[i].pNext, VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR); vk_find_struct_const(frame_info->pReferenceSlots[i].pNext, VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR);
const struct anv_image_view *ref_iv = anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding); const struct anv_image_view *ref_iv = anv_image_view_from_handle(frame_info->pReferenceSlots[i].pPictureResource->imageViewBinding);
const StdVideoDecodeH264ReferenceInfo *ref_info = dpb_slot->pStdReferenceInfo; const StdVideoDecodeH264ReferenceInfo *ref_info = dpb_slot->pStdReferenceInfo;
uint32_t ref_layer =
frame_info->pReferenceSlots[i].pPictureResource->baseArrayLayer;
if (i == 0) if (i == 0)
dmv_bo = anv_image_address(ref_iv->image, &ref_iv->image->vid_dmv_top_surface).bo; dmv_bo = anv_image_dmv_top_address(ref_iv, ref_layer).bo;
#if GFX_VERx10 == 70 #if GFX_VERx10 == 70
avc_directmode.DirectMVBufferAddress[hw * 2] = anv_image_address(ref_iv->image, &ref_iv->image->vid_dmv_top_surface); {
avc_directmode.DirectMVBufferAddress[hw * 2 + 1] = anv_image_address(ref_iv->image, &ref_iv->image->vid_dmv_bottom_surface); bool ref_is_field = ref_info &&
(ref_info->flags.top_field_flag ^ ref_info->flags.bottom_field_flag);
bool ref_dmv_bottom = ref_is_field &&
!sps->flags.direct_8x8_inference_flag;
avc_directmode.DirectMVBufferAddress[hw * 2] =
anv_image_dmv_top_address(ref_iv, ref_layer);
avc_directmode.DirectMVBufferAddress[hw * 2 + 1] = ref_dmv_bottom ?
anv_image_dmv_bottom_address(ref_iv, ref_layer) :
anv_image_dmv_top_address(ref_iv, ref_layer);
}
avc_directmode.DirectMVBufferCacheabilityControl[hw * 2] = 2; avc_directmode.DirectMVBufferCacheabilityControl[hw * 2] = 2;
avc_directmode.DirectMVBufferCacheabilityControl[hw * 2 + 1] = 2; avc_directmode.DirectMVBufferCacheabilityControl[hw * 2 + 1] = 2;
#elif GFX_VERx10 == 75 #elif GFX_VERx10 == 75
{ {
struct anv_address dmv_addr = anv_image_address(ref_iv->image, &ref_iv->image->vid_dmv_top_surface); struct anv_address dmv_addr = anv_image_dmv_top_address(ref_iv, ref_layer);
if (hw == 0) { if (hw == 0) {
avc_directmode.DirectMVBuffer0Address = dmv_addr; avc_directmode.DirectMVBuffer0Address = dmv_addr;
avc_directmode.DirectMVBufferMOCS = anv_mocs(cmd_buffer->device, dmv_addr.bo, 0); avc_directmode.DirectMVBufferMOCS = anv_mocs(cmd_buffer->device, dmv_addr.bo, 0);
@@ -608,29 +667,44 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
} }
} }
#elif GFX_VERx10 == 80 #elif GFX_VERx10 == 80
avc_directmode.DirectMVBufferAddress[hw] = anv_image_address(ref_iv->image, avc_directmode.DirectMVBufferAddress[hw] = anv_image_dmv_top_address(ref_iv, ref_layer);
&ref_iv->image->vid_dmv_top_surface);
#endif #endif
avc_directmode.POCList[2 * hw] = ref_info->PicOrderCnt[0]; {
avc_directmode.POCList[2 * hw + 1] = ref_info->PicOrderCnt[1]; int32_t ref_top, ref_bot;
anv_h264_sane_field_pocs(ref_info->PicOrderCnt, &ref_top, &ref_bot);
avc_directmode.POCList[2 * hw] = ref_top;
avc_directmode.POCList[2 * hw + 1] = ref_bot;
} }
}
uint32_t dst_layer = frame_info->dstPictureResource.baseArrayLayer;
#if GFX_VERx10 == 70 #if GFX_VERx10 == 70
avc_directmode.DirectMVBufferWriteAddress[0] = anv_image_address(img, &img->vid_dmv_top_surface); {
avc_directmode.DirectMVBufferWriteAddress[1] = anv_image_address(img, &img->vid_dmv_bottom_surface); bool cur_dmv_bottom = field_pic && !sps->flags.direct_8x8_inference_flag;
avc_directmode.DirectMVBufferWriteAddress[0] =
anv_image_dmv_top_address(iv, dst_layer);
avc_directmode.DirectMVBufferWriteAddress[1] = cur_dmv_bottom ?
anv_image_dmv_bottom_address(iv, dst_layer) :
anv_image_dmv_top_address(iv, dst_layer);
}
avc_directmode.DirectMVBufferWriteCacheabilityControl[0] = 2; avc_directmode.DirectMVBufferWriteCacheabilityControl[0] = 2;
avc_directmode.DirectMVBufferWriteCacheabilityControl[1] = 2; avc_directmode.DirectMVBufferWriteCacheabilityControl[1] = 2;
#elif GFX_VERx10 == 75 #elif GFX_VERx10 == 75
avc_directmode.DirectMVBufferWriteAddress = anv_image_address(img, &img->vid_dmv_top_surface); avc_directmode.DirectMVBufferWriteAddress = anv_image_dmv_top_address(iv, dst_layer);
avc_directmode.DirectMVBufferWriteMOCS = anv_mocs(cmd_buffer->device, avc_directmode.DirectMVBufferWriteAddress.bo, 0); avc_directmode.DirectMVBufferWriteMOCS = anv_mocs(cmd_buffer->device, avc_directmode.DirectMVBufferWriteAddress.bo, 0);
if (!avc_directmode.DirectMVBufferMOCS) if (!avc_directmode.DirectMVBufferMOCS)
avc_directmode.DirectMVBufferMOCS = anv_mocs(cmd_buffer->device, avc_directmode.DirectMVBufferWriteAddress.bo, 0); avc_directmode.DirectMVBufferMOCS = anv_mocs(cmd_buffer->device, avc_directmode.DirectMVBufferWriteAddress.bo, 0);
#elif GFX_VERx10 == 80 #elif GFX_VERx10 == 80
avc_directmode.DirectMVBufferAttributes.TargetCache = 2; /* LLC/eLLC */ avc_directmode.DirectMVBufferAttributes.TargetCache = 2; /* LLC/eLLC */
avc_directmode.DirectMVBufferWriteAddress = anv_image_address(img, &img->vid_dmv_top_surface); avc_directmode.DirectMVBufferWriteAddress = anv_image_dmv_top_address(iv, dst_layer);
avc_directmode.DirectMVBufferWriteAttributes.TargetCache = 2; avc_directmode.DirectMVBufferWriteAttributes.TargetCache = 2;
#endif #endif
avc_directmode.POCList[32] = h264_pic_info->pStdPictureInfo->PicOrderCnt[0]; {
avc_directmode.POCList[33] = h264_pic_info->pStdPictureInfo->PicOrderCnt[1]; int32_t cur_top, cur_bot;
anv_h264_sane_field_pocs(h264_pic_info->pStdPictureInfo->PicOrderCnt,
&cur_top, &cur_bot);
avc_directmode.POCList[32] = cur_top;
avc_directmode.POCList[33] = cur_bot;
}
} }
const struct anv_h264_slice_params *cur = sp ? &sp[s] : NULL; const struct anv_h264_slice_params *cur = sp ? &sp[s] : NULL;
@@ -654,21 +728,31 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
if (hw < 0) { if (hw < 0) {
ref_idx.ReferenceListEntry[e] = 0xFF; ref_idx.ReferenceListEntry[e] = 0xFF;
} else { } else {
bool is_long = false; bool is_long = false, ref_top = false, ref_bottom_f = false;
for (uint32_t i = 0; i < frame_info->referenceSlotCount; i++) { for (uint32_t i = 0; i < frame_info->referenceSlotCount; i++) {
if (frame_info->pReferenceSlots[i].slotIndex == slot) { if (frame_info->pReferenceSlots[i].slotIndex == slot) {
const struct VkVideoDecodeH264DpbSlotInfoKHR *d = const struct VkVideoDecodeH264DpbSlotInfoKHR *d =
vk_find_struct_const(frame_info->pReferenceSlots[i].pNext, vk_find_struct_const(frame_info->pReferenceSlots[i].pNext,
VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR); VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR);
if (d && d->pStdReferenceInfo) if (d && d->pStdReferenceInfo) {
is_long = d->pStdReferenceInfo->flags.used_for_long_term_reference; is_long = d->pStdReferenceInfo->flags.used_for_long_term_reference ||
d->pStdReferenceInfo->flags.is_non_existing;
ref_top = d->pStdReferenceInfo->flags.top_field_flag;
ref_bottom_f = d->pStdReferenceInfo->flags.bottom_field_flag;
}
break; break;
} }
} }
bool ref_bottom = field_pic && rlb && if (field_pic && rlb && e < ANV_H264_MAX_REF_FRAMES) {
e < ANV_H264_MAX_REF_FRAMES && rlb[e]; ref_bottom_f = rlb[e];
ref_top = !rlb[e];
}
bool ref_is_field = ref_top ^ ref_bottom_f;
bool ref_bottom = (!ref_top) & ref_bottom_f;
ref_idx.ReferenceListEntry[e] = ref_idx.ReferenceListEntry[e] =
(is_long ? 0x60u : 0x20u) | ((uint8_t)hw << 1) | (is_long ? 0x40u : 0x00u) |
(ref_is_field ? 0x00u : 0x20u) |
((uint8_t)hw << 1) |
(ref_bottom ? 0x01u : 0x00u); (ref_bottom ? 0x01u : 0x00u);
} }
} }
@@ -799,6 +883,27 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
ss.LastSliceGroup = last_slice; ss.LastSliceGroup = last_slice;
ss.SliceID = s & (uint32_t)((1u << 4) - 1); ss.SliceID = s & (uint32_t)((1u << 4) - 1);
} }
if (INTEL_DEBUG(DEBUG_PERF) && field_pic && cur) {
char l0[128] = {0}, l1[128] = {0};
for (int e = 0; e < 8; e++) {
char t[16];
snprintf(t, sizeof(t), "%d ", (int8_t)cur->ref_list0[e]);
strncat(l0, t, sizeof(l0) - strlen(l0) - 1);
snprintf(t, sizeof(t), "%d ", (int8_t)cur->ref_list1[e]);
strncat(l1, t, sizeof(l1) - strlen(l1) - 1);
}
mesa_logw("hasvk/slice[%u]: type=%d first_mb=%u qp=%d cabac_init=%d "
"disable_dblk=%d spatial_direct=%d nref_l0=%d nref_l1=%d "
"hor=%u ver=%u next_hor=%u next_ver=%u last=%d | L0: %s| L1: %s",
s, st, cur_fmb,
(int)(pps->pic_init_qp_minus26 + 26 + cur->slice_qp_delta),
cur->cabac_init_idc, cur->disable_deblocking_filter_idc,
cur->direct_spatial_mv_pred_flag,
cur->num_ref_idx_l0_active_minus1 + 1,
cur->num_ref_idx_l1_active_minus1 + 1,
cur_hor, cur_ver, next_hor, next_ver, last_slice, l0, l1);
}
} }
uint32_t bsd_nal = bs_map ? uint32_t bsd_nal = bs_map ?
@@ -808,12 +913,8 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer,
buffer_offset + this_end) : buffer_offset + this_end) :
buffer_offset + current_offset + HEADER_OFFSET; buffer_offset + current_offset + HEADER_OFFSET;
anv_batch_emit(&cmd_buffer->batch, GENX(MFD_AVC_BSD_OBJECT), avc_bsd) { anv_batch_emit(&cmd_buffer->batch, GENX(MFD_AVC_BSD_OBJECT), avc_bsd) {
#if GFX_VERx10 == 70 /* Bound the bitstream object to this slice's data. */
avc_bsd.IndirectBSDDataLength =
buffer_offset + frame_info->srcBufferRange - bsd_nal;
#else
avc_bsd.IndirectBSDDataLength = buffer_offset + this_end - bsd_nal; avc_bsd.IndirectBSDDataLength = buffer_offset + this_end - bsd_nal;
#endif
avc_bsd.IndirectBSDDataStartAddress = bsd_nal; avc_bsd.IndirectBSDDataStartAddress = bsd_nal;
avc_bsd.InlineData.LastSlice = last_slice; avc_bsd.InlineData.LastSlice = last_slice;
avc_bsd.InlineData.FixPrevMBSkipped = 1; avc_bsd.InlineData.FixPrevMBSkipped = 1;