From 4204b5ff5b1610d2216bb2ad3b3b88b589227380 Mon Sep 17 00:00:00 2001 From: dancingmirrors Date: Tue, 7 Jul 2026 15:12:20 -0600 Subject: [PATCH] hasvk: Initial layered DPB support and plenty of debug output. Assisted-by: Claude --- src/intel/vulkan_hasvk/anv_image.c | 125 +++++++++++++++- src/intel/vulkan_hasvk/anv_private.h | 63 ++++++++ src/intel/vulkan_hasvk/genX_cmd_video.c | 191 ++++++++++++++++++------ 3 files changed, 331 insertions(+), 48 deletions(-) diff --git a/src/intel/vulkan_hasvk/anv_image.c b/src/intel/vulkan_hasvk/anv_image.c index 0d70d23..3e02d4e 100644 --- a/src/intel/vulkan_hasvk/anv_image.c +++ b/src/intel/vulkan_hasvk/anv_image.c @@ -711,8 +711,10 @@ add_video_buffers(struct anv_device *device, if (device->info->ver == 7) { /* However for frames wider than 128 MBs we need to make sure we * 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 { /* XXX: Is this correct for Broadwell? */ size = w_mb * h_mb * 128; @@ -723,16 +725,34 @@ add_video_buffers(struct anv_device *device, if (size == 0) 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 = 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); if (result != VK_SUCCESS) 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 = 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); return result; } @@ -997,6 +1017,94 @@ check_drm_format_mod(const struct anv_device *device, 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 * VkImageDrmFormatModifierExplicitCreateInfoEXT. @@ -1013,6 +1121,17 @@ add_all_surfaces_implicit_layout( const struct intel_device_info *devinfo = device->info; 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) { VkImageAspectFlagBits aspect = 1 << b; const uint32_t plane = anv_image_aspect_to_plane(image, aspect); diff --git a/src/intel/vulkan_hasvk/anv_private.h b/src/intel/vulkan_hasvk/anv_private.h index 91cb21a..680be5a 100644 --- a/src/intel/vulkan_hasvk/anv_private.h +++ b/src/intel/vulkan_hasvk/anv_private.h @@ -3299,6 +3299,10 @@ struct anv_image { struct anv_image_memory_range vid_dmv_top_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 @@ -3590,6 +3594,65 @@ enum anv_image_view_state_flags { 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, const struct anv_image *image, VkImageAspectFlagBits aspect, diff --git a/src/intel/vulkan_hasvk/genX_cmd_video.c b/src/intel/vulkan_hasvk/genX_cmd_video.c index 5b58daa..61a6011 100644 --- a/src/intel/vulkan_hasvk/genX_cmd_video.c +++ b/src/intel/vulkan_hasvk/genX_cmd_video.c @@ -154,6 +154,15 @@ void genX(CmdEndVideoCodingKHR) (VkCommandBuffer commandBuffer, 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 anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, const VkVideoDecodeInfoKHR *frame_info) @@ -204,22 +213,45 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, flush.VideoPipelineCacheInvalidate = 1; }; - const bool is_reference = frame_info->pSetupReferenceSlot != NULL; - anv_batch_emit(&cmd_buffer->batch, GENX(MFX_PIPE_MODE_SELECT), sel) { sel.StandardSelect = SS_AVC; sel.CodecSelect = Decode; sel.DecoderShortFormatMode = LongFormatDriverInterface; - sel.PreDeblockingOutputEnable = !is_reference; - sel.PostDeblockingOutputEnable = is_reference; + sel.PreDeblockingOutputEnable = false; + sel.PostDeblockingOutputEnable = true; sel.DecoderModeSelect = VLDMode; } const struct anv_image_view *iv = anv_image_view_from_handle(frame_info->dstPictureResource.imageViewBinding); const struct anv_image *img = iv->image; - if (sps->chroma_format_idc == 0) - anv_video_init_neutral_chroma(cmd_buffer->device, img); + 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); + 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_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.CommandType = 3; - struct anv_address dst_addr = anv_image_address(img, - &img->planes[0].primary_surface.memory_range); + struct anv_address dst_addr = + anv_image_dpb_address(iv, frame_info->dstPictureResource.baseArrayLayer); #if GFX_VERx10 == 70 - if (is_reference) { - buf.PostDeblockingDestinationAddress = dst_addr; - buf.PostDeblockingDestinationCacheabilityControl = 2; - } else { - buf.PreDeblockingDestinationAddress = dst_addr; - } + buf.PostDeblockingDestinationAddress = dst_addr; + buf.PostDeblockingDestinationCacheabilityControl = 2; #else - if (is_reference) - buf.PostDeblockingDestinationAddress = dst_addr; - else - buf.PreDeblockingDestinationAddress = dst_addr; + buf.PostDeblockingDestinationAddress = dst_addr; buf.PreDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PreDeblockingDestinationAddress.bo, 0); buf.PostDeblockingDestinationMOCS = anv_mocs(cmd_buffer->device, buf.PostDeblockingDestinationAddress.bo, 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) continue; 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, - &ref_iv->image->planes[0].primary_surface.memory_range); + struct anv_address ref_addr = + anv_image_dpb_address(ref_iv, + frame_info->pReferenceSlots[i].pPictureResource->baseArrayLayer); buf.ReferencePictureAddress[hw] = ref_addr; #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; } + 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; vk_video_derive_h264_scaling_list(sps, pps, &scaling_lists); 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); 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; + uint32_t ref_layer = + frame_info->pReferenceSlots[i].pPictureResource->baseArrayLayer; 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 - 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 + 1] = 2; #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) { avc_directmode.DirectMVBuffer0Address = dmv_addr; 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 - avc_directmode.DirectMVBufferAddress[hw] = anv_image_address(ref_iv->image, - &ref_iv->image->vid_dmv_top_surface); + avc_directmode.DirectMVBufferAddress[hw] = anv_image_dmv_top_address(ref_iv, ref_layer); #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 - 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[1] = 2; #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); if (!avc_directmode.DirectMVBufferMOCS) avc_directmode.DirectMVBufferMOCS = anv_mocs(cmd_buffer->device, avc_directmode.DirectMVBufferWriteAddress.bo, 0); #elif GFX_VERx10 == 80 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; #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; @@ -654,21 +728,31 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, if (hw < 0) { ref_idx.ReferenceListEntry[e] = 0xFF; } 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++) { if (frame_info->pReferenceSlots[i].slotIndex == slot) { const struct VkVideoDecodeH264DpbSlotInfoKHR *d = vk_find_struct_const(frame_info->pReferenceSlots[i].pNext, VIDEO_DECODE_H264_DPB_SLOT_INFO_KHR); - if (d && d->pStdReferenceInfo) - is_long = d->pStdReferenceInfo->flags.used_for_long_term_reference; + if (d && d->pStdReferenceInfo) { + 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; } } - bool ref_bottom = field_pic && rlb && - e < ANV_H264_MAX_REF_FRAMES && rlb[e]; + if (field_pic && rlb && e < ANV_H264_MAX_REF_FRAMES) { + 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] = - (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); } } @@ -799,6 +883,27 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, ss.LastSliceGroup = last_slice; 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 ? @@ -808,12 +913,8 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, buffer_offset + this_end) : buffer_offset + current_offset + HEADER_OFFSET; anv_batch_emit(&cmd_buffer->batch, GENX(MFD_AVC_BSD_OBJECT), avc_bsd) { -#if GFX_VERx10 == 70 - avc_bsd.IndirectBSDDataLength = - buffer_offset + frame_info->srcBufferRange - bsd_nal; -#else + /* Bound the bitstream object to this slice's data. */ avc_bsd.IndirectBSDDataLength = buffer_offset + this_end - bsd_nal; -#endif avc_bsd.IndirectBSDDataStartAddress = bsd_nal; avc_bsd.InlineData.LastSlice = last_slice; avc_bsd.InlineData.FixPrevMBSkipped = 1;