diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c index e9710240a82..231d1e83574 100644 --- a/src/intel/vulkan/anv_image.c +++ b/src/intel/vulkan/anv_image.c @@ -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; } diff --git a/src/intel/vulkan/anv_physical_device.c b/src/intel/vulkan/anv_physical_device.c index 03bcde7f246..a91ea236a2d 100644 --- a/src/intel/vulkan/anv_physical_device.c +++ b/src/intel/vulkan/anv_physical_device.c @@ -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) { diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index f3bd6c5c4e9..ef0e8de73cf 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -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); diff --git a/src/intel/vulkan/anv_video.c b/src/intel/vulkan/anv_video.c index d23fba71260..4bb2e32a1de 100644 --- a/src/intel/vulkan/anv_video.c +++ b/src/intel/vulkan/anv_video.c @@ -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; +} diff --git a/src/intel/vulkan/genX_cmd_video.c b/src/intel/vulkan/genX_cmd_video.c index d4cd5444ae8..1a02c2c49a7 100644 --- a/src/intel/vulkan/genX_cmd_video.c +++ b/src/intel/vulkan/genX_cmd_video.c @@ -38,6 +38,14 @@ genX(CmdBeginVideoCodingKHR)(VkCommandBuffer commandBuffer, cmd_buffer->video.vid = vid; cmd_buffer->video.params = params; + + if (vid->vk.op != VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR) + return; + + if (!vid->cdf_initialized) { + anv_init_av1_cdf_tables(cmd_buffer, vid); + vid->cdf_initialized = true; + } } void @@ -1210,6 +1218,1154 @@ anv_h264_decode_video(struct anv_cmd_buffer *cmd_buffer, } } +#if GFX_VERx10 >= 120 + +enum av1_seg_index +{ + SEG_LVL_ALT_Q = 0, /* Use alternate Quantizer */ + SEG_LVL_ALT_LFYV, /* Use alternate loop filter value on y plane vertical */ + SEG_LVL_ALT_LFYH, /* Use alternate loop filter value on y plane horizontal */ + SEG_LVL_ALT_LFU, /* Use alternate loop filter value on u plane */ + SEG_LVL_ALT_LFV, /* Use alternate loop filter value on v plane */ + SEG_LVL_REF_FRAME, /* Optional Segment reference frame */ + SEG_LVL_SKIP, /* Optional Segment (0,0) + skip mode */ + SEG_LVL_GLOBAL_MV, /* Global MV */ +}; + +enum av1_ref_frame +{ + AV1_NONE_FRAME = -1, /* none frame */ + AV1_INTRA_FRAME = 0, /* intra frame, which means the current frame */ + AV1_LAST_FRAME = 1, /* last frame */ + AV1_LAST2_FRAME = 2, /* last2 frame */ + AV1_LAST3_FRAME = 3, /* last3 frame */ + AV1_GOLDEN_FRAME = 4, /* golden frame */ + AV1_BWDREF_FRAME = 5, /* bwdref frame */ + AV1_ALTREF2_FRAME = 6, /* altref2 frame */ + AV1_ALTREF_FRAME = 7, /* altref frame */ + AV1_TOTAL_REFS_PER_FRAME = 8, /* total reference frame number */ + AV1_NUM_INTER_REFS = AV1_ALTREF_FRAME - AV1_LAST_FRAME + 1 /* total number of inter ref frames */ +}; + +enum av1_gm_type +{ + AV1_IDENTITY = 0, + AV1_TRANSLATION, + AV1_ROTZOOM, + AV1_AFFINE, +}; + +static const uint32_t btdl_cache_offset = 0; +static const uint32_t smvl_cache_offset = 128; +static const uint32_t ipdl_cache_offset = 384; +static const uint32_t dfly_cache_offset = 640; +static const uint32_t dflu_cache_offset = 1344; +static const uint32_t dflv_cache_offset = 1536; +static const uint32_t cdef_cache_offset = 1728; + +static const uint32_t av1_max_qindex = 255; +static const uint32_t av1_num_qm_levels = 16; +static const uint32_t av1_scaling_factor = (1 << 14); + +static uint32_t +get_qindex(const VkVideoDecodeAV1PictureInfoKHR *av1_pic_info, + uint32_t segment_id) +{ + const StdVideoDecodeAV1PictureInfo *std_pic_info = av1_pic_info->pStdPictureInfo; + uint8_t base_qindex = std_pic_info->pQuantization->base_q_idx; + uint32_t feature_mask = std_pic_info->pSegmentation->FeatureEnabled[segment_id]; + if (std_pic_info->flags.segmentation_enabled && + feature_mask & (1 << SEG_LVL_ALT_Q)) { + int data = std_pic_info->pSegmentation->FeatureData[segment_id][SEG_LVL_ALT_Q]; + return CLAMP(base_qindex + data, 0, av1_max_qindex); + } else + return base_qindex; +} + +static bool +frame_is_key_or_intra(const StdVideoAV1FrameType frame_type) +{ + return (frame_type == STD_VIDEO_AV1_FRAME_TYPE_INTRA_ONLY || + frame_type == STD_VIDEO_AV1_FRAME_TYPE_KEY); +} + +static int32_t +get_relative_dist(const VkVideoDecodeAV1PictureInfoKHR *av1_pic_info, + const struct anv_video_session_params *params, + int32_t a, int32_t b) +{ + if (!params->vk.av1_dec.seq_hdr.base.flags.enable_order_hint) + return 0; + + int32_t bits = params->vk.av1_dec.seq_hdr.base.order_hint_bits_minus_1 + 1; + int32_t diff = a - b; + int32_t m = 1 << (bits - 1); + diff = (diff & (m - 1)) - (diff & m); + + return diff; +} + +static void +anv_av1_decode_video_tile(struct anv_cmd_buffer *cmd_buffer, + const VkVideoDecodeInfoKHR *frame_info, + int tile_idx) +{ + ANV_FROM_HANDLE(anv_buffer, src_buffer, frame_info->srcBuffer); + struct anv_video_session *vid = cmd_buffer->video.vid; + struct anv_video_session_params *params = cmd_buffer->video.params; + const struct VkVideoDecodeAV1PictureInfoKHR *av1_pic_info = + vk_find_struct_const(frame_info->pNext, VIDEO_DECODE_AV1_PICTURE_INFO_KHR); + const StdVideoDecodeAV1PictureInfo *std_pic_info = av1_pic_info->pStdPictureInfo; + const StdVideoAV1SequenceHeader *seq_hdr = ¶ms->vk.av1_dec.seq_hdr.base; + int cdf_index = 0; + if (std_pic_info->pQuantization->base_q_idx <= 20) + cdf_index = 0; + else if (std_pic_info->pQuantization->base_q_idx <= 60) + cdf_index = 1; + else if (std_pic_info->pQuantization->base_q_idx <= 120) + cdf_index = 2; + else + cdf_index = 3; + + anv_batch_emit(&cmd_buffer->batch, GENX(MI_FORCE_WAKEUP), wake) { + wake.HEVCPowerWellControl = true; + wake.MaskBits = 768; + } + anv_batch_emit(&cmd_buffer->batch, GENX(MI_FORCE_WAKEUP), wake) { + wake.HEVCPowerWellControl = true; + wake.MaskBits = 768; + } + + anv_batch_emit(&cmd_buffer->batch, GENX(MI_FLUSH_DW), flush) { + flush.DWordLength = 2; + flush.VideoPipelineCacheInvalidate = 1; + }; + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_VD_CONTROL_STATE), vd) { + vd.VDControlState.PipelineInitialization = 1; + } + + anv_batch_emit(&cmd_buffer->batch, GENX(MFX_WAIT), mfx) { + mfx.MFXSyncControlFlag = 1; + } + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_PIPE_MODE_SELECT), sel) { + sel.CodecSelect = Decode; + sel.MultiEngineMode = SingleEngineMode; + }; + + anv_batch_emit(&cmd_buffer->batch, GENX(MFX_WAIT), mfx) { + mfx.MFXSyncControlFlag = 1; + } + + struct refs_info { + const struct anv_image *img; + uint8_t order_hint; + uint8_t ref_order_hints[STD_VIDEO_AV1_NUM_REF_FRAMES]; + uint8_t disable_frame_end_update_cdf; + uint8_t idx; + uint8_t frame_type; + } ref_info[STD_VIDEO_AV1_NUM_REF_FRAMES] = {}; + + const struct anv_image_view *dst_iv = + anv_image_view_from_handle(frame_info->dstPictureResource.imageViewBinding); + const struct anv_image *dst_img = dst_iv->image; + const struct anv_image_view *dpb_iv = frame_info->pSetupReferenceSlot ? + anv_image_view_from_handle(frame_info->pSetupReferenceSlot->pPictureResource->imageViewBinding) : + dst_iv; + const struct anv_image *dpb_img = dpb_iv->image; + const bool is_10bit = seq_hdr->pColorConfig->BitDepth == 10; + + ref_info[AV1_INTRA_FRAME].img = dpb_img; + + if (dpb_img && frame_info->referenceSlotCount) { + ref_info[AV1_INTRA_FRAME].order_hint = std_pic_info->OrderHint; + ref_info[AV1_INTRA_FRAME].disable_frame_end_update_cdf = + std_pic_info->flags.disable_frame_end_update_cdf; + } + + for (int i = 0; i < STD_VIDEO_AV1_REFS_PER_FRAME; ++i) { + uint8_t ref_idx = av1_pic_info->referenceNameSlotIndices[i]; + + for (unsigned j = 0; j < frame_info->referenceSlotCount; j++) { + int idx = frame_info->pReferenceSlots[j].slotIndex; + + if (ref_idx == idx) { + const struct anv_image_view *ref_iv = + anv_image_view_from_handle(frame_info->pReferenceSlots[j].pPictureResource->imageViewBinding); + const struct anv_image *ref_img = ref_iv->image; + const struct VkVideoDecodeAV1DpbSlotInfoKHR *dpb_slot = + vk_find_struct_const(frame_info->pReferenceSlots[j].pNext, VIDEO_DECODE_AV1_DPB_SLOT_INFO_KHR); + const struct StdVideoDecodeAV1ReferenceInfo *std_ref_info = dpb_slot->pStdReferenceInfo; + + ref_info[i + 1].idx = idx; + ref_info[i + 1].frame_type = std_ref_info->frame_type; + ref_info[i + 1].img = ref_img; + ref_info[i + 1].order_hint = std_ref_info->OrderHint; + memcpy(ref_info[i + 1].ref_order_hints, std_ref_info->SavedOrderHints, STD_VIDEO_AV1_NUM_REF_FRAMES); + ref_info[i + 1].disable_frame_end_update_cdf = std_ref_info->flags.disable_frame_end_update_cdf; + } + } + } + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_SURFACE_STATE), ss) { + ss.SurfaceFormat = is_10bit ? AVP_P010 : AVP_PLANAR_420_8; + ss.SurfacePitchMinus1 = dst_img->planes[0].primary_surface.isl.row_pitch_B - 1; + ss.YOffsetforUCb = dst_img->planes[1].primary_surface.memory_range.offset / + dst_img->planes[0].primary_surface.isl.row_pitch_B; + }; + + if (!frame_is_key_or_intra(std_pic_info->frame_type)) { + for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) { + if (ref_info[r].img && frame_info->referenceSlotCount) { + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_SURFACE_STATE), ss) { + ss.SurfaceID = 0x6 + r; + ss.SurfaceFormat = is_10bit ? AVP_P010 : AVP_PLANAR_420_8; + ss.SurfacePitchMinus1 = ref_info[r].img->planes[0].primary_surface.isl.row_pitch_B - 1; + ss.YOffsetforUCb = ref_info[r].img->planes[1].primary_surface.memory_range.offset / + ref_info[r].img->planes[0].primary_surface.isl.row_pitch_B; + } + } + } + } + + if (std_pic_info->flags.allow_intrabc) { + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_SURFACE_STATE), ss) { + ss.SurfaceID = 0xE; + ss.SurfaceFormat = is_10bit ? AVP_P010 : AVP_PLANAR_420_8; + ss.SurfacePitchMinus1 = dst_img->planes[0].primary_surface.isl.row_pitch_B - 1; + ss.YOffsetforUCb = dst_img->planes[1].primary_surface.memory_range.offset / + dst_img->planes[0].primary_surface.isl.row_pitch_B; + } + } + + bool use_internal_cache_mem = true; + +#if GFX_VERx10 == 125 + assert(dst_img->planes[0].primary_surface.isl.tiling == ISL_TILING_4); +#endif + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_PIPE_BUF_ADDR_STATE), buf) { + buf.DecodedOutputFrameBufferAddress = anv_image_address(dst_img, + &dst_img->planes[0].primary_surface.memory_range); + buf.DecodedOutputFrameBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, buf.DecodedOutputFrameBufferAddress.bo, 0), +#if GFX_VERx10 >= 125 + .TiledResourceMode = TRMODE_TILEF, +#endif + }; + buf.CurrentFrameMVWriteBufferAddress = anv_image_address(dpb_img, + &dpb_img->vid_dmv_top_surface); + buf.CurrentFrameMVWriteBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, buf.CurrentFrameMVWriteBufferAddress.bo, 0), + }; + + if (std_pic_info->flags.allow_intrabc) { + buf.IntraBCDecodedOutputFrameBufferAddress = + anv_image_address(dst_img, &dst_img->planes[0].primary_surface.memory_range); + } + + buf.IntraBCDecodedOutputFrameBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, buf.IntraBCDecodedOutputFrameBufferAddress.bo, 0), + }; + + if (use_internal_cache_mem) { + buf.BitstreamLineRowstoreBufferAddress = (struct anv_address) { + NULL, + btdl_cache_offset * 64 + }; + + buf.BitstreamLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1, + }; + } else { + buf.BitstreamLineRowstoreBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE].offset + }; + buf.BitstreamLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_LINE_ROWSTORE].mem->bo, 0), + }; + } + + buf.BitstreamTileLineRowstoreBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE].offset + }; + + buf.BitstreamTileLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_BITSTREAM_TILE_LINE_ROWSTORE].mem->bo, 0), + }; + + if (use_internal_cache_mem) { + buf.IntraPredictionLineRowstoreBufferAddress = (struct anv_address) { + NULL, + ipdl_cache_offset * 64 + }; + buf.IntraPredictionLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1 + }; + } else { + buf.IntraPredictionLineRowstoreBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE].offset + }; + buf.IntraPredictionLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_LINE_ROWSTORE].mem->bo, 0), + }; + } + buf.IntraPredictionTileLineRowstoreBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE].offset + }; + + buf.IntraPredictionTileLineRowstoreBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_INTRA_PREDICTION_TILE_LINE_ROWSTORE].mem->bo, 0), + }; + + if (use_internal_cache_mem) { + buf.SpatialMotionVectorLineBufferAddress = (struct anv_address) { + NULL, + smvl_cache_offset * 64 + }; + buf.SpatialMotionVectorLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1 + }; + } else { + buf.SpatialMotionVectorLineBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE].offset + }; + buf.SpatialMotionVectorLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_LINE].mem->bo, 0), + }; + } + + buf.SpatialMotionVectorTileLineBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE].offset + }; + + buf.SpatialMotionVectorTileLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_SPATIAL_MOTION_VECTOR_TILE_LINE].mem->bo, 0), + }; + + buf.LoopRestorationMetaTileColumnBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN].offset + }; + buf.LoopRestorationMetaTileColumnBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_META_TILE_COLUMN].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileLineYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y].offset + }; + buf.LoopRestorationFilterTileLineYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_Y].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileLineUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U].offset + }; + + buf.LoopRestorationFilterTileLineUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_U].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileLineVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V].offset + }; + + buf.LoopRestorationFilterTileLineVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_LINE_V].mem->bo, 0), + }; + + if (use_internal_cache_mem) { + buf.DeblockerFilterLineYBufferAddress = (struct anv_address) { + NULL, + dfly_cache_offset * 64 + }; + buf.DeblockerFilterLineYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1, + }; + } else { + buf.DeblockerFilterLineYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y].offset + }; + buf.DeblockerFilterLineYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_Y].mem->bo, 0), + }; + } + + if (use_internal_cache_mem) { + buf.DeblockerFilterLineUBufferAddress = (struct anv_address) { + NULL, + dflu_cache_offset * 64 + }; + buf.DeblockerFilterLineUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1, + }; + } else { + buf.DeblockerFilterLineUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U].offset + }; + buf.DeblockerFilterLineUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_U].mem->bo, 0), + }; + } + if (use_internal_cache_mem) { + buf.DeblockerFilterLineVBufferAddress = (struct anv_address) { + NULL, + dflv_cache_offset * 64 + }; + buf.DeblockerFilterLineVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1, + }; + } else { + buf.DeblockerFilterLineVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V].offset + }; + buf.DeblockerFilterLineVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_LINE_V].mem->bo, 0), + }; + } + + buf.DeblockerFilterTileLineYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y].offset + }; + buf.DeblockerFilterTileLineYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_Y].mem->bo, 0), + }; + + buf.DeblockerFilterTileLineUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U].offset + }; + + buf.DeblockerFilterTileLineUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_U].mem->bo, 0), + }; + + buf.DeblockerFilterTileLineVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V].offset + }; + buf.DeblockerFilterTileLineVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_LINE_V].mem->bo, 0), + }; + + buf.DeblockerFilterTileColumnYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y].offset + }; + + buf.DeblockerFilterTileColumnYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_Y].mem->bo, 0), + }; + + buf.DeblockerFilterTileColumnUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U].offset + }; + + buf.DeblockerFilterTileColumnUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_U].mem->bo, 0), + }; + buf.DeblockerFilterTileColumnVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V].offset + }; + buf.DeblockerFilterTileColumnVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DEBLOCKER_FILTER_TILE_COLUMN_V].mem->bo, 0), + }; + + if (use_internal_cache_mem) { + buf.CDEFFilterLineBufferAddress = (struct anv_address) { NULL, cdef_cache_offset * 64}; + buf.CDEFFilterLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + .RowStoreScratchBufferCacheSelect = 1, + }; + } else { + buf.CDEFFilterLineBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_LINE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_LINE].offset + }; + buf.CDEFFilterLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_LINE].mem->bo, 0), + }; + } + + buf.CDEFFilterTileLineBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE].offset + }; + buf.CDEFFilterTileLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_LINE].mem->bo, 0), + }; + + buf.CDEFFilterTileColumnBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN].offset + }; + buf.CDEFFilterTileColumnBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TILE_COLUMN].mem->bo, 0), + }; + + buf.CDEFFilterMetaTileLineBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE].offset + }; + buf.CDEFFilterMetaTileLineBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_LINE].mem->bo, 0), + }; + + buf.CDEFFilterMetaTileColumnBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN].offset + }; + + buf.CDEFFilterMetaTileColumnBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_META_TILE_COLUMN].mem->bo, 0), + }; + + buf.CDEFFilterTopLeftCornerBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER].offset + }; + buf.CDEFFilterTopLeftCornerBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_CDEF_FILTER_TOP_LEFT_CORNER].mem->bo, 0), + }; + + buf.SuperResTileColumnYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y].offset + }; + buf.SuperResTileColumnYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_Y].mem->bo, 0), + }; + + buf.SuperResTileColumnUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U].offset + }; + buf.SuperResTileColumnUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_U].mem->bo, 0), + }; + + buf.SuperResTileColumnVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V].offset + }; + buf.SuperResTileColumnVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_SUPER_RES_TILE_COLUMN_V].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileColumnYBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y].offset + }; + + buf.LoopRestorationFilterTileColumnYBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_Y].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileColumnUBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U].offset + }; + + buf.LoopRestorationFilterTileColumnUBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_U].mem->bo, 0), + }; + + buf.LoopRestorationFilterTileColumnVBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V].offset + }; + buf.LoopRestorationFilterTileColumnVBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_LOOP_RESTORATION_FILTER_TILE_COLUMN_V].mem->bo, 0), + }; + + struct anv_bo *ref_bo = NULL; + struct anv_bo *collocated_bo = NULL; + + if (std_pic_info->frame_type != STD_VIDEO_AV1_FRAME_TYPE_KEY) { + for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) { + const struct anv_image *ref_img = ref_info[r].img; + if (ref_img) { + + buf.ReferencePictureAddress[r] = + anv_image_address(ref_img, &ref_img->planes[0].primary_surface.memory_range); + buf.CollocatedMVTemporalBufferAddress[r] = + anv_image_address(ref_img, &ref_img->vid_dmv_top_surface); + + if (!ref_bo) + ref_bo = ref_img->bindings[0].address.bo; + if (!collocated_bo) + collocated_bo = ref_img->bindings[ref_img->vid_dmv_top_surface.binding].address.bo; + + } + } + } + + buf.ReferencePictureAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, ref_bo, 0), +#if GFX_VERx10 >= 125 + .TiledResourceMode = TRMODE_TILEF, +#endif + }; + buf.CollocatedMVTemporalBufferAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, collocated_bo, 0), + }; + + bool use_default_cdf = false; + + if (std_pic_info->primary_ref_frame == 7) { + use_default_cdf = true; + } else { + if (ref_info[std_pic_info->primary_ref_frame + 1].disable_frame_end_update_cdf) + use_default_cdf = true; + } + + if (use_default_cdf) { + buf.CDFTablesInitializationBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + cdf_index].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_CDF_DEFAULTS_0 + cdf_index].offset }; + } else { + const struct anv_image *ref_img = ref_info[std_pic_info->primary_ref_frame + 1].img; + buf.CDFTablesInitializationBufferAddress = anv_image_address(ref_img, + &ref_img->av1_cdf_table); + } + buf.CDFTablesInitializationBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, buf.CDFTablesInitializationBufferAddress.bo, 0), + }; + + if (!std_pic_info->flags.disable_frame_end_update_cdf) { + const struct anv_image *ref_img = ref_info[0].img; + buf.CDFTablesBackwardAdaptationBufferAddress = anv_image_address(ref_img, + &ref_img->av1_cdf_table); + } + + buf.CDFTablesBackwardAdaptationBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, buf.CDFTablesBackwardAdaptationBufferAddress.bo, 0), + }; + buf.AV1SegmentIDReadBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + }; + buf.AV1SegmentIDWriteBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + }; + buf.DecodedFrameStatusErrorBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + }; + + buf.DecodedBlockDataStreamoutBufferAddress = (struct anv_address) { + vid->vid_mem[ANV_VID_MEM_AV1_DBD_BUFFER].mem->bo, + vid->vid_mem[ANV_VID_MEM_AV1_DBD_BUFFER].offset + }; + buf.DecodedBlockDataStreamoutBufferAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, vid->vid_mem[ANV_VID_MEM_AV1_DBD_BUFFER].mem->bo, 0), + }; + }; + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_IND_OBJ_BASE_ADDR_STATE), ind) { + ind.AVPIndirectBitstreamObjectBaseAddress = anv_address_add(src_buffer->address, + frame_info->srcBufferOffset & ~4095); + ind.AVPIndirectBitstreamObjectAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, src_buffer->address.bo, 0), + }; +#if GFX_VERx10 >= 125 + /* FIXME. + ind.AVPIndirectCUObjectAddressAttributes = (struct GENX(MEMORYADDRESSATTRIBUTES)) { + .MOCS = anv_mocs(cmd_buffer->device, NULL, 0), + }; + */ +#endif + } + + uint32_t frame_restoration_type[3]; + for (unsigned i = 0; i < 3; i++) { + frame_restoration_type[i] = std_pic_info->pLoopRestoration ? + std_pic_info->pLoopRestoration->FrameRestorationType[i] : 0; + } + + uint32_t ref_mask = 0; + uint32_t ref_frame_sign_bias = 0; + uint32_t ref_frame_side = 0; + for (enum av1_ref_frame r = AV1_LAST_FRAME; r <= AV1_ALTREF_FRAME; r++) { + if (seq_hdr->flags.enable_order_hint && + !frame_is_key_or_intra(std_pic_info->frame_type)) { + if (get_relative_dist(av1_pic_info, params, + ref_info[r].order_hint, ref_info[AV1_INTRA_FRAME].order_hint) > 0) + ref_frame_sign_bias |= (1 << r); + + if ((get_relative_dist(av1_pic_info, params, + ref_info[r].order_hint, ref_info[AV1_INTRA_FRAME].order_hint) > 0) || + ref_info[r].order_hint == ref_info[AV1_INTRA_FRAME].order_hint) + ref_frame_side |= (1 << r); + } + } + + uint8_t num_mfmv = 0; + uint8_t mfmv_ref[7] = { 0, }; + if (!frame_is_key_or_intra(std_pic_info->frame_type) && + std_pic_info->flags.use_ref_frame_mvs && + seq_hdr->order_hint_bits_minus_1 + 1) { + + assert (seq_hdr->flags.enable_order_hint); + + int total = 2; + + if (ref_info[AV1_LAST_FRAME].ref_order_hints[AV1_ALTREF_FRAME - AV1_LAST_FRAME + 1] != + ref_info[AV1_GOLDEN_FRAME].order_hint) { + + if (!frame_is_key_or_intra(ref_info[0 + 1].frame_type)) { + total = 3; + mfmv_ref[num_mfmv++] = AV1_LAST_FRAME - AV1_LAST_FRAME; + } + } + + if (get_relative_dist(av1_pic_info, params, + ref_info[AV1_BWDREF_FRAME].order_hint, + ref_info[AV1_INTRA_FRAME].order_hint) > 0 && + !frame_is_key_or_intra(ref_info[AV1_BWDREF_FRAME - AV1_LAST_FRAME + 1].frame_type)) { + mfmv_ref[num_mfmv++] = AV1_BWDREF_FRAME - AV1_LAST_FRAME; + } + + if (get_relative_dist(av1_pic_info, params, + ref_info[AV1_ALTREF2_FRAME].order_hint, + ref_info[AV1_INTRA_FRAME].order_hint) > 0 && + !frame_is_key_or_intra(ref_info[AV1_ALTREF2_FRAME - AV1_LAST_FRAME + 1].frame_type)) { + mfmv_ref[num_mfmv++] = AV1_ALTREF2_FRAME - AV1_LAST_FRAME; + } + + if (num_mfmv < total && + get_relative_dist(av1_pic_info, params, + ref_info[AV1_ALTREF_FRAME].order_hint, + ref_info[AV1_INTRA_FRAME].order_hint) > 0 && + !frame_is_key_or_intra(ref_info[AV1_ALTREF_FRAME - AV1_LAST_FRAME + 1].frame_type)) { + mfmv_ref[num_mfmv++] = AV1_ALTREF_FRAME - AV1_LAST_FRAME; + } + + if (num_mfmv < total && + !frame_is_key_or_intra(ref_info[AV1_LAST2_FRAME - AV1_LAST_FRAME + 1].frame_type)) { + mfmv_ref[num_mfmv++] = AV1_LAST2_FRAME - AV1_LAST_FRAME; + } + } + + assert(num_mfmv <= 7); + + for (unsigned int i = 0; i < num_mfmv; i++) { + ref_mask |= (1 << mfmv_ref[i]); + } + + uint8_t preskip_segid = 0; + uint8_t last_active_segid = 0; + bool frame_lossless = true; + bool lossless[8] = { false }; + + for (unsigned i = 0; i < 8; i++) { + for (unsigned j = 0; j < 8; j++) { + if (std_pic_info->pSegmentation->FeatureEnabled[i] & (1 << j)) { + last_active_segid = i; + if (j >= 5) + preskip_segid = 1; + } + } + uint32_t qindex = get_qindex(av1_pic_info, i); + lossless[i] = (qindex == 0) && + (std_pic_info->pQuantization->DeltaQYDc == 0) && + (std_pic_info->pQuantization->DeltaQUAc == 0) && + (std_pic_info->pQuantization->DeltaQUDc == 0) && + (std_pic_info->pQuantization->DeltaQVAc == 0) && + (std_pic_info->pQuantization->DeltaQVDc == 0); + frame_lossless &= lossless[i]; + } + + VkExtent2D frameExtent = frame_info->dstPictureResource.codedExtent; + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_PIC_STATE), pic) { + pic.FrameWidth = frameExtent.width - 1; + pic.FrameHeight = frameExtent.height - 1; + + if (seq_hdr->pColorConfig->BitDepth == 12) + pic.SequencePixelBitDepthIdc = SeqPix_12bit; + else if (seq_hdr->pColorConfig->BitDepth == 10) + pic.SequencePixelBitDepthIdc = SeqPix_10bit; + else + pic.SequencePixelBitDepthIdc = SeqPix_8bit; + if (seq_hdr->pColorConfig->subsampling_x == 1 && + seq_hdr->pColorConfig->subsampling_y == 1) { + if (seq_hdr->pColorConfig->flags.mono_chrome) + pic.SequenceChromaSubSamplingFormat = SS_Monochrome; + else + pic.SequenceChromaSubSamplingFormat = SS_420; + } else if (seq_hdr->pColorConfig->subsampling_x == 1 && + seq_hdr->pColorConfig->subsampling_y == 0) { + pic.SequenceChromaSubSamplingFormat = SS_422; + } else if (seq_hdr->pColorConfig->subsampling_x == 0 && + seq_hdr->pColorConfig->subsampling_y == 0) { + pic.SequenceChromaSubSamplingFormat = SS_444; + } + + pic.SequenceSuperblockSizeUsed = seq_hdr->flags.use_128x128_superblock; + pic.SequenceEnableOrderHintFlag = seq_hdr->flags.enable_order_hint; + pic.SequenceOrderHintBitsMinus1 = seq_hdr->flags.enable_order_hint ? seq_hdr->order_hint_bits_minus_1 : 0; + pic.SequenceEnableFilterIntraFlag = seq_hdr->flags.enable_filter_intra; + pic.SequenceEnableIntraEdgeFilterFlag = seq_hdr->flags.enable_intra_edge_filter; + pic.SequenceEnableDualFilterFlag = seq_hdr->flags.enable_dual_filter; + pic.SequenceEnableInterIntraCompoundFlag = seq_hdr->flags.enable_interintra_compound; + pic.SequenceEnableMaskedCompoundFlag = seq_hdr->flags.enable_masked_compound; + pic.SequenceEnableJointCompoundFlag = seq_hdr->flags.enable_jnt_comp; + pic.AllowScreenContentToolsFlag = std_pic_info->flags.allow_screen_content_tools; + pic.ForceIntegerMVFlag = std_pic_info->flags.force_integer_mv; + pic.AllowWarpedMotionFlag = std_pic_info->flags.allow_warped_motion; + pic.UseCDEFFilterFlag = seq_hdr->flags.enable_cdef; + pic.UseSuperResFlag = std_pic_info->flags.use_superres; + pic.FrameLevelLoopRestorationFilterEnable = frame_restoration_type[0] || frame_restoration_type[1] || frame_restoration_type[2]; + pic.FrameType = std_pic_info->frame_type; + pic.IntraOnlyFlag = frame_is_key_or_intra(std_pic_info->frame_type); + pic.ErrorResilientModeFlag = std_pic_info->flags.error_resilient_mode; + pic.AllowIntraBCFlag = std_pic_info->flags.allow_intrabc; + pic.PrimaryReferenceFrameIdx = std_pic_info->primary_ref_frame; + pic.SegmentationEnableFlag = std_pic_info->flags.segmentation_enabled; + pic.SegmentationUpdateMapFlag = std_pic_info->flags.segmentation_update_map; + pic.SegmentationTemporalUpdateFlag = pic.IntraOnlyFlag ? 0 : std_pic_info->flags.segmentation_temporal_update; + pic.PreSkipSegmentIDFlag = preskip_segid; + pic.LastActiveSegmentSegmentID = last_active_segid; + pic.DeltaQPresentFlag = std_pic_info->flags.delta_q_present; + pic.DeltaQRes = std_pic_info->delta_q_res; + pic.FrameCodedLosslessMode = frame_lossless; /* TODO */ + pic.SegmentMapisZeroFlag = 0; /* TODO */ + pic.SegmentIDBufferStreamInEnableFlag = 0; /* TODO */ + pic.SegmentIDBufferStreamOutEnableFlag = 0; /* TODO */ + pic.BaseQindex = std_pic_info->pQuantization->base_q_idx; + pic.YdcdeltaQ = std_pic_info->pQuantization->DeltaQYDc; + pic.UdcdeltaQ = std_pic_info->pQuantization->DeltaQUDc; + pic.UacdeltaQ = std_pic_info->pQuantization->DeltaQUAc; + pic.VdcdeltaQ = std_pic_info->pQuantization->DeltaQVDc; + pic.VacdeltaQ = std_pic_info->pQuantization->DeltaQVAc; + pic.AllowHighPrecisionMV = std_pic_info->flags.allow_high_precision_mv; + pic.FrameLevelReferenceModeSelect = !(std_pic_info->flags.reference_select == 0); + pic.McompFilterType = std_pic_info->interpolation_filter; + pic.MotionModeSwitchableFlag = std_pic_info->flags.is_motion_mode_switchable; + pic.UseReferenceFrameMVSetFlag = std_pic_info->flags.use_ref_frame_mvs; + pic.ReferenceFrameSignBias = ref_frame_sign_bias; + pic.CurrentFrameOrderHint = std_pic_info->OrderHint; + pic.ReducedTxSetUsed = std_pic_info->flags.reduced_tx_set; + pic.FrameTransformMode = std_pic_info->TxMode; + pic.SkipModePresentFlag = std_pic_info->flags.skip_mode_present; + pic.SkipModeFrame0 = std_pic_info->SkipModeFrame[0]; + pic.SkipModeFrame1 = std_pic_info->SkipModeFrame[1]; + pic.ReferenceFrameSide = ref_frame_side; + pic.GlobalMotionType1 = std_pic_info->pGlobalMotion->GmType[1]; + pic.GlobalMotionType2 = std_pic_info->pGlobalMotion->GmType[2]; + pic.GlobalMotionType3 = std_pic_info->pGlobalMotion->GmType[3]; + pic.GlobalMotionType4 = std_pic_info->pGlobalMotion->GmType[4]; + pic.GlobalMotionType5 = std_pic_info->pGlobalMotion->GmType[5]; + pic.GlobalMotionType6 = std_pic_info->pGlobalMotion->GmType[6]; + pic.GlobalMotionType7 = std_pic_info->pGlobalMotion->GmType[7]; + pic.FrameLevelGlobalMotionInvalidFlags = 0; + + uint8_t idx = 0; + + for (enum av1_ref_frame r = AV1_LAST_FRAME; r <= AV1_ALTREF_FRAME; r++) { + for (uint32_t i = 0; i < STD_VIDEO_AV1_GLOBAL_MOTION_PARAMS; i++) + pic.WarpParameters[idx++] = std_pic_info->pGlobalMotion->gm_params[r][i] & 0xffff; + } + + pic.ReferenceFrameIdx1 = AV1_LAST_FRAME; + pic.ReferenceFrameIdx2 = AV1_LAST2_FRAME; + pic.ReferenceFrameIdx3 = AV1_LAST3_FRAME; + pic.ReferenceFrameIdx4 = AV1_GOLDEN_FRAME; + pic.ReferenceFrameIdx5 = AV1_BWDREF_FRAME; + pic.ReferenceFrameIdx6 = AV1_ALTREF2_FRAME; + pic.ReferenceFrameIdx7 = AV1_ALTREF_FRAME; + + if (!frame_is_key_or_intra(std_pic_info->frame_type)) { + for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) { + const struct anv_image *ref_img = ref_info[r].img; + + if (!ref_img) + continue; + + int ref_width = ref_img->vk.extent.width - 1; + int ref_height = ref_img->vk.extent.height - 1; + + uint32_t h_scale_factor = + (ref_img->vk.extent.width * av1_scaling_factor + (frameExtent.width >> 1)) / + frameExtent.width; + uint32_t v_scale_factor = + (ref_img->vk.extent.height * av1_scaling_factor + (frameExtent.height >> 1)) / + frameExtent.height; + + switch (r) { + case AV1_INTRA_FRAME: + pic.IntraFrameWidthinPixelMinus1 = frameExtent.width - 1; + pic.IntraFrameHeightinPixelMinus1 = frameExtent.height - 1; + pic.VerticalScaleFactorForIntra = av1_scaling_factor; + pic.HorizontalScaleFactorForIntra = av1_scaling_factor; + break; + case AV1_LAST_FRAME: + pic.LastFrameWidthinPixelMinus1 = ref_width; + pic.LastFrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForLast = v_scale_factor; + pic.HorizontalScaleFactorForLast = h_scale_factor; + break; + case AV1_LAST2_FRAME: + pic.Last2FrameWidthinPixelMinus1 = ref_width; + pic.Last2FrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForLast2 = v_scale_factor; + pic.HorizontalScaleFactorForLast2 = h_scale_factor; + break; + case AV1_LAST3_FRAME: + pic.Last3FrameWidthinPixelMinus1 = ref_width; + pic.Last3FrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForLast3 = v_scale_factor; + pic.HorizontalScaleFactorForLast3 = h_scale_factor; + break; + case AV1_GOLDEN_FRAME: + pic.GoldenFrameWidthinPixelMinus1 = ref_width; + pic.GoldenFrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForGolden = v_scale_factor; + pic.HorizontalScaleFactorForGolden = h_scale_factor; + break; + case AV1_BWDREF_FRAME: + pic.BWDREFFrameWidthinPixelMinus1 = ref_width; + pic.BWDREFFrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForBWDREF = v_scale_factor; + pic.HorizontalScaleFactorForBWDREF = h_scale_factor; + break; + case AV1_ALTREF2_FRAME: + pic.ALTREF2FrameWidthinPixelMinus1 = ref_width; + pic.ALTREF2FrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForALTREF2 = v_scale_factor; + pic.HorizontalScaleFactorForALTREF2 = h_scale_factor; + break; + case AV1_ALTREF_FRAME: + pic.ALTREFFrameWidthinPixelMinus1 = ref_width; + pic.ALTREFFrameHeightinPixelMinus1 = ref_height; + pic.VerticalScaleFactorForALTREF = v_scale_factor; + pic.HorizontalScaleFactorForALTREF = h_scale_factor; + break; + default: + break; + } + } + } + + pic.FrameLevelGlobalMotionInvalidFlags = 0; + for (enum av1_ref_frame r = AV1_INTRA_FRAME; r <= AV1_ALTREF_FRAME; r++) + pic.ReferenceFrameOrderHint[r] = ref_info[r].order_hint; + }; + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_INTER_PRED_STATE), inter) { + inter.ActiveReferenceBitmask = ref_mask; + + for (enum av1_ref_frame r = AV1_LAST_FRAME; r <= AV1_ALTREF_FRAME; r++) { + switch (r) { + case AV1_LAST_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints0[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_LAST2_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints1[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_LAST3_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints2[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_GOLDEN_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints3[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_BWDREF_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints4[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_ALTREF2_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints5[j] = ref_info[r].ref_order_hints[j + 1]; + break; + case AV1_ALTREF_FRAME: + for (unsigned j = 0; j < 7; j++) + inter.SavedOrderHints6[j] = ref_info[r].ref_order_hints[j + 1]; + break; + default: + break; + } + } + } + + for (unsigned i = 0; i < 8; ++i) { + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_SEGMENT_STATE), seg) { + seg.SegmentID = i; + seg.SegmentFeatureMask = std_pic_info->pSegmentation->FeatureEnabled[i]; + seg.SegmentDeltaQindex = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_ALT_Q]; + seg.SegmentBlockSkipFlag = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_SKIP]; + seg.SegmentBlockGlobalMVFlag = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_GLOBAL_MV]; + seg.SegmentLosslessFlag = lossless[i]; + if (lossless[i] || !std_pic_info->pQuantization->flags.using_qmatrix) { + seg.SegmentLumaYQMLevel = av1_num_qm_levels - 1; + seg.SegmentChromaUQMLevel = av1_num_qm_levels - 1; + seg.SegmentChromaVQMLevel = av1_num_qm_levels - 1; + } else { + seg.SegmentLumaYQMLevel = std_pic_info->pQuantization->qm_y; + seg.SegmentChromaUQMLevel = std_pic_info->pQuantization->qm_u; + seg.SegmentChromaVQMLevel = std_pic_info->pQuantization->qm_v; + } + /* TODO. handling negative values? + seg.SegmentDeltaLoopFilterLevelLumaVertical = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_ALT_LFYV]; + seg.SegmentDeltaLoopFilterLevelLumaHorizontal = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_ALT_LFYH]; + seg.SegmentDeltaLoopFilterLevelChromaU = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_ALT_LFU]; + seg.SegmentDeltaLoopFilterLevelChromaV = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_ALT_LFV]; + seg.SegmentReferenceFrame = std_pic_info->pSegmentation->FeatureData[i][SEG_LVL_REF_FRAME]; + */ + }; + + if (!std_pic_info->flags.segmentation_enabled) + break; + } + + const StdVideoAV1LoopFilter *lf = std_pic_info->pLoopFilter; + const StdVideoAV1CDEF *cdef = std_pic_info->pCDEF; + uint32_t cdef_strengths[8] = { 0 }, cdef_uv_strengths[8] = { 0 }; + for (unsigned i = 0; i < (1 << cdef->cdef_bits); ++i) { + cdef_strengths[i] = (cdef->cdef_y_pri_strength[i] << 2) + + cdef->cdef_y_sec_strength[i]; + cdef_uv_strengths[i] = (cdef->cdef_uv_pri_strength[i] << 2) + + cdef->cdef_uv_sec_strength[i]; + } + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_INLOOP_FILTER_STATE), fil) { + fil.LumaYDeblockerFilterLevelVertical = lf->loop_filter_level[0]; + fil.LumaYDeblockerFilterLevelHorizontal = lf->loop_filter_level[1]; + fil.ChromaUDeblockerFilterLevel = lf->loop_filter_level[2]; + fil.ChromaVDeblockerFilterLevel = lf->loop_filter_level[3]; + fil.DeblockerFilterSharpnessLevel = lf->loop_filter_sharpness; + fil.DeblockerFilterModeRefDeltaEnableFlag = lf->flags.loop_filter_delta_enabled; + fil.DeblockerDeltaLFResolution = std_pic_info->delta_lf_res; + fil.DeblockerFilterDeltaLFMultiFlag = std_pic_info->flags.delta_lf_multi; + fil.DeblockerFilterDeltaLFPresentFlag = std_pic_info->flags.delta_lf_present; + fil.DeblockerFilterRefDeltas0 = lf->loop_filter_ref_deltas[0]; + fil.DeblockerFilterRefDeltas1 = lf->loop_filter_ref_deltas[1]; + fil.DeblockerFilterRefDeltas2 = lf->loop_filter_ref_deltas[2]; + fil.DeblockerFilterRefDeltas3 = lf->loop_filter_ref_deltas[3]; + fil.DeblockerFilterRefDeltas4 = lf->loop_filter_ref_deltas[4]; + fil.DeblockerFilterRefDeltas5 = lf->loop_filter_ref_deltas[5]; + fil.DeblockerFilterRefDeltas6 = lf->loop_filter_ref_deltas[6]; + fil.DeblockerFilterRefDeltas7 = lf->loop_filter_ref_deltas[7]; + fil.DeblockerFilterModeDeltas0 = lf->loop_filter_mode_deltas[0]; + fil.DeblockerFilterModeDeltas1 = lf->loop_filter_mode_deltas[1]; + fil.CDEFYStrength0 = cdef_strengths[0]; + fil.CDEFYStrength1 = cdef_strengths[1]; + fil.CDEFYStrength2 = cdef_strengths[2]; + fil.CDEFYStrength3 = cdef_strengths[3]; + fil.CDEFBits = cdef->cdef_bits; + fil.CDEFFilterDmpaingFactorMinus3 = cdef->cdef_damping_minus_3; + fil.CDEFYStrength4 = cdef_strengths[4]; + fil.CDEFYStrength5 = cdef_strengths[5]; + fil.CDEFYStrength6 = cdef_strengths[6]; + fil.CDEFYStrength7 = cdef_strengths[7]; + fil.CDEFUVStrength0 = cdef_uv_strengths[0]; + fil.CDEFUVStrength1 = cdef_uv_strengths[1]; + fil.CDEFUVStrength2 = cdef_uv_strengths[2]; + fil.CDEFUVStrength3 = cdef_uv_strengths[3]; + fil.CDEFUVStrength4 = cdef_uv_strengths[4]; + fil.CDEFUVStrength5 = cdef_uv_strengths[5]; + fil.CDEFUVStrength6 = cdef_uv_strengths[6]; + fil.CDEFUVStrength7 = cdef_uv_strengths[7]; + fil.SuperResUpscaledFrameWidthMinus1 = frameExtent.width - 1; + fil.SuperResDenom = std_pic_info->flags.use_superres ? 0 /*TODO*/ : 8; + fil.FrameLoopRestorationFilterLumaY = frame_restoration_type[0]; + fil.FrameLoopRestorationFilterChromaU = frame_restoration_type[1]; + fil.FrameLoopRestorationFilterChromaV = frame_restoration_type[2]; + + bool loop_restoration_filter_enable = + frame_restoration_type[0] || frame_restoration_type[1] || frame_restoration_type[2]; + + fil.LoopRestorationUnitSizeLumaY =loop_restoration_filter_enable ? + std_pic_info->pLoopRestoration->LoopRestorationSize[0] : 0; + fil.UseSameLoopRestorationUnitSizeChromasUVFlag = (frame_restoration_type[1] != 0 || frame_restoration_type[2] !=0) ? + std_pic_info->pLoopRestoration->LoopRestorationSize[0] == std_pic_info->pLoopRestoration->LoopRestorationSize[1] : false; + + fil.LumaPlanex_step_qn = 0; + fil.LumaPlanex0_qn = 0; + fil.ChromaPlanex_step_qn = 0; + fil.ChromaPlanex0_qn = 0; + }; + + unsigned column = tile_idx % std_pic_info->pTileInfo->TileCols; + unsigned row = tile_idx / std_pic_info->pTileInfo->TileCols; + bool last_tile = (column == std_pic_info->pTileInfo->TileCols - 1) && + (row == std_pic_info->pTileInfo->TileRows - 1); + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_TILE_CODING), til) { + til.FrameTileID = tile_idx; + til.TGTileNum = tile_idx; + til.TileGroupID = 0; + til.TileColumnPositioninSBUnit = std_pic_info->pTileInfo->pMiColStarts[column]; + til.TileRowPositioninSBUnit = std_pic_info->pTileInfo->pMiRowStarts[row]; + til.TileWidthinSBMinus1 = std_pic_info->pTileInfo->pWidthInSbsMinus1[column]; + til.TileHeightinSBMinus1 = std_pic_info->pTileInfo->pHeightInSbsMinus1[row]; + til.IsLastTileofRowFlag = column == std_pic_info->pTileInfo->TileCols - 1; + til.IsLastTileofColumnFlag = row == std_pic_info->pTileInfo->TileRows - 1; + til.IsStartTileofTileGroupFlag = tile_idx == 0; + til.IsEndTileofTileGroupFlag = (column == std_pic_info->pTileInfo->TileCols - 1) && + (row == std_pic_info->pTileInfo->TileRows - 1); + til.IsLastTileofFrameFlag = (column == std_pic_info->pTileInfo->TileCols - 1) && + (row == std_pic_info->pTileInfo->TileRows - 1); + til.DisableCDFUpdateFlag = std_pic_info->flags.disable_cdf_update; + til.DisableFrameContextUpdateFlag = std_pic_info->flags.disable_frame_end_update_cdf || (tile_idx != std_pic_info->pTileInfo->context_update_tile_id); + til.NumberofActiveBEPipes = 1; + til.NumofTileColumnsinFrameMinus1 = std_pic_info->pTileInfo->TileCols - 1; + til.NumofTileRowsinFrameMinus1 = std_pic_info->pTileInfo->TileRows - 1; + }; + + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_BSD_OBJECT), bsd) { + bsd.TileIndirectBSDDataLength = av1_pic_info->pTileSizes[tile_idx]; + bsd.TileIndirectDataStartAddress = (frame_info->srcBufferOffset & 4095) + + av1_pic_info->pTileOffsets[tile_idx]; + }; + + if (last_tile) { + anv_batch_emit(&cmd_buffer->batch, GENX(AVP_VD_CONTROL_STATE), vd) { + vd.VDControlState.MemoryImplicitFlush = 1; + } + + anv_batch_emit(&cmd_buffer->batch, GENX(VD_PIPELINE_FLUSH), vd) { + vd.AVPPipelineDone = 1; + vd.VDCommandMessageParserDone = 1; + vd.AVPPipelineCommandFlush = 1; + } + } +} + +static void +anv_av1_decode_video(struct anv_cmd_buffer *cmd_buffer, + const VkVideoDecodeInfoKHR *frame_info) +{ + const struct VkVideoDecodeAV1PictureInfoKHR *av1_pic_info = + vk_find_struct_const(frame_info->pNext, VIDEO_DECODE_AV1_PICTURE_INFO_KHR); + + for (unsigned t = 0; t < av1_pic_info->tileCount; t++) + anv_av1_decode_video_tile(cmd_buffer, frame_info, t); +} +#endif + static void handle_inline_query_end(struct anv_cmd_buffer *cmd_buffer, const VkVideoInlineQueryInfoKHR *inline_query) @@ -1236,6 +2392,9 @@ genX(CmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, { ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + if (anv_batch_has_error(&cmd_buffer->batch)) + return; + const VkVideoInlineQueryInfoKHR *inline_query = vk_find_struct_const(frame_info->pNext, VIDEO_INLINE_QUERY_INFO_KHR); @@ -1246,6 +2405,11 @@ genX(CmdDecodeVideoKHR)(VkCommandBuffer commandBuffer, case VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR: anv_h265_decode_video(cmd_buffer, frame_info); break; +#if GFX_VERx10 >= 120 + case VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR: + anv_av1_decode_video(cmd_buffer, frame_info); + break; +#endif default: assert(0); }