anv: add initial support for AV1 decoding

Co-authored-by: Hyunjun Ko <zzoon@igalia.com>
- Allow intrabc
- Fix to manage refrenece frames using referenceNameSlotIndices
- Fix to set bitmask of motion field projection correctly
- Set destination buffer offset to the BSD_OBJECT
- Support 10-bit decoding.
- Fix small bugs.
- Change to C-style comment.

Signed-off-by: Hyunjun Ko <zzoon@igalia.com>
Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32775>
This commit is contained in:
Dave Airlie
2024-02-02 13:31:30 +10:00
committed by Marge Bot
parent 0fd0a51df6
commit 8432b8b282
5 changed files with 1569 additions and 15 deletions

View File

@@ -36,6 +36,7 @@
#include "util/u_math.h"
#include "vk_format.h"
#include "av1_tables.h"
#define ANV_OFFSET_IMPLICIT UINT64_MAX
@@ -946,19 +947,7 @@ add_video_buffers(struct anv_device *device,
unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
size = w_mb * h_mb * 128;
} else {
for (unsigned i = 0; i < profile_list->profileCount; i++) {
if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR ||
profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR) {
unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, ANV_MB_WIDTH);
unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
size = w_mb * h_mb * 128;
} else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR ||
profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR) {
unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, 32);
unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, 32);
size = ALIGN(w_mb * h_mb, 2) << 6;
}
}
size = anv_video_get_image_mv_size(device, image, profile_list);
}
if (size == 0)
@@ -966,6 +955,19 @@ add_video_buffers(struct anv_device *device,
ok = image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE,
ANV_OFFSET_IMPLICIT, size, 65536, &image->vid_dmv_top_surface);
if (ok != VK_SUCCESS)
return ok;
/* Doesn't work for av1 without provided profiles */
if (!independent_profile) {
for (unsigned i = 0; i < profile_list->profileCount; i++) {
if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
ok = image_binding_grow(device, image, ANV_IMAGE_MEMORY_BINDING_PRIVATE,
ANV_OFFSET_IMPLICIT, av1_cdf_max_num_bytes, 4096, &image->av1_cdf_table);
}
}
}
return ok;
}

View File

@@ -238,6 +238,7 @@ get_device_extensions(const struct anv_physical_device *device,
.KHR_video_decode_queue = device->video_decode_enabled,
.KHR_video_decode_h264 = VIDEO_CODEC_H264DEC && device->video_decode_enabled,
.KHR_video_decode_h265 = VIDEO_CODEC_H265DEC && device->video_decode_enabled,
.KHR_video_decode_av1 = device->info.ver >= 12 && VIDEO_CODEC_AV1DEC && device->video_decode_enabled,
.KHR_video_encode_queue = device->video_encode_enabled,
.KHR_video_encode_h264 = VIDEO_CODEC_H264ENC && device->video_encode_enabled,
.KHR_video_encode_h265 = device->info.ver >= 12 && VIDEO_CODEC_H265ENC && device->video_encode_enabled,
@@ -2810,6 +2811,8 @@ void anv_GetPhysicalDeviceQueueFamilyProperties2(
if (queue_family->queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
prop->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR |
VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR;
if (pdevice->info.ver >= 12)
prop->videoCodecOperations |= VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR;
}
if (queue_family->queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) {

View File

@@ -5525,6 +5525,7 @@ struct anv_image {
/* Link in the anv_device.image_private_objects list */
struct list_head link;
struct anv_image_memory_range av1_cdf_table;
};
static inline bool
@@ -6315,11 +6316,52 @@ enum anv_vid_mem_h265_types {
ANV_VID_MEM_H265_ENC_MAX,
};
enum anv_vid_mem_av1_types {
ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE,
ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE,
ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE,
ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE,
ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE,
ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE,
ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U,
ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V,
ANV_VID_MEM_AV1_CDEF_FILTER_LINE,
ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE,
ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN,
ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE,
ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN,
ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER,
ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y,
ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U,
ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U,
ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V,
ANV_VID_MEM_AV1_CDF_DEFAULTS_0,
ANV_VID_MEM_AV1_CDF_DEFAULTS_1,
ANV_VID_MEM_AV1_CDF_DEFAULTS_2,
ANV_VID_MEM_AV1_CDF_DEFAULTS_3,
ANV_VID_MEM_AV1_DBD_BUFFER,
ANV_VID_MEM_AV1_MAX,
};
struct anv_video_session {
struct vk_video_session vk;
bool cdf_initialized;
/* the decoder needs some private memory allocations */
struct anv_vid_mem vid_mem[ANV_VID_MEM_H265_ENC_MAX];
struct anv_vid_mem vid_mem[ANV_VID_MEM_AV1_MAX];
};
struct anv_video_session_params {
@@ -6327,6 +6369,13 @@ struct anv_video_session_params {
VkVideoEncodeRateControlModeFlagBitsKHR rc_mode;
};
void anv_init_av1_cdf_tables(struct anv_cmd_buffer *cmd,
struct anv_video_session *vid);
uint32_t anv_video_get_image_mv_size(struct anv_device *device,
struct anv_image *image,
const struct VkVideoProfileListInfoKHR *profile_list);
void
anv_dump_pipe_bits(enum anv_pipe_bits bits, FILE *f);

View File

@@ -23,6 +23,7 @@
#include "anv_private.h"
#include "av1_tables.h"
#include "vk_video/vulkan_video_codecs_common.h"
VkResult
@@ -115,13 +116,18 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
pCapabilities->minBitstreamBufferOffsetAlignment = 32;
pCapabilities->minBitstreamBufferSizeAlignment = 32;
pCapabilities->minBitstreamBufferSizeAlignment = 1;
pCapabilities->pictureAccessGranularity.width = ANV_MB_WIDTH;
pCapabilities->pictureAccessGranularity.height = ANV_MB_HEIGHT;
pCapabilities->minCodedExtent.width = ANV_MB_WIDTH;
pCapabilities->minCodedExtent.height = ANV_MB_HEIGHT;
pCapabilities->maxCodedExtent.width = 4096;
pCapabilities->maxCodedExtent.height = 4096;
pCapabilities->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR;
struct VkVideoDecodeCapabilitiesKHR *dec_caps = (struct VkVideoDecodeCapabilitiesKHR *)
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_CAPABILITIES_KHR);
if (dec_caps)
dec_caps->flags = VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR;
@@ -154,6 +160,31 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice,
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION;
break;
}
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: {
const struct VkVideoDecodeAV1ProfileInfoKHR *av1_profile =
vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_AV1_PROFILE_INFO_KHR);
if (av1_profile->stdProfile != STD_VIDEO_AV1_PROFILE_MAIN)
return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR;
if (pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR &&
pVideoProfile->lumaBitDepth != VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR)
return VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR;
struct VkVideoDecodeAV1CapabilitiesKHR *ext = (struct VkVideoDecodeAV1CapabilitiesKHR *)
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_AV1_CAPABILITIES_KHR);
ext->maxLevel = STD_VIDEO_AV1_LEVEL_6_0;
pCapabilities->maxDpbSlots = 8;
pCapabilities->maxActiveReferencePictures = 7;
dec_caps->flags |= VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_DISTINCT_BIT_KHR;
strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_EXTENSION_NAME);
pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_AV1_DECODE_SPEC_VERSION;
break;
}
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: {
struct VkVideoDecodeH265CapabilitiesKHR *ext = (struct VkVideoDecodeH265CapabilitiesKHR *)
vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H265_CAPABILITIES_KHR);
@@ -485,6 +516,192 @@ get_h265_video_session_mem_reqs(struct anv_video_session *vid,
}
}
static const uint8_t av1_buffer_size[ANV_VID_MEM_AV1_MAX][4] = {
{ 2 , 4 , 2 , 4 }, /* bsdLineBuf, */
{ 2 , 4 , 2 , 4 }, /* bsdTileLineBuf, */
{ 2 , 4 , 4 , 8 }, /* intraPredLine, */
{ 2 , 4 , 4 , 8 }, /* intraPredTileLine, */
{ 4 , 8 , 4 , 8 }, /* spatialMvLineBuf, */
{ 4 , 8 , 4 , 8 }, /* spatialMvTileLineBuf, */
{ 1 , 1 , 1 , 1 }, /* lrMetaTileCol, */
{ 7 , 7 , 7 , 7 }, /* lrTileLineY, */
{ 5 , 5 , 5 , 5 }, /* lrTileLineU, */
{ 5 , 5 , 5 , 5 }, /* lrTileLineV, */
{ 9 , 17 , 11 , 21 }, /* deblockLineYBuf, */
{ 3 , 4 , 3 , 5 }, /* deblockLineUBuf, */
{ 3 , 4 , 3 , 5 }, /* deblockLineVBuf, */
{ 9 , 17 , 11 , 21 }, /* deblockTileLineYBuf, */
{ 3 , 4 , 3 , 5 }, /* deblockTileLineVBuf, */
{ 3 , 4 , 3 , 5 }, /* deblockTileLineUBuf, */
{ 8 , 16 , 10 , 20 }, /* deblockTileColYBuf, */
{ 2 , 4 , 3 , 5 }, /* deblockTileColUBuf, */
{ 2 , 4 , 3 , 5 }, /* deblockTileColVBuf, */
{ 8 , 16 , 10 , 20 }, /* cdefLineBuf, */
{ 8 , 16 , 10 , 20 }, /* cdefTileLineBuf, */
{ 8 , 16 , 10 , 20 }, /* cdefTileColBuf, */
{ 1 , 1 , 1 , 1 }, /* cdefMetaTileLine, */
{ 1 , 1 , 1 , 1 }, /* cdefMetaTileCol, */
{ 1 , 1 , 1 , 1 }, /* cdefTopLeftCornerBuf, */
{ 22, 44 , 29 , 58 }, /* superResTileColYBuf, */
{ 8 , 16 , 10 , 20 }, /* superResTileColUBuf, */
{ 8 , 16 , 10 , 20 }, /* superResTileColVBuf, */
{ 9 , 17 , 11 , 22 }, /* lrTileColYBuf, */
{ 5 , 9 , 6 , 12 }, /* lrTileColUBuf, */
{ 5 , 9 , 6 , 12 }, /* lrTileColVBuf, */
};
static const uint8_t av1_buffer_size_ext[ANV_VID_MEM_AV1_MAX][4] = {
{ 0 , 0 , 0 , 0 }, /* bsdLineBuf, */
{ 0 , 0 , 0 , 0 }, /* bsdTileLineBuf, */
{ 0 , 0 , 0 , 0 }, /* intraPredLine, */
{ 0 , 0 , 0 , 0 }, /* intraPredTileLine, */
{ 0 , 0 , 0 , 0 }, /* spatialMvLineBuf, */
{ 0 , 0 , 0 , 0 }, /* spatialMvTileLineBuf, */
{ 1 , 1 , 1 , 1 }, /* lrMetaTileCol, */
{ 0 , 0 , 0 , 0 }, /* lrTileLineY, */
{ 0 , 0 , 0 , 0 }, /* lrTileLineU, */
{ 0 , 0 , 0 , 0 }, /* lrTileLineV, */
{ 0 , 0 , 0 , 0 }, /* deblockLineYBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockLineUBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockLineVBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileLineYBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileLineVBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileLineUBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileColYBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileColUBuf, */
{ 0 , 0 , 0 , 0 }, /* deblockTileColVBuf, */
{ 1 , 1 , 2 , 2 }, /* cdefLineBuf, */
{ 1 , 1 , 2 , 2 }, /* cdefTileLineBuf, */
{ 1 , 1 , 2 , 2 }, /* cdefTileColBuf, */
{ 0 , 0 , 0 , 0 }, /* cdefMetaTileLine, */
{ 1 , 1 , 1 , 1 }, /* cdefMetaTileCol, */
{ 0 , 0 , 0 , 0 }, /* cdefTopLeftCornerBuf, */
{ 22, 44 , 29 , 58 }, /* superResTileColYBuf, */
{ 8 , 16 , 10 , 20 }, /* superResTileColUBuf, */
{ 8 , 16 , 10 , 20 }, /* superResTileColVBuf, */
{ 2 , 2 , 2 , 2 }, /* lrTileColYBuf, */
{ 1 , 1 , 1 , 1 }, /* lrTileColUBuf, */
{ 1 , 1 , 1 , 1 }, /* lrTileColVBuf, */
};
static void
get_av1_video_session_mem_reqs(struct anv_video_session *vid,
VkVideoSessionMemoryRequirementsKHR *mem_reqs,
uint32_t *pVideoSessionMemoryRequirementsCount,
uint32_t memory_types)
{
VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
out,
mem_reqs,
pVideoSessionMemoryRequirementsCount);
const uint32_t av1_mi_size_log2 = 2;
const uint32_t av1_max_mib_size_log2 = 5;
uint32_t width = vid->vk.max_coded.width;
uint32_t height = vid->vk.max_coded.height;
uint32_t mi_cols = width >> av1_mi_size_log2;
uint32_t mi_rows = height >> av1_mi_size_log2;
uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
uint32_t max_tile_width_sb = DIV_ROUND_UP(4096, 1 << (av1_max_mib_size_log2 + av1_mi_size_log2));
uint32_t max_tile_cols = 16; /* TODO. get the profile to work this out */
/* Assume 8-bit 128x128 sb is true, can't know at this point */
int buf_size_idx = 1;
for (enum anv_vid_mem_av1_types mem = ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE;
mem < ANV_VID_MEM_AV1_MAX; mem++) {
VkDeviceSize buffer_size = 0;
switch (mem) {
case ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE:
case ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE:
case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V:
buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_CDEF_FILTER_LINE:
buffer_size = max_tile_width_sb * av1_buffer_size[mem][buf_size_idx] +
av1_buffer_size_ext[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE:
case ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE:
case ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V:
buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y:
buffer_size = max_tile_cols * 7;
break;
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U:
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V:
buffer_size = max_tile_cols * 5;
break;
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U:
case ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V:
buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE:
buffer_size = width_in_sb * av1_buffer_size[mem][buf_size_idx] +
av1_buffer_size_ext[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE:
buffer_size = max_tile_cols;
break;
case ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER:
buffer_size = max_tile_cols * 8; /* TODO. take from profile */
break;
case ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN:
case ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN:
case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y:
case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U:
case ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V:
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y:
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U:
case ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V:
case ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN:
buffer_size = height_in_sb * av1_buffer_size[mem][buf_size_idx] +
av1_buffer_size_ext[mem][buf_size_idx];
break;
case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
buffer_size = av1_cdf_max_num_bytes;
break;
case ANV_VID_MEM_AV1_DBD_BUFFER:
buffer_size = 1;
break;
default:
assert(0);
break;
}
switch (mem) {
case ANV_VID_MEM_AV1_CDF_DEFAULTS_0:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_1:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_2:
case ANV_VID_MEM_AV1_CDF_DEFAULTS_3:
break;
default:
buffer_size *= 64;
break;
}
vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) {
p->memoryBindIndex = mem;
p->memoryRequirements.size = buffer_size;
p->memoryRequirements.alignment = 4096;
p->memoryRequirements.memoryTypeBits = memory_types;
}
}
}
VkResult
anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,
VkVideoSessionKHR videoSession,
@@ -523,6 +740,12 @@ anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,
pVideoSessionMemoryRequirementsCount,
memory_types);
break;
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
get_av1_video_session_mem_reqs(vid,
mem_reqs,
pVideoSessionMemoryRequirementsCount,
memory_types);
break;
default:
unreachable("unknown codec");
}
@@ -559,6 +782,7 @@ anv_BindVideoSessionMemoryKHR(VkDevice _device,
switch (vid->vk.op) {
case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR:
case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR:
case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR:
for (unsigned i = 0; i < bind_mem_count; i++) {
copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]);
}
@@ -660,3 +884,115 @@ anv_GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR(VkPhysicalDevice physi
/* TODO. */
return VK_SUCCESS;
}
static void
init_single_av1_entry(const struct syntax_element_cdf_table_layout *entry, uint16_t *dst_ptr)
{
uint16_t entry_count_per_cl = entry->entry_count_per_cl;
uint16_t entry_count_total = entry->entry_count_total;
uint16_t start_cl = entry->start_cl;
const uint16_t *src = entry->init_data;
uint16_t *dst = dst_ptr + start_cl * 32;
uint16_t entry_count_left = entry_count_total;
while (entry_count_left >= entry_count_per_cl) {
memcpy(dst, src, entry_count_per_cl * sizeof(uint16_t));
entry_count_left -= entry_count_per_cl;
src += entry_count_per_cl;
dst += 32;
}
if (entry_count_left > 0)
memcpy(dst, src, entry_count_left * sizeof(uint16_t));
}
#define INIT_TABLE(x) do {\
for (unsigned i = 0; i < ARRAY_SIZE((x)); i++) \
init_single_av1_entry(&(x)[i], dst_ptr); \
} while (0)
static void
init_all_av1_entry(uint16_t *dst_ptr, int index)
{
INIT_TABLE(av1_cdf_intra_part1);
switch (index) {
case 0:
INIT_TABLE(av1_cdf_intra_coeffs_0);
break;
case 1:
INIT_TABLE(av1_cdf_intra_coeffs_1);
break;
case 2:
INIT_TABLE(av1_cdf_intra_coeffs_2);
break;
case 3:
INIT_TABLE(av1_cdf_intra_coeffs_3);
break;
default:
unreachable("illegal av1 entry\n");
}
INIT_TABLE(av1_cdf_intra_part2);
INIT_TABLE(av1_cdf_inter);
}
void
anv_init_av1_cdf_tables(struct anv_cmd_buffer *cmd,
struct anv_video_session *vid)
{
void *ptr;
for (unsigned i = 0; i < 4; i++) {
VkResult result =
anv_device_map_bo(cmd->device,
vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo,
vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].offset,
vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size,
NULL,
&ptr);
if (result != VK_SUCCESS) {
anv_batch_set_error(&cmd->batch, result);
return;
}
init_all_av1_entry(ptr, i);
anv_device_unmap_bo(cmd->device, vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].mem->bo, ptr,
vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + i].size, NULL);
}
}
uint32_t
anv_video_get_image_mv_size(struct anv_device *device,
struct anv_image *image,
const struct VkVideoProfileListInfoKHR *profile_list)
{
uint32_t size = 0;
for (unsigned i = 0; i < profile_list->profileCount; i++) {
if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) {
unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, ANV_MB_WIDTH);
unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, ANV_MB_HEIGHT);
size = w_mb * h_mb * 128;
} else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) {
unsigned w_mb = DIV_ROUND_UP(image->vk.extent.width, 32);
unsigned h_mb = DIV_ROUND_UP(image->vk.extent.height, 32);
size = ALIGN(w_mb * h_mb, 2) << 6;
} else if (profile_list->pProfiles[i].videoCodecOperation == VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) {
const uint32_t av1_mi_size_log2 = 2;
uint32_t width = image->vk.extent.width;
uint32_t height = image->vk.extent.height;
uint32_t mi_cols = width >> av1_mi_size_log2;
uint32_t mi_rows = height >> av1_mi_size_log2;
uint32_t width_in_sb = align(mi_cols, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
uint32_t height_in_sb = align(mi_rows, (1 << av1_mi_size_log2)) >> av1_mi_size_log2;
uint32_t sb_total = width_in_sb * height_in_sb;
size = sb_total * 16;
}
}
return size;
}

File diff suppressed because it is too large Load Diff