diff --git a/src/intel/vulkan_hasvk/anv_private.h b/src/intel/vulkan_hasvk/anv_private.h index 6d32d63..43b7b76 100644 --- a/src/intel/vulkan_hasvk/anv_private.h +++ b/src/intel/vulkan_hasvk/anv_private.h @@ -87,8 +87,8 @@ #include "vk_util.h" #include "vk_queue.h" #include "vk_log.h" -#include "vk_ycbcr_conversion.h" #include "vk_video.h" +#include "vk_ycbcr_conversion.h" /* Pre-declarations needed for WSI entrypoints */ struct wl_surface; @@ -1071,6 +1071,7 @@ struct anv_device { pthread_mutex_t mutex; struct intel_batch_decode_ctx decoder[ANV_MAX_QUEUE_FAMILIES]; + /* * When decoding a anv_cmd_buffer, we might need to search for BOs through * the cmd_buffer's list. @@ -2638,8 +2639,8 @@ struct anv_cmd_buffer { struct u_trace trace; struct { - struct anv_video_session *vid; - struct anv_video_session_params *params; + struct anv_video_session *vid; + struct anv_video_session_params *params; } video; }; @@ -3700,22 +3701,15 @@ struct anv_query_pool { struct intel_perf_query_info **pass_query; }; -static inline uint32_t khr_perf_query_preamble_offset(const struct anv_query_pool *pool, - uint32_t pass) -{ - return pool->pass_size * pass + 8; -} - -struct anv_vid_mem { - struct anv_device_memory *mem; - VkDeviceSize offset; - VkDeviceSize size; -}; - -#define ANV_VIDEO_MEM_REQS_H264 4 #define ANV_MB_WIDTH 16 #define ANV_MB_HEIGHT 16 +struct anv_vid_mem { + struct anv_device_memory *mem; + VkDeviceSize offset; + VkDeviceSize size; +}; + enum { ANV_VID_MEM_H264_INTRA_ROW_STORE, ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE, @@ -3725,16 +3719,22 @@ enum { }; struct anv_video_session { - struct vk_video_session vk; + struct vk_video_session vk; /* the decoder needs some private memory allocations */ - struct anv_vid_mem vid_mem[ANV_VID_MEM_H264_MAX]; + struct anv_vid_mem vid_mem[ANV_VID_MEM_H264_MAX]; }; struct anv_video_session_params { - struct vk_video_session_parameters vk; + struct vk_video_session_parameters vk; }; +static inline uint32_t khr_perf_query_preamble_offset(const struct anv_query_pool *pool, + uint32_t pass) +{ + return pool->pass_size * pass + 8; +} + void anv_dump_pipe_bits(enum anv_pipe_bits bits); @@ -3864,8 +3864,11 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(anv_sampler, base, VkSampler, VK_DEFINE_NONDISP_HANDLE_CASTS(anv_performance_configuration_intel, base, VkPerformanceConfigurationINTEL, VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL) -VK_DEFINE_NONDISP_HANDLE_CASTS(anv_video_session, vk.base, VkVideoSessionKHR, VK_OBJECT_TYPE_VIDEO_SESSION_KHR) -VK_DEFINE_NONDISP_HANDLE_CASTS(anv_video_session_params, vk.base, VkVideoSessionParametersKHR, VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR) +VK_DEFINE_NONDISP_HANDLE_CASTS(anv_video_session, vk.base, VkVideoSessionKHR, + VK_OBJECT_TYPE_VIDEO_SESSION_KHR) +VK_DEFINE_NONDISP_HANDLE_CASTS(anv_video_session_params, vk.base, + VkVideoSessionParametersKHR, + VK_OBJECT_TYPE_VIDEO_SESSION_PARAMETERS_KHR) #define anv_genX(devinfo, thing) ({ \ __typeof(&gfx7_##thing) genX_thing; \ diff --git a/src/intel/vulkan_hasvk/anv_video.c b/src/intel/vulkan_hasvk/anv_video.c index 2f3e3c1..7e87fcd 100644 --- a/src/intel/vulkan_hasvk/anv_video.c +++ b/src/intel/vulkan_hasvk/anv_video.c @@ -23,18 +23,23 @@ #include "anv_private.h" +#include +#include +#include "vk_common_entrypoints.h" #include "vk_video/vulkan_video_codecs_common.h" +#include "vk_video/vulkan_video_codec_h264std.h" VkResult anv_CreateVideoSessionKHR(VkDevice _device, - const VkVideoSessionCreateInfoKHR *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkVideoSessionKHR *pVideoSession) + const VkVideoSessionCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkVideoSessionKHR *pVideoSession) { ANV_FROM_HANDLE(anv_device, device, _device); struct anv_video_session *vid = - vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*vid), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); + vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*vid), 8, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (!vid) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); @@ -62,7 +67,10 @@ anv_DestroyVideoSessionKHR(VkDevice _device, if (!_session) return; - vk_object_base_finish(&vid->vk.base); + /* Otherwise we hit VK_ERROR_DEVICE_LOST for unknown reasons. */ + vk_common_DeviceWaitIdle(_device); + + vk_video_session_finish(&vid->vk); vk_free2(&device->vk.alloc, pAllocator, vid); } @@ -101,9 +109,28 @@ anv_DestroyVideoSessionParametersKHR(VkDevice _device, VkResult anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, - const VkVideoProfileInfoKHR *pVideoProfile, - VkVideoCapabilitiesKHR *pCapabilities) + const VkVideoProfileInfoKHR + *pVideoProfile, + VkVideoCapabilitiesKHR + *pCapabilities) { + if (pVideoProfile->videoCodecOperation != VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) { + return VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR; + } + + const VkVideoDecodeH264ProfileInfoKHR *h264_profile = + vk_find_struct_const(pVideoProfile->pNext, VIDEO_DECODE_H264_PROFILE_INFO_KHR); + if (h264_profile) { + switch (h264_profile->stdProfileIdc) { + case STD_VIDEO_H264_PROFILE_IDC_BASELINE: + case STD_VIDEO_H264_PROFILE_IDC_MAIN: + case STD_VIDEO_H264_PROFILE_IDC_HIGH: + break; + default: + return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; + } + } + pCapabilities->minBitstreamBufferOffsetAlignment = 32; pCapabilities->minBitstreamBufferSizeAlignment = 32; pCapabilities->pictureAccessGranularity.width = ANV_MB_WIDTH; @@ -112,105 +139,150 @@ anv_GetPhysicalDeviceVideoCapabilitiesKHR(VkPhysicalDevice physicalDevice, pCapabilities->minCodedExtent.height = ANV_MB_HEIGHT; pCapabilities->maxCodedExtent.width = 4096; pCapabilities->maxCodedExtent.height = 4096; - pCapabilities->flags = VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; + pCapabilities->flags = + VK_VIDEO_CAPABILITY_SEPARATE_REFERENCE_IMAGES_BIT_KHR; - struct VkVideoDecodeCapabilitiesKHR *dec_caps = (struct VkVideoDecodeCapabilitiesKHR *) + 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; + dec_caps->flags = + VK_VIDEO_DECODE_CAPABILITY_DPB_AND_OUTPUT_COINCIDE_BIT_KHR; - switch (pVideoProfile->videoCodecOperation) { - case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: { - struct VkVideoDecodeH264CapabilitiesKHR *ext = (struct VkVideoDecodeH264CapabilitiesKHR *) - vk_find_struct(pCapabilities->pNext, VIDEO_DECODE_H264_CAPABILITIES_KHR); - pCapabilities->maxDpbSlots = 17; - pCapabilities->maxActiveReferencePictures = 16; + struct VkVideoDecodeH264CapabilitiesKHR *ext = + (struct VkVideoDecodeH264CapabilitiesKHR *) + vk_find_struct(pCapabilities->pNext, + VIDEO_DECODE_H264_CAPABILITIES_KHR); + pCapabilities->maxDpbSlots = 16; + pCapabilities->maxActiveReferencePictures = 16; + if (ext) { ext->fieldOffsetGranularity.x = 0; ext->fieldOffsetGranularity.y = 0; ext->maxLevelIdc = 51; - strcpy(pCapabilities->stdHeaderVersion.extensionName, VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME); - pCapabilities->stdHeaderVersion.specVersion = VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION; - break; - } - default: - break; } + strcpy(pCapabilities->stdHeaderVersion.extensionName, + VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_EXTENSION_NAME); + pCapabilities->stdHeaderVersion.specVersion = + VK_STD_VULKAN_VIDEO_CODEC_H264_DECODE_SPEC_VERSION; + return VK_SUCCESS; } VkResult anv_GetPhysicalDeviceVideoFormatPropertiesKHR(VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceVideoFormatInfoKHR *pVideoFormatInfo, - uint32_t *pVideoFormatPropertyCount, - VkVideoFormatPropertiesKHR *pVideoFormatProperties) + const + VkPhysicalDeviceVideoFormatInfoKHR + *pVideoFormatInfo, + uint32_t + *pVideoFormatPropertyCount, + VkVideoFormatPropertiesKHR + *pVideoFormatProperties) { *pVideoFormatPropertyCount = 1; if (!pVideoFormatProperties) return VK_SUCCESS; + VkImageUsageFlags usage_flags = pVideoFormatInfo->imageUsage; + + const VkImageUsageFlags dpb_output_coincide_usage = + VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR | + VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR; + if ((usage_flags & dpb_output_coincide_usage) == VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR || + (usage_flags & dpb_output_coincide_usage) == VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) + usage_flags |= dpb_output_coincide_usage; + + if (usage_flags & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR) + usage_flags |= + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + + pVideoFormatProperties[0].sType = + VK_STRUCTURE_TYPE_VIDEO_FORMAT_PROPERTIES_KHR; + pVideoFormatProperties[0].pNext = NULL; pVideoFormatProperties[0].format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + pVideoFormatProperties[0].componentMapping.r = + VK_COMPONENT_SWIZZLE_IDENTITY; + pVideoFormatProperties[0].componentMapping.g = + VK_COMPONENT_SWIZZLE_IDENTITY; + pVideoFormatProperties[0].componentMapping.b = + VK_COMPONENT_SWIZZLE_IDENTITY; + pVideoFormatProperties[0].componentMapping.a = + VK_COMPONENT_SWIZZLE_IDENTITY; + pVideoFormatProperties[0].imageCreateFlags = + VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT + | VK_IMAGE_CREATE_ALIAS_BIT; pVideoFormatProperties[0].imageType = VK_IMAGE_TYPE_2D; pVideoFormatProperties[0].imageTiling = VK_IMAGE_TILING_OPTIMAL; - pVideoFormatProperties[0].imageUsageFlags = pVideoFormatInfo->imageUsage; + pVideoFormatProperties[0].imageUsageFlags = usage_flags; + return VK_SUCCESS; } static void get_h264_video_session_mem_reqs(struct anv_video_session *vid, VkVideoSessionMemoryRequirementsKHR *mem_reqs, + uint32_t *pVideoSessionMemoryRequirementsCount, uint32_t memory_types) { - uint32_t width_in_mb = align(vid->vk.max_coded.width, ANV_MB_WIDTH) / ANV_MB_WIDTH; - /* intra row store is width in macroblocks * 64 */ - mem_reqs[0].memoryBindIndex = ANV_VID_MEM_H264_INTRA_ROW_STORE; - mem_reqs[0].memoryRequirements.size = width_in_mb * 64; - mem_reqs[0].memoryRequirements.alignment = 4096; - mem_reqs[0].memoryRequirements.memoryTypeBits = memory_types; + VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR, + out, + mem_reqs, + pVideoSessionMemoryRequirementsCount); - /* deblocking filter row store is width in macroblocks * 64 * 4*/ - mem_reqs[1].memoryBindIndex = ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE; - mem_reqs[1].memoryRequirements.size = width_in_mb * 64 * 4; - mem_reqs[1].memoryRequirements.alignment = 4096; - mem_reqs[1].memoryRequirements.memoryTypeBits = memory_types; + uint32_t width_in_mb = + align(vid->vk.max_coded.width, ANV_MB_WIDTH) / ANV_MB_WIDTH; + + /* intra row store is width in macroblocks * 64 */ + vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) { + p->memoryBindIndex = ANV_VID_MEM_H264_INTRA_ROW_STORE; + p->memoryRequirements.size = width_in_mb * 64; + p->memoryRequirements.alignment = 64; + p->memoryRequirements.memoryTypeBits = memory_types; + } + + /* deblocking filter row store is width in macroblocks * 64 * 4 */ + vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) { + p->memoryBindIndex = ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE; + p->memoryRequirements.size = width_in_mb * 64 * 4; + p->memoryRequirements.alignment = 64; + p->memoryRequirements.memoryTypeBits = memory_types; + } /* bsd mpc row scratch is width in macroblocks * 64 * 2 */ - mem_reqs[2].memoryBindIndex = ANV_VID_MEM_H264_BSD_MPC_ROW_SCRATCH; - mem_reqs[2].memoryRequirements.size = width_in_mb * 64 * 2; - mem_reqs[2].memoryRequirements.alignment = 4096; - mem_reqs[2].memoryRequirements.memoryTypeBits = memory_types; + vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) { + p->memoryBindIndex = ANV_VID_MEM_H264_BSD_MPC_ROW_SCRATCH; + p->memoryRequirements.size = width_in_mb * 64 * 2; + p->memoryRequirements.alignment = 64; + p->memoryRequirements.memoryTypeBits = memory_types; + } /* mpr row scratch is width in macroblocks * 64 * 2 */ - mem_reqs[3].memoryBindIndex = ANV_VID_MEM_H264_MPR_ROW_SCRATCH; - mem_reqs[3].memoryRequirements.size = width_in_mb * 64 * 2; - mem_reqs[3].memoryRequirements.alignment = 4096; - mem_reqs[3].memoryRequirements.memoryTypeBits = memory_types; + vk_outarray_append_typed(VkVideoSessionMemoryRequirementsKHR, &out, p) { + p->memoryBindIndex = ANV_VID_MEM_H264_MPR_ROW_SCRATCH; + p->memoryRequirements.size = width_in_mb * 64 * 2; + p->memoryRequirements.alignment = 64; + p->memoryRequirements.memoryTypeBits = memory_types; + } } VkResult anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device, VkVideoSessionKHR videoSession, - uint32_t *pVideoSessionMemoryRequirementsCount, - VkVideoSessionMemoryRequirementsKHR *mem_reqs) + uint32_t + *pVideoSessionMemoryRequirementsCount, + VkVideoSessionMemoryRequirementsKHR + *mem_reqs) { ANV_FROM_HANDLE(anv_device, device, _device); ANV_FROM_HANDLE(anv_video_session, vid, videoSession); - switch (vid->vk.op) { - case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: - *pVideoSessionMemoryRequirementsCount = ANV_VIDEO_MEM_REQS_H264; - break; - default: - UNREACHABLE("unknown codec"); - } - if (!mem_reqs) - return VK_SUCCESS; - uint32_t memory_types = (1ull << device->physical->memory.type_count) - 1; switch (vid->vk.op) { case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: - get_h264_video_session_mem_reqs(vid, mem_reqs, memory_types); + get_h264_video_session_mem_reqs(vid, mem_reqs, + pVideoSessionMemoryRequirementsCount, + memory_types); break; default: UNREACHABLE("unknown codec"); @@ -221,16 +293,17 @@ anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device, VkResult anv_UpdateVideoSessionParametersKHR(VkDevice _device, - VkVideoSessionParametersKHR _params, - const VkVideoSessionParametersUpdateInfoKHR *pUpdateInfo) + VkVideoSessionParametersKHR _params, + const + VkVideoSessionParametersUpdateInfoKHR + *pUpdateInfo) { ANV_FROM_HANDLE(anv_video_session_params, params, _params); return vk_video_session_parameters_update(¶ms->vk, pUpdateInfo); } static void -copy_bind(struct anv_vid_mem *dst, - const VkBindVideoSessionMemoryInfoKHR *src) +copy_bind(struct anv_vid_mem *dst, const VkBindVideoSessionMemoryInfoKHR *src) { dst->mem = anv_device_memory_from_handle(src->memory); dst->offset = src->memoryOffset; @@ -245,15 +318,19 @@ anv_BindVideoSessionMemoryKHR(VkDevice _device, { ANV_FROM_HANDLE(anv_video_session, vid, videoSession); - assert(bind_mem_count == 4); switch (vid->vk.op) { case VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR: + /* Validate bind_mem_count and memoryBindIndex values to prevent + * out-of-bounds access to vid->vid_mem array. */ for (unsigned i = 0; i < bind_mem_count; i++) { + if (bind_mem[i].memoryBindIndex >= ANV_VID_MEM_H264_MAX) { + continue; + } copy_bind(&vid->vid_mem[bind_mem[i].memoryBindIndex], &bind_mem[i]); } break; default: - UNREACHABLE("unknown codec"); + UNREACHABLE("unknown codec!"); } return VK_SUCCESS; }