hasvk: Validate profiles and harden the video session objects.

Assisted-by: Claude
This commit is contained in:
dancingmirrors authored and elwrcl committed 2026-07-21 22:08:59 +03:00
1 parent cece575042
commit 5c6ad1fb4c
2 files changed
+149 -69

No files matched your search

+15 -12
View File
@@ -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.
@@ -3700,11 +3701,8 @@ 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;
}
#define ANV_MB_WIDTH 16
#define ANV_MB_HEIGHT 16
struct anv_vid_mem {
struct anv_device_memory *mem;
@@ -3712,10 +3710,6 @@ struct anv_vid_mem {
VkDeviceSize size;
};
#define ANV_VIDEO_MEM_REQS_H264 4
#define ANV_MB_WIDTH 16
#define ANV_MB_HEIGHT 16
enum {
ANV_VID_MEM_H264_INTRA_ROW_STORE,
ANV_VID_MEM_H264_DEBLOCK_FILTER_ROW_STORE,
@@ -3735,6 +3729,12 @@ struct anv_video_session_params {
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; \
+134 -57
View File
@@ -23,7 +23,11 @@
#include "anv_private.h"
#include <stdlib.h>
#include <string.h>
#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,
@@ -34,7 +38,8 @@ anv_CreateVideoSessionKHR(VkDevice _device,
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;
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;
VK_OUTARRAY_MAKE_TYPED(VkVideoSessionMemoryRequirementsKHR,
out,
mem_reqs,
pVideoSessionMemoryRequirementsCount);
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_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 */
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;
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");
@@ -222,15 +294,16 @@ anv_GetVideoSessionMemoryRequirementsKHR(VkDevice _device,
VkResult
anv_UpdateVideoSessionParametersKHR(VkDevice _device,
VkVideoSessionParametersKHR _params,
const VkVideoSessionParametersUpdateInfoKHR *pUpdateInfo)
const
VkVideoSessionParametersUpdateInfoKHR
*pUpdateInfo)
{
ANV_FROM_HANDLE(anv_video_session_params, params, _params);
return vk_video_session_parameters_update(&params->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;
}