mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-10-31 10:58:03 +03:00
hasvk: Initial layered DPB support and plenty of debug output.
Assisted-by: Claude
This commit is contained in:
1 parent
72177c94e1
commit
4204b5ff5b
3 files changed
+327
-44
No files matched your search
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in new issue
Block a user