21#define VK_NO_PROTOTYPES
22#define VK_ENABLE_BETA_EXTENSIONS
26#include <versionhelpers.h>
54#include <va/va_drmcommon.h>
57#include <sys/sysmacros.h>
61#include <drm_fourcc.h>
65#if HAVE_LINUX_DMA_BUF_H
67#include <linux/dma-buf.h>
73#define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x)
87#ifdef VK_EXT_shader_long_vector
88 VkPhysicalDeviceShaderLongVectorFeaturesEXT long_vector;
91#ifdef VK_EXT_shader_replicated_composites
92 VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT replicated_composites;
95#ifdef VK_EXT_zero_initialize_device_memory
96 VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT zero_initialize;
99#ifdef VK_KHR_shader_expect_assume
100 VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume;
103#ifdef VK_KHR_shader_maximal_reconvergence
104 VkPhysicalDeviceShaderMaximalReconvergenceFeaturesKHR maximal_reconvergence;
107#ifdef VK_KHR_maintenance9
108 VkPhysicalDeviceMaintenance9FeaturesKHR maintenance_9;
110#ifdef VK_KHR_maintenance11
111 VkPhysicalDeviceMaintenance11FeaturesKHR maintenance_11;
113#ifdef VK_KHR_unified_image_layouts
114 VkPhysicalDeviceUnifiedImageLayoutsFeaturesKHR unified_layouts;
118#ifdef VK_KHR_video_maintenance2
119 VkPhysicalDeviceVideoMaintenance2FeaturesKHR video_maintenance_2;
121#ifdef VK_KHR_video_decode_vp9
122 VkPhysicalDeviceVideoDecodeVP9FeaturesKHR vp9_decode;
124#ifdef VK_KHR_video_encode_av1
125 VkPhysicalDeviceVideoEncodeAV1FeaturesKHR av1_encode;
132#ifdef VK_KHR_shader_relaxed_extended_instruction
133 VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instruction;
136#ifdef VK_KHR_internally_synchronized_queues
137 VkPhysicalDeviceInternallySynchronizedQueuesFeaturesKHR internal_queue_sync;
158 VkPhysicalDeviceExternalMemoryHostPropertiesEXT
hprops;
249 feats->
device = (VkPhysicalDeviceFeatures2) {
250 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
254 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
256 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
258 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
261 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES);
263 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR);
265 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT);
267#ifdef VK_EXT_shader_long_vector
269 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_FEATURES_EXT);
272#ifdef VK_EXT_shader_replicated_composites
274 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT);
277#ifdef VK_EXT_zero_initialize_device_memory
279 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_DEVICE_MEMORY_FEATURES_EXT);
282#ifdef VK_KHR_shader_expect_assume
284 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR);
287#ifdef VK_KHR_shader_maximal_reconvergence
289 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MAXIMAL_RECONVERGENCE_FEATURES_KHR);
292#ifdef VK_KHR_maintenance9
294 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_9_FEATURES_KHR);
296#ifdef VK_KHR_maintenance11
298 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_11_FEATURES_KHR);
300#ifdef VK_KHR_unified_image_layouts
302 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFIED_IMAGE_LAYOUTS_FEATURES_KHR);
306 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
307#ifdef VK_KHR_video_maintenance2
309 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR);
311#ifdef VK_KHR_video_decode_vp9
313 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR);
315#ifdef VK_KHR_video_encode_av1
317 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR);
321 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
323 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
325 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
327 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR);
329#ifdef VK_KHR_shader_relaxed_extended_instruction
331 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR);
334#ifdef VK_KHR_internally_synchronized_queues
336 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INTERNALLY_SYNCHRONIZED_QUEUES_FEATURES_KHR);
340 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV);
346#define COPY_VAL(VAL) \
348 dst->VAL = src->VAL; \
351 COPY_VAL(device.features.shaderImageGatherExtended);
352 COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
353 COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
354 COPY_VAL(device.features.fragmentStoresAndAtomics);
355 COPY_VAL(device.features.vertexPipelineStoresAndAtomics);
356 COPY_VAL(device.features.shaderInt64);
357 COPY_VAL(device.features.shaderInt16);
358 COPY_VAL(device.features.shaderFloat64);
359 COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
360 COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
362 COPY_VAL(vulkan_1_1.samplerYcbcrConversion);
363 COPY_VAL(vulkan_1_1.storagePushConstant16);
364 COPY_VAL(vulkan_1_1.storageBuffer16BitAccess);
365 COPY_VAL(vulkan_1_1.uniformAndStorageBuffer16BitAccess);
367 COPY_VAL(vulkan_1_2.timelineSemaphore);
368 COPY_VAL(vulkan_1_2.scalarBlockLayout);
369 COPY_VAL(vulkan_1_2.bufferDeviceAddress);
370 COPY_VAL(vulkan_1_2.hostQueryReset);
371 COPY_VAL(vulkan_1_2.storagePushConstant8);
373 COPY_VAL(vulkan_1_2.storageBuffer8BitAccess);
374 COPY_VAL(vulkan_1_2.uniformAndStorageBuffer8BitAccess);
376 COPY_VAL(vulkan_1_2.shaderBufferInt64Atomics);
377 COPY_VAL(vulkan_1_2.shaderSharedInt64Atomics);
378 COPY_VAL(vulkan_1_2.vulkanMemoryModel);
379 COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
380 COPY_VAL(vulkan_1_2.vulkanMemoryModelAvailabilityVisibilityChains);
381 COPY_VAL(vulkan_1_2.uniformBufferStandardLayout);
382 COPY_VAL(vulkan_1_2.runtimeDescriptorArray);
383 COPY_VAL(vulkan_1_2.shaderSubgroupExtendedTypes);
384 COPY_VAL(vulkan_1_2.shaderUniformBufferArrayNonUniformIndexing);
385 COPY_VAL(vulkan_1_2.shaderSampledImageArrayNonUniformIndexing);
386 COPY_VAL(vulkan_1_2.shaderStorageBufferArrayNonUniformIndexing);
387 COPY_VAL(vulkan_1_2.shaderStorageImageArrayNonUniformIndexing);
389 COPY_VAL(vulkan_1_3.dynamicRendering);
391 COPY_VAL(vulkan_1_3.synchronization2);
392 COPY_VAL(vulkan_1_3.computeFullSubgroups);
393 COPY_VAL(vulkan_1_3.subgroupSizeControl);
394 COPY_VAL(vulkan_1_3.shaderZeroInitializeWorkgroupMemory);
395 COPY_VAL(vulkan_1_3.dynamicRendering);
397 COPY_VAL(timeline_semaphore.timelineSemaphore);
398 COPY_VAL(subgroup_rotate.shaderSubgroupRotate);
399 COPY_VAL(host_image_copy.hostImageCopy);
401#ifdef VK_EXT_shader_long_vector
405#ifdef VK_EXT_shader_replicated_composites
406 COPY_VAL(replicated_composites.shaderReplicatedComposites);
409#ifdef VK_EXT_zero_initialize_device_memory
410 COPY_VAL(zero_initialize.zeroInitializeDeviceMemory);
413 COPY_VAL(video_maintenance_1.videoMaintenance1);
414#ifdef VK_KHR_video_maintenance2
415 COPY_VAL(video_maintenance_2.videoMaintenance2);
418#ifdef VK_KHR_video_decode_vp9
419 COPY_VAL(vp9_decode.videoDecodeVP9);
422#ifdef VK_KHR_video_encode_av1
423 COPY_VAL(av1_encode.videoEncodeAV1);
426 COPY_VAL(shader_object.shaderObject);
428 COPY_VAL(cooperative_matrix.cooperativeMatrix);
430 COPY_VAL(atomic_float.shaderBufferFloat32Atomics);
431 COPY_VAL(atomic_float.shaderBufferFloat32AtomicAdd);
433 COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout);
434 COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayoutScalarBlockLayout);
435 COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout8BitAccess);
436 COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout16BitAccess);
438#ifdef VK_KHR_shader_relaxed_extended_instruction
439 COPY_VAL(relaxed_extended_instruction.shaderRelaxedExtendedInstruction);
442#ifdef VK_KHR_shader_expect_assume
443 COPY_VAL(expect_assume.shaderExpectAssume);
446#ifdef VK_KHR_shader_maximal_reconvergence
447 COPY_VAL(maximal_reconvergence.shaderMaximalReconvergence);
450#ifdef VK_KHR_maintenance9
451 COPY_VAL(maintenance_9.maintenance9);
453#ifdef VK_KHR_maintenance11
454 COPY_VAL(maintenance_11.maintenance11);
456#ifdef VK_KHR_unified_image_layouts
457 COPY_VAL(unified_layouts.unifiedImageLayouts);
458 COPY_VAL(unified_layouts.unifiedImageLayoutsVideo);
461#ifdef VK_KHR_internally_synchronized_queues
462 COPY_VAL(internal_queue_sync.internallySynchronizedQueues);
470#define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
471#define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
483 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_GRAY8, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8_UNORM } },
484 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GRAY10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
485 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GRAY12, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
486 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GRAY14, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
487 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GRAY16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
488 { VK_FORMAT_R32_UINT,
AV_PIX_FMT_GRAY32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_UINT } },
489 { VK_FORMAT_R32_SFLOAT,
AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_SFLOAT } },
492 { VK_FORMAT_R8G8B8A8_UNORM,
AV_PIX_FMT_BGRA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
493 { VK_FORMAT_R8G8B8A8_UNORM,
AV_PIX_FMT_RGBA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
494 { VK_FORMAT_R8G8B8_UNORM,
AV_PIX_FMT_RGB24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8_UNORM } },
495 { VK_FORMAT_B8G8R8_UNORM,
AV_PIX_FMT_BGR24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8_UNORM } },
496 { VK_FORMAT_R16G16B16_UNORM,
AV_PIX_FMT_RGB48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16_UNORM } },
497 { VK_FORMAT_R16G16B16A16_UNORM,
AV_PIX_FMT_RGBA64, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
498 { VK_FORMAT_R8G8B8A8_UNORM,
AV_PIX_FMT_BGR0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
499 { VK_FORMAT_R8G8B8A8_UNORM,
AV_PIX_FMT_RGB0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
500 { VK_FORMAT_A2R10G10B10_UNORM_PACK32,
AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
501 { VK_FORMAT_A2B10G10R10_UNORM_PACK32,
AV_PIX_FMT_X2BGR10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2B10G10R10_UNORM_PACK32 } },
502 { VK_FORMAT_R32G32B32_SFLOAT,
AV_PIX_FMT_RGBF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_SFLOAT } },
503 { VK_FORMAT_R16G16B16A16_SFLOAT,
AV_PIX_FMT_RGBAF16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_SFLOAT } },
504 { VK_FORMAT_R32G32B32A32_SFLOAT,
AV_PIX_FMT_RGBAF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_SFLOAT } },
505 { VK_FORMAT_R32G32B32_UINT,
AV_PIX_FMT_RGB96, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_UINT } },
506 { VK_FORMAT_R32G32B32A32_UINT,
AV_PIX_FMT_RGBA128, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_UINT } },
509 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_GBRP, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
510 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRP10, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
511 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRP12, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
512 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRP14, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
513 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRP16, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
514 { VK_FORMAT_R16_SFLOAT,
AV_PIX_FMT_GBRPF16, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT } },
515 { VK_FORMAT_R32_SFLOAT,
AV_PIX_FMT_GBRPF32, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
518 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_XYZP12, VK_IMAGE_ASPECT_COLOR_BIT, 3, 3, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
521 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_GBRAP, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
522 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRAP10, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
523 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRAP12, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
524 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRAP14, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
525 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_GBRAP16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
526 { VK_FORMAT_R16_SFLOAT,
AV_PIX_FMT_GBRAPF16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT, VK_FORMAT_R16_SFLOAT } },
527 { VK_FORMAT_R32_UINT,
AV_PIX_FMT_GBRAP32, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_R32_UINT } },
528 { VK_FORMAT_R32_SFLOAT,
AV_PIX_FMT_GBRAPF32, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R32_SFLOAT } },
535 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
AV_PIX_FMT_P010,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
536 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
AV_PIX_FMT_P012,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
541 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
AV_PIX_FMT_P210,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
542 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
AV_PIX_FMT_P212,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
547 { VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16,
AV_PIX_FMT_P410,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
548 { VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16,
AV_PIX_FMT_P412,
ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
566 { VK_FORMAT_G8B8G8R8_422_UNORM,
AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
567 { VK_FORMAT_B8G8R8G8_422_UNORM,
AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
568 { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
569 { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
570 { VK_FORMAT_G16B16G16R16_422_UNORM,
AV_PIX_FMT_Y216, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
573 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_YUVA420P, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
574 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA420P10, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
575 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA420P16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
578 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_YUVA422P, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
579 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA422P10, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
580 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA422P12, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
581 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA422P16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
584 { VK_FORMAT_R8_UNORM,
AV_PIX_FMT_YUVA444P, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
585 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA444P10, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
586 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA444P12, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
587 { VK_FORMAT_R16_UNORM,
AV_PIX_FMT_YUVA444P16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
590 { VK_FORMAT_A2R10G10B10_UNORM_PACK32,
AV_PIX_FMT_XV30, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
591 { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
592 { VK_FORMAT_R16G16B16A16_UNORM,
AV_PIX_FMT_XV48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
613 VkImageTiling tiling,
616 VkImageAspectFlags *
aspect,
617 VkImageUsageFlags *supported_usage,
618 int disable_multiplane,
int need_storage)
624 const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
625 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
626 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
630 VkFormatProperties3 fprops = {
631 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
633 VkFormatProperties2 prop = {
634 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
637 VkFormatFeatureFlagBits2 feats_primary, feats_secondary;
638 int basics_primary = 0, basics_secondary = 0;
639 int storage_primary = 0, storage_secondary = 0;
641 vk->GetPhysicalDeviceFormatProperties2(hwctx->
phys_dev,
645 feats_primary = tiling == VK_IMAGE_TILING_LINEAR ?
646 fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
647 basics_primary = (feats_primary & basic_flags) == basic_flags;
648 storage_primary = !!(feats_primary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
651 vk->GetPhysicalDeviceFormatProperties2(hwctx->
phys_dev,
654 feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ?
655 fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
656 basics_secondary = (feats_secondary & basic_flags) == basic_flags;
657 storage_secondary = !!(feats_secondary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
659 feats_secondary = feats_primary;
660 basics_secondary = basics_primary;
661 storage_secondary = storage_primary;
664 if (basics_primary &&
666 (!need_storage || (need_storage && (storage_primary | storage_secondary)))) {
681 ((need_storage && (storage_primary | storage_secondary)) ?
682 VK_IMAGE_USAGE_STORAGE_BIT : 0);
684 }
else if (basics_secondary &&
685 (!need_storage || (need_storage && storage_secondary))) {
706#if CONFIG_VULKAN_STATIC
707VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
716#if CONFIG_VULKAN_STATIC
719 static const char *lib_names[] = {
722#elif defined(__APPLE__)
733 p->libvulkan = dlopen(lib_names[
i], RTLD_NOW | RTLD_LOCAL);
743 hwctx->
get_proc_addr = (PFN_vkGetInstanceProcAddr)dlsym(p->libvulkan,
"vkGetInstanceProcAddr");
772#ifdef VK_KHR_shader_relaxed_extended_instruction
775#ifdef VK_EXT_shader_long_vector
778#ifdef VK_EXT_shader_replicated_composites
781#ifdef VK_EXT_zero_initialize_device_memory
784#ifdef VK_KHR_shader_expect_assume
787#ifdef VK_KHR_shader_maximal_reconvergence
790#ifdef VK_KHR_maintenance9
793#ifdef VK_KHR_maintenance11
796#ifdef VK_KHR_unified_image_layouts
800#ifdef VK_KHR_video_maintenance2
803#ifdef VK_KHR_internally_synchronized_queues
827#ifdef VK_KHR_video_decode_vp9
830#ifdef VK_KHR_video_encode_av1
866 VkDebugUtilsMessageTypeFlagsEXT messageType,
867 const VkDebugUtilsMessengerCallbackDataEXT *
data,
874 switch (
data->messageIdNumber) {
883 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l =
AV_LOG_VERBOSE;
break;
884 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l =
AV_LOG_INFO;
break;
885 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l =
AV_LOG_WARNING;
break;
886 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: l =
AV_LOG_ERROR;
break;
891 for (
int i = 0;
i <
data->cmdBufLabelCount;
i++)
897#define ADD_VAL_TO_LIST(list, count, val) \
899 list = av_realloc_array(list, ++count, sizeof(*list)); \
901 err = AVERROR(ENOMEM); \
904 list[count - 1] = av_strdup(val); \
905 if (!list[count - 1]) { \
906 err = AVERROR(ENOMEM); \
911#define RELEASE_PROPS(props, count) \
913 for (int i = 0; i < count; i++) \
914 av_free((void *)((props)[i])); \
915 av_free((void *)props); \
921 VkDeviceSize max_vram = 0, max_visible_vram = 0;
925 for (
int i = 0;
i < p->mprops.memoryTypeCount;
i++) {
926 const VkMemoryType
type = p->mprops.memoryTypes[
i];
927 const VkMemoryHeap heap = p->mprops.memoryHeaps[
type.heapIndex];
928 if (!(
type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
930 max_vram =
FFMAX(max_vram, heap.size);
931 if (
type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
932 max_visible_vram =
FFMAX(max_visible_vram, heap.size);
935 return max_vram - max_visible_vram < 1024;
951 const char *
const **
dst, uint32_t *
num,
955 const char **extension_names =
NULL;
959 int err = 0, found, extensions_found = 0;
962 int optional_exts_num;
963 uint32_t sup_ext_count;
964 char *user_exts_str =
NULL;
966 VkExtensionProperties *sup_ext;
976 if (!user_exts_str) {
981 vk->EnumerateInstanceExtensionProperties(
NULL, &sup_ext_count,
NULL);
982 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
985 vk->EnumerateInstanceExtensionProperties(
NULL, &sup_ext_count, sup_ext);
993 if (!user_exts_str) {
998 vk->EnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
999 &sup_ext_count,
NULL);
1000 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
1003 vk->EnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
1004 &sup_ext_count, sup_ext);
1007 for (
int i = 0;
i < optional_exts_num;
i++) {
1008 tstr = optional_exts[
i].
name;
1012 if (!strcmp(tstr, VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME) &&
1020 (!strcmp(tstr, VK_EXT_SHADER_OBJECT_EXTENSION_NAME))) {
1024 for (
int j = 0; j < sup_ext_count; j++) {
1025 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1034 p->vkctx.extensions |= optional_exts[
i].
flag;
1042 tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
1044 for (
int j = 0; j < sup_ext_count; j++) {
1045 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1061#ifdef VK_KHR_shader_relaxed_extended_instruction
1063 tstr = VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME;
1065 for (
int j = 0; j < sup_ext_count; j++) {
1066 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1080 if (user_exts_str) {
1081 char *save, *token =
av_strtok(user_exts_str,
"+", &save);
1084 for (
int j = 0; j < sup_ext_count; j++) {
1085 if (!strcmp(token, sup_ext[j].extensionName)) {
1101 *
dst = extension_names;
1102 *
num = extensions_found;
1116 const char *
const **
dst, uint32_t *
num,
1123 static const char layer_standard_validation[] = {
"VK_LAYER_KHRONOS_validation" };
1124 int layer_standard_validation_found = 0;
1126 uint32_t sup_layer_count;
1127 VkLayerProperties *sup_layers;
1130 char *user_layers_str =
NULL;
1133 const char **enabled_layers =
NULL;
1134 uint32_t enabled_layers_count = 0;
1142 vk->EnumerateInstanceLayerProperties(&sup_layer_count,
NULL);
1143 sup_layers =
av_malloc_array(sup_layer_count,
sizeof(VkLayerProperties));
1146 vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers);
1149 for (
int i = 0;
i < sup_layer_count;
i++)
1153 if (!debug_opt && !user_layers)
1158 if (!strcmp(debug_opt->
value,
"printf")) {
1160 }
else if (!strcmp(debug_opt->
value,
"validate")) {
1162 }
else if (!strcmp(debug_opt->
value,
"practices")) {
1165 char *end_ptr =
NULL;
1166 int idx = strtol(debug_opt->
value, &end_ptr, 10);
1167 if (end_ptr == debug_opt->
value || end_ptr[0] !=
'\0' ||
1182 for (
int i = 0;
i < sup_layer_count;
i++) {
1183 if (!strcmp(layer_standard_validation, sup_layers[
i].layerName)) {
1185 layer_standard_validation);
1186 ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation);
1188 layer_standard_validation_found = 1;
1192 if (!layer_standard_validation_found) {
1194 "Validation Layer \"%s\" not supported\n", layer_standard_validation);
1205 if (!user_layers_str) {
1210 token =
av_strtok(user_layers_str,
"+", &save);
1215 if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) {
1221 for (
int j = 0; j < sup_layer_count; j++) {
1222 if (!strcmp(token, sup_layers[j].layerName)) {
1233 if (!strcmp(layer_standard_validation, token))
1237 "Layer \"%s\" not supported\n", token);
1254 *
dst = enabled_layers;
1255 *
num = enabled_layers_count;
1270 VkApplicationInfo application_info = {
1271 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
1272 .pApplicationName =
"ffmpeg",
1276 .pEngineName =
"libavutil",
1277 .apiVersion = VK_API_VERSION_1_3,
1282 VkValidationFeaturesEXT validation_features = {
1283 .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
1285 VkInstanceCreateInfo inst_props = {
1286 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
1287 .pApplicationInfo = &application_info,
1303 &inst_props.enabledLayerCount, debug_mode);
1309 &inst_props.enabledExtensionCount, *debug_mode);
1317 static const VkValidationFeatureEnableEXT feat_list_validate[] = {
1318 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1319 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1320 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
1322 validation_features.pEnabledValidationFeatures = feat_list_validate;
1323 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_validate);
1324 inst_props.pNext = &validation_features;
1326 static const VkValidationFeatureEnableEXT feat_list_debug[] = {
1327 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1328 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1329 VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
1331 validation_features.pEnabledValidationFeatures = feat_list_debug;
1332 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_debug);
1333 inst_props.pNext = &validation_features;
1335 static const VkValidationFeatureEnableEXT feat_list_practices[] = {
1336 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1337 VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
1339 validation_features.pEnabledValidationFeatures = feat_list_practices;
1340 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_practices);
1341 inst_props.pNext = &validation_features;
1345 for (
int i = 0;
i < inst_props.enabledExtensionCount;
i++) {
1346 if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
1347 inst_props.ppEnabledExtensionNames[
i])) {
1348 inst_props.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
1355 ret = vk->CreateInstance(&inst_props, hwctx->
alloc, &hwctx->
inst);
1358 if (ret != VK_SUCCESS) {
1375 VkDebugUtilsMessengerCreateInfoEXT dbg = {
1376 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
1377 .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
1378 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
1379 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
1380 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
1381 .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
1382 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
1383 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
1388 vk->CreateDebugUtilsMessengerEXT(hwctx->
inst, &dbg,
1389 hwctx->
alloc, &p->debug_ctx);
1395 RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount);
1414 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return "integrated";
1415 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return "discrete";
1416 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
return "virtual";
1417 case VK_PHYSICAL_DEVICE_TYPE_CPU:
return "software";
1418 default:
return "unknown";
1425 int err = 0, choice = -1;
1431 VkPhysicalDevice *devices =
NULL;
1432 VkPhysicalDeviceIDProperties *idp =
NULL;
1433 VkPhysicalDeviceProperties2 *prop =
NULL;
1434 VkPhysicalDeviceDriverProperties *driver_prop =
NULL;
1435 VkPhysicalDeviceDrmPropertiesEXT *drm_prop =
NULL;
1437 ret = vk->EnumeratePhysicalDevices(hwctx->
inst, &
num,
NULL);
1438 if (ret != VK_SUCCESS || !
num) {
1447 ret = vk->EnumeratePhysicalDevices(hwctx->
inst, &
num, devices);
1448 if (ret != VK_SUCCESS) {
1482 for (
int i = 0;
i <
num;
i++) {
1484 drm_prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
1485 driver_prop[
i].pNext = &drm_prop[
i];
1487 driver_prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
1488 idp[
i].pNext = &driver_prop[
i];
1489 idp[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1490 prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1491 prop[
i].pNext = &idp[
i];
1493 vk->GetPhysicalDeviceProperties2(devices[
i], &prop[
i]);
1495 prop[
i].properties.deviceName,
1497 prop[
i].properties.deviceID);
1501 for (
int i = 0;
i <
num;
i++) {
1502 if (!memcmp(idp[
i].deviceUUID, select->
uuid, VK_UUID_SIZE)) {
1511 for (
int i = 0;
i <
num;
i++) {
1512 if ((select->
drm_major == drm_prop[
i].primaryMajor &&
1513 select->
drm_minor == drm_prop[
i].primaryMinor) ||
1514 (select->
drm_major == drm_prop[
i].renderMajor &&
1515 select->
drm_minor == drm_prop[
i].renderMinor)) {
1524 }
else if (select->
name) {
1526 for (
int i = 0;
i <
num;
i++) {
1527 if (strstr(prop[
i].properties.deviceName, select->
name)) {
1538 for (
int i = 0;
i <
num;
i++) {
1539 if (select->
pci_device == prop[
i].properties.deviceID) {
1550 for (
int i = 0;
i <
num;
i++) {
1551 if (select->
vendor_id == prop[
i].properties.vendorID) {
1562 choice = select->
index;
1574 choice, prop[choice].properties.deviceName,
1576 prop[choice].properties.deviceID);
1578 p->props = prop[choice];
1579 p->props.pNext =
NULL;
1580 p->dprops = driver_prop[choice];
1581 p->dprops.pNext =
NULL;
1595 VkQueueFlagBits
flags)
1598 uint32_t min_score = UINT32_MAX;
1600 for (
int i = 0;
i < num_qf;
i++) {
1601 VkQueueFlagBits qflags = qf[
i].queueFamilyProperties.queueFlags;
1604 if ((
flags & VK_QUEUE_TRANSFER_BIT) &&
1605 (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
1606 qflags |= VK_QUEUE_TRANSFER_BIT;
1608 if (qflags &
flags) {
1609 uint32_t score =
av_popcount(qflags) + qf[
i].queueFamilyProperties.timestampValidBits;
1610 if (score < min_score) {
1618 qf[
index].queueFamilyProperties.timestampValidBits++;
1624 VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf,
1625 VkVideoCodecOperationFlagsKHR
flags)
1628 uint32_t min_score = UINT32_MAX;
1630 for (
int i = 0;
i < num_qf;
i++) {
1631 const VkQueueFlags qflags = qf[
i].queueFamilyProperties.queueFlags;
1632 const VkVideoCodecOperationFlagsKHR vflags = qf_vid[
i].videoCodecOperations;
1634 if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR)))
1637 if (vflags &
flags) {
1638 uint32_t score =
av_popcount(vflags) + qf[
i].queueFamilyProperties.timestampValidBits;
1639 if (score < min_score) {
1647 qf[
index].queueFamilyProperties.timestampValidBits++;
1659 VkQueueFamilyProperties2 *qf =
NULL;
1660 VkQueueFamilyVideoPropertiesKHR *qf_vid =
NULL;
1663 vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &
num,
NULL);
1678 for (uint32_t
i = 0;
i <
num;
i++) {
1679 qf_vid[
i] = (VkQueueFamilyVideoPropertiesKHR) {
1680 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
1682 qf[
i] = (VkQueueFamilyProperties2) {
1683 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
1689 vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->
phys_dev, &
num, qf);
1692 for (
int i = 0;
i <
num;
i++) {
1694 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ?
" graphics" :
"",
1695 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ?
" compute" :
"",
1696 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ?
" transfer" :
"",
1697 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ?
" encode" :
"",
1698 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ?
" decode" :
"",
1699 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ?
" sparse" :
"",
1700 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ?
" optical_flow" :
"",
1701 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ?
" protected" :
"",
1702 qf[
i].queueFamilyProperties.queueCount);
1706 qf[
i].queueFamilyProperties.timestampValidBits = 0;
1711#ifdef VK_KHR_internally_synchronized_queues
1713 hwctx->
queue_flags |= VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR;
1717#define PICK_QF(type, vid_op) \
1723 idx = pick_video_queue_family(qf, qf_vid, num, vid_op); \
1725 idx = pick_queue_family(qf, num, type); \
1730 for (i = 0; i < hwctx->nb_qf; i++) { \
1731 if (hwctx->qf[i].idx == idx) { \
1732 hwctx->qf[i].flags |= type; \
1733 hwctx->qf[i].video_caps |= vid_op; \
1737 if (i == hwctx->nb_qf) { \
1738 hwctx->qf[i].idx = idx; \
1739 hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \
1740 if (p->limit_queues || \
1741 p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { \
1742 int max = p->limit_queues; \
1743 if (type == VK_QUEUE_GRAPHICS_BIT) \
1744 hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, \
1747 hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, max); \
1749 hwctx->qf[i].flags = type; \
1750 hwctx->qf[i].video_caps = vid_op; \
1755 PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1756 PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1757 PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1759 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR);
1760 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
1762 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR);
1763 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
1765#ifdef VK_KHR_video_decode_vp9
1766 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR);
1769#ifdef VK_KHR_video_encode_av1
1770 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR);
1772 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
1775 PICK_QF(VK_QUEUE_OPTICAL_FLOW_BIT_NV, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1783 sizeof(VkDeviceQueueCreateInfo));
1784 if (!cd->pQueueCreateInfos)
1787 for (uint32_t
i = 0;
i < hwctx->
nb_qf;
i++) {
1790 VkDeviceQueueCreateInfo *pc;
1791 for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) {
1792 if (hwctx->
qf[
i].
idx == cd->pQueueCreateInfos[j].queueFamilyIndex) {
1802 for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++)
1803 av_free((
void *)cd->pQueueCreateInfos[
i].pQueuePriorities);
1804 av_free((
void *)cd->pQueueCreateInfos);
1808 for (uint32_t j = 0; j < hwctx->
qf[
i].
num; j++)
1811 pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
1812 pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) {
1813 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1815 .queueFamilyIndex = hwctx->
qf[
i].
idx,
1816 .queueCount = hwctx->
qf[
i].
num,
1839 vk->DestroyDebugUtilsMessengerEXT(hwctx->
inst, p->debug_ctx,
1843 vk->DestroyInstance(hwctx->
inst, hwctx->
alloc);
1846 dlclose(p->libvulkan);
1857 for (uint32_t
i = 0;
i < p->nb_tot_qfs;
i++) {
1869 int disable_multiplane,
1880 VkDeviceCreateInfo dev_info = {
1881 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1893 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
1897 &dev_info.enabledExtensionCount, debug_mode))) {
1898 for (
int i = 0;
i < dev_info.queueCreateInfoCount;
i++)
1899 av_free((
void *)dev_info.pQueueCreateInfos[
i].pQueuePriorities);
1900 av_free((
void *)dev_info.pQueueCreateInfos);
1906 vk->GetPhysicalDeviceFeatures2(hwctx->
phys_dev, &supported_feats.
device);
1911 dev_info.pNext = p->feats.device.pNext;
1912 dev_info.pEnabledFeatures = &p->feats.device.features;
1917 p->limit_queues = strtol(opt_d->
value,
NULL, 10);
1924 ret = vk->CreateDevice(hwctx->
phys_dev, &dev_info, hwctx->
alloc,
1927 for (
int i = 0;
i < dev_info.queueCreateInfoCount;
i++)
1928 av_free((
void *)dev_info.pQueueCreateInfos[
i].pQueuePriorities);
1929 av_free((
void *)dev_info.pQueueCreateInfos);
1931 if (ret != VK_SUCCESS) {
1934 for (
int i = 0;
i < dev_info.enabledExtensionCount;
i++)
1935 av_free((
void *)dev_info.ppEnabledExtensionNames[
i]);
1936 av_free((
void *)dev_info.ppEnabledExtensionNames);
1944 p->use_linear_images = strtol(opt_d->
value,
NULL, 10);
1947 p->disable_multiplane = disable_multiplane;
1948 if (!p->disable_multiplane) {
1951 p->disable_multiplane = strtol(opt_d->
value,
NULL, 10);
1955 p->avoid_host_import = p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
1958 p->avoid_host_import = strtol(opt_d->
value,
NULL, 10);
1995 VkQueueFamilyProperties2 *qf;
1996 VkQueueFamilyVideoPropertiesKHR *qf_vid;
1997 VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info;
2016 p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2017 p->props.pNext = &p->hprops;
2018 p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
2019 p->hprops.pNext = &p->dprops;
2020 p->dprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
2022 vk->GetPhysicalDeviceProperties2(hwctx->
phys_dev, &p->props);
2024 p->props.properties.deviceName);
2027 p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
2029 p->props.properties.limits.minMemoryMapAlignment);
2031 p->props.properties.limits.nonCoherentAtomSize);
2034 p->hprops.minImportedHostPointerAlignment);
2036 vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &qf_num,
NULL);
2042 ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) {
2043 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
2047 ext_sem_props_info.handleType =
2049 IsWindows8OrGreater()
2050 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
2051 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
2053 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
2055 p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
2056 vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->
phys_dev,
2057 &ext_sem_props_info,
2058 &p->ext_sem_props_opaque);
2064 qf_vid =
av_malloc_array(qf_num,
sizeof(VkQueueFamilyVideoPropertiesKHR));
2070 for (uint32_t
i = 0;
i < qf_num;
i++) {
2071 qf_vid[
i] = (VkQueueFamilyVideoPropertiesKHR) {
2072 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
2074 qf[
i] = (VkQueueFamilyProperties2) {
2075 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
2080 vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->
phys_dev, &qf_num, qf);
2082 p->nb_tot_qfs = qf_num;
2085 p->qf_mutex =
av_calloc(qf_num,
sizeof(*p->qf_mutex));
2091 for (uint32_t
i = 0;
i < qf_num;
i++) {
2092 p->qf_mutex[
i] =
av_calloc(qf[
i].queueFamilyProperties.queueCount,
2093 sizeof(**p->qf_mutex));
2094 if (!p->qf_mutex[
i]) {
2098 for (uint32_t j = 0; j < qf[
i].queueFamilyProperties.queueCount; j++) {
2110 for (
int i = 0;
i < hwctx->
nb_qf;
i++) {
2112 hwctx->
qf[
i].
flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
2113 VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
2120 for (
int i = 0;
i < hwctx->
nb_qf;
i++) {
2124 for (
int j = (
i - 1); j >= 0; j--) {
2131 p->img_qfs[p->nb_img_qfs++] = hwctx->
qf[
i].
idx;
2134#if FF_API_VULKAN_SYNC_QUEUES
2136 if (!hwctx->lock_queue)
2138 if (!hwctx->unlock_queue)
2144 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
2146 p->vkctx.device =
ctx;
2147 p->vkctx.hwctx = hwctx;
2150 p->compute_qf =
ff_vk_qf_find(&p->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
2151 p->transfer_qf =
ff_vk_qf_find(&p->vkctx, VK_QUEUE_TRANSFER_BIT, 0);
2154 p->transfer_offset_align = 1;
2155 if (p->transfer_qf) {
2156 VkQueueFlags
flags = p->vkctx.qf_props[p->transfer_qf->idx].queueFamilyProperties.queueFlags;
2157 if (!(
flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
2158 p->transfer_offset_align = 4;
2160#ifdef VK_KHR_maintenance11
2161 if (p->vkctx.maintenance_11_feats.maintenance11)
2162 p->transfer_offset_align = 1;
2166 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
2178 if (device && device[0]) {
2184 dev_select.
index = strtol(device, &end, 10);
2185 if (end == device || *end) {
2186 dev_select.
index = 0;
2187 dev_select.
name = device;
2204 switch(src_ctx->
type) {
2208 VADisplay dpy = src_hwctx->
display;
2209#if VA_CHECK_VERSION(1, 15, 0)
2211 VADisplayAttribute attr = {
2212 .type = VADisplayPCIID,
2217#if VA_CHECK_VERSION(1, 15, 0)
2218 vas = vaGetDisplayAttributes(dpy, &attr, 1);
2219 if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED)
2220 dev_select.pci_device = (attr.value & 0xFFFF);
2223 if (!dev_select.pci_device) {
2224 vendor = vaQueryVendorString(dpy);
2230 if (strstr(vendor,
"AMD"))
2231 dev_select.vendor_id = 0x1002;
2240 struct stat drm_node_info;
2241 drmDevice *drm_dev_info;
2244 err = fstat(src_hwctx->
fd, &drm_node_info);
2251 dev_select.drm_major = major(drm_node_info.st_dev);
2252 dev_select.drm_minor = minor(drm_node_info.st_dev);
2253 dev_select.has_drm = 1;
2255 err = drmGetDevice(src_hwctx->
fd, &drm_dev_info);
2262 if (drm_dev_info->bustype == DRM_BUS_PCI)
2263 dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
2265 drmFreeDevice(&drm_dev_info);
2275 CudaFunctions *cu = cu_internal->
cuda_dl;
2277 int ret =
CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
2284 dev_select.has_uuid = 1;
2299 const void *hwconfig,
2307 p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2308 VK_IMAGE_TILING_OPTIMAL,
2320 p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2321 VK_IMAGE_TILING_OPTIMAL,
2335 constraints->
max_width = p->props.properties.limits.maxImageDimension2D;
2336 constraints->
max_height = p->props.properties.limits.maxImageDimension2D;
2349 VkMemoryPropertyFlagBits req_flags,
const void *alloc_extension,
2350 VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
2357 VkMemoryAllocateInfo alloc_info = {
2358 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2359 .pNext = alloc_extension,
2360 .allocationSize = req->size,
2365 for (
int i = 0;
i < p->mprops.memoryTypeCount;
i++) {
2366 const VkMemoryType *
type = &p->mprops.memoryTypes[
i];
2369 if (!(req->memoryTypeBits & (1 <<
i)))
2373 if ((
type->propertyFlags & req_flags) != req_flags)
2377 if (req->size > p->mprops.memoryHeaps[
type->heapIndex].size)
2391 alloc_info.memoryTypeIndex =
index;
2393 ret = vk->AllocateMemory(dev_hwctx->
act_dev, &alloc_info,
2394 dev_hwctx->
alloc, mem);
2395 if (ret != VK_SUCCESS) {
2401 *mem_flags |= p->mprops.memoryTypes[
index].propertyFlags;
2415 if (internal->cuda_fc_ref) {
2421 CudaFunctions *cu = cu_internal->
cuda_dl;
2424 if (internal->cu_sem[
i])
2425 CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[
i]));
2426 if (internal->cu_mma[
i])
2427 CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[
i]));
2428 if (internal->ext_mem[
i])
2429 CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[
i]));
2431 if (internal->ext_sem_handle[
i])
2432 CloseHandle(internal->ext_sem_handle[
i]);
2433 if (internal->ext_mem_handle[
i])
2434 CloseHandle(internal->ext_mem_handle[
i]);
2442 if (internal->drm_sync_sem != VK_NULL_HANDLE)
2443 p->vkctx.vkfn.DestroySemaphore(p->p.act_dev, internal->drm_sync_sem,
2463 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
2465 .pSemaphores =
f->sem,
2466 .pValues =
f->sem_value,
2467 .semaphoreCount = nb_sems,
2475 for (
int i = 0;
i < nb_images;
i++) {
2490 void *alloc_pnext,
size_t alloc_pnext_stride)
2492 int img_cnt = 0, err;
2500 while (
f->img[img_cnt]) {
2502 VkImageMemoryRequirementsInfo2 req_desc = {
2503 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2504 .image =
f->img[img_cnt],
2506 VkMemoryDedicatedAllocateInfo ded_alloc = {
2507 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
2508 .pNext = (
void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride),
2510 VkMemoryDedicatedRequirements ded_req = {
2511 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
2513 VkMemoryRequirements2 req = {
2514 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
2518 vk->GetImageMemoryRequirements2(hwctx->
act_dev, &req_desc, &req);
2521 "plane %d: driver reports prefersDedicatedAllocation=%i requiresDedicatedAllocation=%i\n",
2522 img_cnt, ded_req.prefersDedicatedAllocation, ded_req.requiresDedicatedAllocation);
2524 if (
f->tiling == VK_IMAGE_TILING_LINEAR)
2525 req.memoryRequirements.size =
FFALIGN(req.memoryRequirements.size,
2526 p->props.properties.limits.minMemoryMapAlignment);
2529 use_ded_mem = ded_req.prefersDedicatedAllocation |
2530 ded_req.requiresDedicatedAllocation;
2534 ded_alloc.image =
f->img[img_cnt];
2538 f->tiling == VK_IMAGE_TILING_LINEAR ?
2539 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
2540 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
2541 use_ded_mem ? &ded_alloc : (
void *)ded_alloc.pNext,
2542 &
f->flags, &
f->mem[img_cnt])))
2545 f->size[img_cnt] = req.memoryRequirements.size;
2546 bind_info[img_cnt].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
2547 bind_info[img_cnt].image =
f->img[img_cnt];
2548 bind_info[img_cnt].memory =
f->mem[img_cnt];
2554 ret = vk->BindImageMemory2(hwctx->
act_dev, img_cnt, bind_info);
2555 if (ret != VK_SUCCESS) {
2575 VkAccessFlags2 *new_access)
2579 *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2580 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2583 *new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2584 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2587 *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2588 *new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
2591 *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2592 *new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
2595 *new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR;
2596 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2599 *new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
2600 *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2603 *new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
2604 *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2618 VkImageLayout new_layout;
2619 VkAccessFlags2 new_access;
2622 uint32_t dst_qf = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2623 VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE;
2625 dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR;
2626 src_stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
2633 .data = (uint8_t *)hwfc,
2636 .data[0] = (uint8_t *)
frame,
2637 .hw_frames_ctx = &tmp_ref,
2640 VkCommandBuffer cmd_buf;
2642 cmd_buf = exec->
buf;
2648 VK_PIPELINE_STAGE_2_NONE,
2649 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
2655 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
2656 new_access, new_layout, dst_qf);
2658 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
2659 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2660 .pImageMemoryBarriers = img_bar,
2661 .imageMemoryBarrierCount = nb_img_bar,
2683 VkImageLayout new_layout;
2684 VkAccessFlags2 new_access;
2688 for (
i = 0;
i < p->vkctx.host_image_props.copyDstLayoutCount;
i++) {
2689 if (p->vkctx.host_image_props.pCopyDstLayouts[
i] == new_layout)
2692 if (
i == p->vkctx.host_image_props.copyDstLayoutCount)
2695 for (
i = 0;
i < nb_images;
i++) {
2696 layout_change[
i] = (VkHostImageLayoutTransitionInfoEXT) {
2697 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
2699 .oldLayout =
frame->layout[
i],
2700 .newLayout = new_layout,
2701 .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2702 .subresourceRange.layerCount = 1,
2703 .subresourceRange.levelCount = 1,
2705 frame->layout[
i] = new_layout;
2708 ret = vk->TransitionImageLayoutEXT(p->vkctx.hwctx->act_dev,
2709 nb_images, layout_change);
2710 if (ret != VK_SUCCESS) {
2724 if (hwfc_vk->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
2736 int frame_w,
int frame_h,
int plane)
2753 VkImageTiling tiling, VkImageUsageFlagBits
usage,
2754 VkImageCreateFlags
flags,
int nb_layers,
2766 VkSemaphoreTypeCreateInfo sem_type_info = {
2767 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
2768 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
2771 VkSemaphoreCreateInfo sem_spawn = {
2772 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
2773 .pNext = &sem_type_info,
2776 VkExportSemaphoreCreateInfo ext_sem_info_opaque = {
2777 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
2779 .handleTypes = IsWindows8OrGreater()
2780 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
2781 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
2783 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
2788 if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) {
2802 for (
int i = 0; (hwfc_vk->
format[
i] != VK_FORMAT_UNDEFINED);
i++) {
2803 VkImageCreateInfo create_info = {
2804 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2805 .pNext = create_pnext,
2806 .imageType = VK_IMAGE_TYPE_2D,
2810 .arrayLayers = nb_layers,
2813 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
2815 .samples = VK_SAMPLE_COUNT_1_BIT,
2816 .pQueueFamilyIndices = p->img_qfs,
2817 .queueFamilyIndexCount = p->nb_img_qfs,
2818 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2819 VK_SHARING_MODE_EXCLUSIVE,
2822 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
2825 ret = vk->CreateImage(hwctx->
act_dev, &create_info,
2827 if (ret != VK_SUCCESS) {
2835 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_spawn,
2837 if (ret != VK_SUCCESS) {
2844 f->queue_family[
i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2845 f->layout[
i] = create_info.initialLayout;
2847 f->sem_value[
i] = 0;
2863 VkExternalMemoryHandleTypeFlags *comp_handle_types,
2864 VkExternalMemoryHandleTypeFlags *iexp,
2865 VkExternalMemoryHandleTypeFlagBits
exp)
2873 const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info =
2875 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
2876 int has_mods = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info;
2879 VkExternalImageFormatProperties eprops = {
2880 .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
2882 VkImageFormatProperties2 props = {
2883 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
2886 VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
2887 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
2889 .pQueueFamilyIndices = p->img_qfs,
2890 .queueFamilyIndexCount = p->nb_img_qfs,
2891 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2892 VK_SHARING_MODE_EXCLUSIVE,
2894 VkPhysicalDeviceExternalImageFormatInfo enext = {
2895 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
2897 .pNext = has_mods ? &phy_dev_mod_info :
NULL,
2899 VkPhysicalDeviceImageFormatInfo2 pinfo = {
2900 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
2901 .pNext = !
exp ?
NULL : &enext,
2902 .format = hwctx->
format[0],
2903 .type = VK_IMAGE_TYPE_2D,
2905 .usage = hwctx->
usage,
2906 .flags = (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && has_mods) ?
2910 nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
2911 for (
int i = 0;
i < nb_mods;
i++) {
2913 phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[
i];
2915 ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->
phys_dev,
2919 av_log(hwfc,
AV_LOG_VERBOSE,
"GetPhysicalDeviceImageFormatProperties2: mod[%d]=0x%llx -> %s\n",
2920 i, (
unsigned long long)phy_dev_mod_info.drmFormatModifier,
2921 ret == VK_SUCCESS ?
"OK" :
"FAIL");
2922 if (ret == VK_SUCCESS) {
2924 *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
2925 if (
exp == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
2928 VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
2936 VkExternalMemoryHandleTypeFlags *comp_handle_types,
2937 VkExternalMemoryHandleTypeFlags *export_types)
2942 *comp_handle_types = 0x0;
2943 *export_types = 0x0;
2947 try_export_flags(hwfc, comp_handle_types, export_types, IsWindows8OrGreater()
2948 ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
2949 : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
2952 (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
2954 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
2957 hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
2959 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2971 VkExternalMemoryHandleTypeFlags e;
2974 VkExternalMemoryImageCreateInfo eiinfo = {
2975 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
2982 eminfo[
i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
2984 eminfo[
i].handleTypes = e;
2991 av_log(hwfc,
AV_LOG_ERROR,
"vulkan_pool_alloc failed: create_frame failed: %d\n", err);
2999 if ( (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
3000 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))
3002 else if (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)
3004 else if (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)
3006 else if (hwctx->
usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
3073 if (p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
3076 "NVIDIA drivers mishandle multi-plane images\n");
3080 const VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
3082 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
3083 int has_mods = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
3084 mod_list && mod_list->drmFormatModifierCount;
3085 int nb_mods = has_mods ? mod_list->drmFormatModifierCount : 1;
3088 if (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && !has_mods)
3091 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
3092 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
3093 .pQueueFamilyIndices = p->img_qfs,
3094 .queueFamilyIndexCount = p->nb_img_qfs,
3095 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3096 VK_SHARING_MODE_EXCLUSIVE,
3098 VkPhysicalDeviceImageFormatInfo2 pinfo = {
3099 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3100 .type = VK_IMAGE_TYPE_2D,
3102 .usage = hwctx->
usage,
3109 VkVideoProfileListInfoKHR profile_list;
3110 const VkVideoProfileListInfoKHR *pl =
3112 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
3115 profile_list.pNext =
NULL;
3119 VkImageFormatListCreateInfo format_list;
3120 const VkImageFormatListCreateInfo *fl =
3122 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
3125 format_list.pNext =
NULL;
3132 hwctx->
format[
i] != VK_FORMAT_UNDEFINED;
i++) {
3133 pinfo.format = hwctx->
format[
i];
3137 for (
int j = 0; j < nb_mods; j++) {
3138 VkHostImageCopyDevicePerformanceQueryEXT perf = {
3139 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT,
3141 VkImageFormatProperties2 props = {
3142 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3147 mod_info.drmFormatModifier = mod_list->pDrmFormatModifiers[j];
3149 ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->
phys_dev,
3151 if (ret != VK_SUCCESS) {
3153 "format %i is not supported: %s\n",
3158 if (!perf.optimalDeviceAccess) {
3160 "format %i has no optimal device access (identical "
3161 "memory layout: %i)\n",
3162 pinfo.format, perf.identicalMemoryLayout);
3168 if (!p->vkctx.host_image_props.identicalMemoryTypeRequirements) {
3170 VkExternalMemoryHandleTypeFlags e;
3171 VkExternalMemoryImageCreateInfo eiinfo = {
3172 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
3176 VkImageCreateInfo create_info = {
3177 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3178 .pNext = eiinfo.handleTypes ? &eiinfo : hwctx->
create_pnext,
3179 .imageType = VK_IMAGE_TYPE_2D,
3180 .format = hwctx->
format[0],
3186 .usage = hwctx->
usage,
3187 .samples = VK_SAMPLE_COUNT_1_BIT,
3188 .pQueueFamilyIndices = p->img_qfs,
3189 .queueFamilyIndexCount = p->nb_img_qfs,
3190 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3191 VK_SHARING_MODE_EXCLUSIVE,
3193 VkDeviceImageMemoryRequirements req_info = {
3194 .sType = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS,
3195 .pCreateInfo = &create_info,
3196 .planeAspect = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ?
3197 VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : 0,
3199 VkMemoryRequirements2 req = {
3200 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
3203 vk->GetDeviceImageMemoryRequirements(dev_hwctx->
act_dev, &req_info, &req);
3205 VkMemoryPropertyFlags req_flags = hwctx->
tiling == VK_IMAGE_TILING_LINEAR ?
3206 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
3207 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
3209 if (!(req.memoryRequirements.memoryTypeBits & (1U <<
index)))
3211 if ((p->mprops.memoryTypes[
index].propertyFlags & req_flags) == req_flags)
3214 if (
index == p->mprops.memoryTypeCount) {
3216 "no compatible memory type\n");
3232 VkImageUsageFlags supported_usage;
3236 int disable_multiplane = p->disable_multiplane ||
3238 int is_lone_dpb = ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) ||
3239 ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
3240 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)));
3247 if (p->use_linear_images &&
3248 (hwctx->
tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
3249 hwctx->
tiling = VK_IMAGE_TILING_LINEAR;
3261 if ((hwfc->
width & ((1 <<
desc->log2_chroma_w) - 1)) ||
3262 (hwfc->
height & ((1 <<
desc->log2_chroma_h) - 1)))
3263 disable_multiplane = 1;
3265 if (hwctx->
format[0] != VK_FORMAT_UNDEFINED) {
3270 "for the current sw_format %s!\n",
3282 (hwctx->
usage & VK_IMAGE_USAGE_STORAGE_BIT));
3291 NULL, &supported_usage,
3294 (hwctx->
usage & VK_IMAGE_USAGE_STORAGE_BIT));
3303 int drm_mod_with_video = (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
3305 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR));
3307 if (!is_lone_dpb && !drm_mod_with_video) {
3309 hwctx->
usage |= supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
3310 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3311 VK_IMAGE_USAGE_STORAGE_BIT |
3312 VK_IMAGE_USAGE_SAMPLED_BIT);
3320 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR))
3321 hwctx->
usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
3324 if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3327 hwctx->
usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
3333 int sampleable = hwctx->
usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
3334 VK_IMAGE_USAGE_STORAGE_BIT);
3335 hwctx->
img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
3337 hwctx->
img_flags |= VK_IMAGE_CREATE_ALIAS_BIT;
3339 hwctx->
img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
3348 if ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3351 const VkVideoProfileListInfoKHR *pl;
3354 hwctx->
img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3357 for (
i = 0;
i < pl->profileCount;
i++) {
3359 if (pl->pProfiles[
i].videoCodecOperation & 0xFFFF0000)
3362 if (
i == pl->profileCount)
3363 hwctx->
img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3368 if ((hwctx->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) &&
3370 hwctx->
usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
3401 VkImageDrmFormatModifierPropertiesEXT drm_mod = {
3402 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
3404 err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->
act_dev,
f->img[0],
3406 if (err != VK_SUCCESS) {
3412 VkDrmFormatModifierPropertiesListEXT modp;
3413 VkFormatProperties2 fmtp;
3414 VkDrmFormatModifierPropertiesEXT *mod_props =
NULL;
3416 modp = (VkDrmFormatModifierPropertiesListEXT) {
3417 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
3419 fmtp = (VkFormatProperties2) {
3420 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
3425 vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->
phys_dev, fmt->
fallback[
i], &fmtp);
3427 modp.pDrmFormatModifierProperties =
3428 av_calloc(modp.drmFormatModifierCount,
sizeof(*modp.pDrmFormatModifierProperties));
3429 if (!modp.pDrmFormatModifierProperties) {
3433 vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->
phys_dev, fmt->
fallback[
i], &fmtp);
3435 for (uint32_t j = 0; j < modp.drmFormatModifierCount; ++j) {
3436 VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[j];
3437 if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
3443 if (mod_props ==
NULL) {
3444 av_log(hwfc,
AV_LOG_ERROR,
"No DRM format modifier properties found for modifier 0x%016"PRIx64
"\n",
3445 drm_mod.drmFormatModifier);
3446 av_free(modp.pDrmFormatModifierProperties);
3452 av_free(modp.pDrmFormatModifierProperties);
3516static const struct {
3517 uint32_t drm_fourcc;
3519} vulkan_drm_format_map[] = {
3520 { DRM_FORMAT_R8, VK_FORMAT_R8_UNORM },
3521 { DRM_FORMAT_R16, VK_FORMAT_R16_UNORM },
3522 { DRM_FORMAT_GR88, VK_FORMAT_R8G8_UNORM },
3523 { DRM_FORMAT_RG88, VK_FORMAT_R8G8_UNORM },
3524 { DRM_FORMAT_GR1616, VK_FORMAT_R16G16_UNORM },
3525 { DRM_FORMAT_RG1616, VK_FORMAT_R16G16_UNORM },
3526 { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3527 { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3528 { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3529 { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3530 { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3531 { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3532 { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3533 { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3536#ifdef DRM_FORMAT_XYUV8888
3537 { DRM_FORMAT_XYUV8888, VK_FORMAT_R8G8B8A8_UNORM },
3538 { DRM_FORMAT_XVYU2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 } ,
3539 { DRM_FORMAT_XVYU12_16161616, VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 } ,
3540 { DRM_FORMAT_XVYU16161616, VK_FORMAT_R16G16B16A16_UNORM } ,
3544static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
3547 if (vulkan_drm_format_map[
i].drm_fourcc == drm_fourcc)
3548 return vulkan_drm_format_map[
i].vk_format;
3549 return VK_FORMAT_UNDEFINED;
3558 int bind_counts = 0;
3567 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3568 if (drm_to_vulkan_fmt(
desc->layers[
i].format) == VK_FORMAT_UNDEFINED) {
3570 desc->layers[
i].format);
3581 f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
3583 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3587 VkSemaphoreTypeCreateInfo sem_type_info = {
3588 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3589 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
3592 VkSemaphoreCreateInfo sem_spawn = {
3593 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3594 .pNext = &sem_type_info,
3599 VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = {
3600 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
3601 .drmFormatModifier =
desc->objects[0].format_modifier,
3602 .drmFormatModifierPlaneCount =
planes,
3603 .pPlaneLayouts = (
const VkSubresourceLayout *)&ext_img_layouts,
3605 VkExternalMemoryImageCreateInfo ext_img_spec = {
3606 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
3607 .pNext = &ext_img_mod_spec,
3608 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3610 VkImageCreateInfo create_info = {
3611 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3612 .pNext = &ext_img_spec,
3613 .imageType = VK_IMAGE_TYPE_2D,
3614 .format = drm_to_vulkan_fmt(
desc->layers[
i].format),
3619 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
3620 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
3622 .samples = VK_SAMPLE_COUNT_1_BIT,
3623 .pQueueFamilyIndices =
p->img_qfs,
3624 .queueFamilyIndexCount =
p->nb_img_qfs,
3625 .sharingMode =
p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3626 VK_SHARING_MODE_EXCLUSIVE,
3637 if (sw_vkfmts && sw_vkfmts[
i] != VK_FORMAT_UNDEFINED)
3638 create_info.format = sw_vkfmts[
i];
3642 VkExternalImageFormatProperties ext_props = {
3643 .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
3645 VkImageFormatProperties2 props_ret = {
3646 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3647 .pNext = &ext_props,
3649 VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = {
3650 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
3651 .drmFormatModifier = ext_img_mod_spec.drmFormatModifier,
3652 .pQueueFamilyIndices = create_info.pQueueFamilyIndices,
3653 .queueFamilyIndexCount = create_info.queueFamilyIndexCount,
3654 .sharingMode = create_info.sharingMode,
3656 VkPhysicalDeviceExternalImageFormatInfo props_ext = {
3657 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3658 .pNext = &props_drm_mod,
3659 .handleType = ext_img_spec.handleTypes,
3661 VkPhysicalDeviceImageFormatInfo2 fmt_props;
3664 create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT |
3665 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3667 create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT |
3668 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3670 fmt_props = (VkPhysicalDeviceImageFormatInfo2) {
3671 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3672 .pNext = &props_ext,
3673 .format = create_info.format,
3674 .type = create_info.imageType,
3675 .tiling = create_info.tiling,
3676 .usage = create_info.usage,
3677 .flags = create_info.flags,
3681 ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev,
3682 &fmt_props, &props_ret);
3683 if (ret != VK_SUCCESS) {
3691 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
3692 hwfc->sw_format,
src->width,
src->height,
i);
3695 for (
int j = 0; j <
planes; j++) {
3696 ext_img_layouts[j].offset =
desc->layers[
i].planes[j].offset;
3697 ext_img_layouts[j].rowPitch =
desc->layers[
i].planes[j].pitch;
3698 ext_img_layouts[j].size = 0;
3699 ext_img_layouts[j].arrayPitch = 0;
3700 ext_img_layouts[j].depthPitch = 0;
3704 ret = vk->CreateImage(hwctx->act_dev, &create_info,
3705 hwctx->alloc, &
f->img[
i]);
3706 if (ret != VK_SUCCESS) {
3713 ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
3714 hwctx->alloc, &
f->sem[
i]);
3715 if (ret != VK_SUCCESS) {
3722 f->queue_family[
i] = VK_QUEUE_FAMILY_EXTERNAL;
3723 f->layout[
i] = create_info.initialLayout;
3725 f->sem_value[
i] = 0;
3728 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3730 VkImageMemoryRequirementsInfo2 req_desc = {
3731 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
3734 VkMemoryDedicatedRequirements ded_req = {
3735 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
3737 VkMemoryRequirements2 req2 = {
3738 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
3743 VkMemoryFdPropertiesKHR fdmp = {
3744 .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
3750 VkImportMemoryFdInfoKHR idesc = {
3751 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
3752 .fd = dup(
desc->objects[
desc->layers[
i].planes[0].object_index].fd),
3753 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3755 VkMemoryDedicatedAllocateInfo ded_alloc = {
3756 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
3758 .image = req_desc.image,
3762 ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev,
3763 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3765 if (ret != VK_SUCCESS) {
3773 vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2);
3776 req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits;
3779 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
3780 (ded_req.prefersDedicatedAllocation ||
3781 ded_req.requiresDedicatedAllocation) ?
3782 &ded_alloc : ded_alloc.pNext,
3783 &
f->flags, &
f->mem[
i]);
3789 f->size[
i] = req2.memoryRequirements.size;
3792 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3794 for (
int j = 0; j <
planes; j++) {
3795 VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
3796 j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
3797 VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
3799 plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
3801 plane_info[bind_counts].planeAspect = aspect;
3803 bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
3805 bind_info[bind_counts].image =
f->img[
i];
3806 bind_info[bind_counts].memory =
f->mem[
i];
3809 bind_info[bind_counts].memoryOffset = 0;
3816 ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
3817 if (ret != VK_SUCCESS) {
3845#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
3847 VkCommandBuffer cmd_buf;
3853 for (
int i = 0;
i <
desc->nb_objects;
i++) {
3854 VkSemaphoreTypeCreateInfo sem_type_info = {
3855 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3856 .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
3858 VkSemaphoreCreateInfo sem_spawn = {
3859 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3860 .pNext = &sem_type_info,
3862 VkImportSemaphoreFdInfoKHR import_info;
3863 struct dma_buf_export_sync_file implicit_fd_info = {
3864 .flags = DMA_BUF_SYNC_READ,
3868 if (ioctl(
desc->objects[
i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
3869 &implicit_fd_info)) {
3874 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3878 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_spawn,
3879 hwctx->
alloc, &drm_sync_sem[
i]);
3880 if (ret != VK_SUCCESS) {
3885 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3889 import_info = (VkImportSemaphoreFdInfoKHR) {
3890 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
3891 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
3892 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
3893 .semaphore = drm_sync_sem[
i],
3894 .fd = implicit_fd_info.fd,
3897 ret = vk->ImportSemaphoreFdKHR(hwctx->
act_dev, &import_info);
3898 if (ret != VK_SUCCESS) {
3903 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3909 cmd_buf = exec->
buf;
3913 for (
int i = 0;
i <
desc->nb_objects;
i++)
3914 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3920 drm_sync_sem,
desc->nb_objects,
3921 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 1);
3924 VK_PIPELINE_STAGE_2_NONE,
3925 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
3932 VK_PIPELINE_STAGE_2_NONE,
3933 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
3935 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : 0x0) |
3937 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT : 0x0),
3938 VK_IMAGE_LAYOUT_GENERAL,
3939 p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED :
p->img_qfs[0]);
3941 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
3942 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
3943 .pImageMemoryBarriers = img_bar,
3944 .imageMemoryBarrierCount = nb_img_bar,
3955 "image may be corrupted.\n");
3971 if ((err = vulkan_map_from_drm_frame_desc(hwfc, &
f,
src,
flags)))
3975 dst->data[0] = (uint8_t *)
f;
3977 dst->height =
src->height;
3980 &vulkan_unmap_from_drm,
f);
3984 err = vulkan_map_from_drm_frame_sync(hwfc,
dst,
desc,
flags);
4007 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
4013 vaSyncSurface(vaapi_ctx->
display, surface_id);
4021 err = vulkan_map_from_drm(dst_fc,
dst,
tmp,
flags);
4038 VkDeviceMemory mem,
size_t size)
4046 CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
4047 .type = IsWindows8OrGreater()
4048 ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
4049 : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
4052 VkMemoryGetWin32HandleInfoKHR export_info = {
4053 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
4055 .handleType = IsWindows8OrGreater()
4056 ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4057 : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
4060 ret = vk->GetMemoryWin32HandleKHR(hwctx->
act_dev, &export_info,
4061 &ext_desc.handle.win32.handle);
4062 if (ret != VK_SUCCESS) {
4067 dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
4069 CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
4070 .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
4073 VkMemoryGetFdInfoKHR export_info = {
4074 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
4076 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
4079 ret = vk->GetMemoryFdKHR(hwctx->
act_dev, &export_info,
4080 &ext_desc.handle.fd);
4081 if (ret != VK_SUCCESS) {
4088 ret =
CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
4091 close(ext_desc.handle.fd);
4110 VkSemaphoreGetWin32HandleInfoKHR sem_export = {
4111 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
4113 .handleType = IsWindows8OrGreater()
4114 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4115 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
4117 CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
4121 VkSemaphoreGetFdInfoKHR sem_export = {
4122 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
4124 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
4126 CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
4132 ret = vk->GetSemaphoreWin32HandleKHR(hwctx->
act_dev, &sem_export,
4133 &ext_sem_desc.handle.win32.handle);
4135 ret = vk->GetSemaphoreFdKHR(hwctx->
act_dev, &sem_export,
4136 &ext_sem_desc.handle.fd);
4138 if (ret != VK_SUCCESS) {
4144 dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
4147 ret =
CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
4151 close(ext_sem_desc.handle.fd);
4179 CudaFunctions *cu = cu_internal->
cuda_dl;
4180 CUarray_format cufmt =
desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
4181 CU_AD_FORMAT_UNSIGNED_INT8;
4182 const int elem_size = 1 + (
desc->comp[0].depth > 8);
4185 dst_int = dst_f->internal;
4187 if (!dst_int->cuda_fc_ref) {
4191 if (!dst_int->cuda_fc_ref)
4195 for (
int i = 0;
i < nb_images;
i++) {
4196 err = export_mem_to_cuda(
ctx, cuda_cu, cu, dst_int,
i,
4197 dst_f->mem[
i], dst_f->size[
i]);
4201 err = export_sem_to_cuda(
ctx, cuda_cu, cu, dst_int,
i,
4207 if (nb_images !=
planes) {
4211 if (
desc->comp[
i].step / elem_size > 1) {
4213 "Cannot map a multiplane Vulkan image (%d image(s) "
4214 "for %d plane(s)) to CUDA; create the Vulkan device "
4215 "with the disable_multiplane=1 option (one image per "
4216 "plane) for CUDA interop.\n", nb_images,
planes);
4221 VkImageSubresource subres = {
4222 .aspectMask =
i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
4223 i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
4224 VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
4226 VkSubresourceLayout
layout = { 0 };
4227 vk->GetImageSubresourceLayout(hwctx->
act_dev, dst_f->img[
FFMIN(
i, nb_images - 1)],
4234 CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
4239 .NumChannels =
desc->comp[
i].step / elem_size,
4247 tex_desc.arrayDesc.Width = p_w;
4248 tex_desc.arrayDesc.Height = p_h;
4250 ret =
CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[
i],
4251 dst_int->ext_mem[
FFMIN(
i, nb_images - 1)],
4258 ret =
CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[
i],
4259 dst_int->cu_mma[
i], 0));
4292 CudaFunctions *cu = cu_internal->
cuda_dl;
4303 err =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
4307 err = vulkan_export_to_cuda(hwfc,
src->hw_frames_ctx,
dst);
4313 dst_int = dst_f->internal;
4315 for (
int i = 0;
i < nb_images;
i++) {
4316 s_w_par[
i].params.fence.value = dst_f->sem_value[
i] + 0;
4317 s_s_par[
i].params.fence.value = dst_f->sem_value[
i] + 1;
4320 err =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
4321 nb_images, cuda_dev->stream));
4326 CUDA_MEMCPY2D cpy = {
4327 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
4328 .srcDevice = (CUdeviceptr)
src->data[
i],
4329 .srcPitch =
src->linesize[
i],
4332 .dstMemoryType = CU_MEMORYTYPE_ARRAY,
4333 .dstArray = dst_int->cu_array[
i],
4339 cpy.WidthInBytes = p_w *
desc->comp[
i].step;
4342 err =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
4347 err =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
4348 nb_images, cuda_dev->stream));
4352 for (
int i = 0;
i < nb_images;
i++)
4353 dst_f->sem_value[
i]++;
4374 switch (
src->format) {
4379 return vulkan_map_from_vaapi(hwfc,
dst,
src,
flags);
4385 return vulkan_map_from_drm(hwfc,
dst,
src,
flags);
4395typedef struct VulkanDRMMapping {
4396 AVDRMFrameDescriptor drm_desc;
4414static inline uint32_t vulkan_fmt_to_drm(
VkFormat vkfmt)
4417 if (vulkan_drm_format_map[
i].vk_format == vkfmt)
4418 return vulkan_drm_format_map[
i].drm_fourcc;
4419 return DRM_FORMAT_INVALID;
4422#define MAX_MEMORY_PLANES 4
4423static VkImageAspectFlags plane_index_to_aspect(
int plane) {
4424 if (plane == 0)
return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4425 if (plane == 1)
return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
4426 if (plane == 2)
return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
4427 if (plane == 3)
return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT;
4430 return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4433#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
4443 if (
f->internal->drm_sync_sem == VK_NULL_HANDLE) {
4444 VkExportSemaphoreCreateInfo exp_info = {
4445 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
4446 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
4448 VkSemaphoreTypeCreateInfo type_info = {
4449 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
4451 .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
4453 VkSemaphoreCreateInfo sem_create = {
4454 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
4455 .pNext = &type_info,
4457 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_create, hwctx->
alloc,
4458 &
f->internal->drm_sync_sem);
4459 if (ret != VK_SUCCESS) {
4471 for (
int i = 0;
i < nb_sems;
i++)
4474 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
4476 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 0);
4478 VkSemaphoreGetFdInfoKHR get_fd_info = {
4479 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
4480 .semaphore =
f->internal->drm_sync_sem,
4481 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
4483 ret = vk->GetSemaphoreFdKHR(hwctx->
act_dev, &get_fd_info, &sync_fd);
4484 if (ret != VK_SUCCESS) {
4486 "Failed to get sync fd from DRM map export semaphore: %s\n",
4509 VkImageDrmFormatModifierPropertiesEXT drm_mod = {
4510 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
4512 const int nb_sems = nb_images;
4513 int free_drm_desc_on_err = 1;
4524#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
4526 f->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
4527 vk->GetSemaphoreFdKHR && vk->CreateSemaphore) {
4528 err = vulkan_drm_export_sync_fd(hwfc,
f, fp, nb_sems);
4537 VkSemaphoreWaitInfo wait_info = {
4538 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4540 .semaphoreCount = nb_sems,
4541 .pSemaphores =
f->sem,
4542 .pValues =
f->sem_value,
4544 vk->WaitSemaphores(hwctx->
act_dev, &wait_info, UINT64_MAX);
4552 free_drm_desc_on_err = 0;
4554 ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->
act_dev,
f->img[0],
4556 if (ret != VK_SUCCESS) {
4562 for (
int i = 0; (
i <
planes) && (
f->mem[
i]);
i++) {
4563 VkMemoryGetFdInfoKHR export_info = {
4564 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
4565 .memory =
f->mem[
i],
4566 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
4569 ret = vk->GetMemoryFdKHR(hwctx->
act_dev, &export_info,
4571 if (ret != VK_SUCCESS) {
4577#if HAVE_LINUX_DMA_BUF_H && defined(DMA_BUF_IOCTL_IMPORT_SYNC_FILE)
4579 int dup_fd = dup(sync_fd);
4581 struct dma_buf_import_sync_file import_info = {
4582 .flags = DMA_BUF_SYNC_WRITE,
4585 if (ioctl(drm_desc->
objects[
i].
fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import_info) < 0)
4604 drm_desc->
layers[
i].
format = vulkan_fmt_to_drm(plane_vkfmt);
4614 VkSubresourceLayout
layout;
4615 int aspect_plane = (nb_images == 1) ?
i : j;
4616 VkImageSubresource sub = {
4617 .aspectMask = plane_index_to_aspect(aspect_plane),
4634 if (
f->tiling == VK_IMAGE_TILING_OPTIMAL)
4640 dst->height =
src->height;
4641 dst->data[0] = (uint8_t *)drm_desc;
4654 if (free_drm_desc_on_err)
4694 switch (
dst->format) {
4704 return vulkan_map_to_vaapi(hwfc,
dst,
src,
flags);
4716 AVFrame *swf, VkBufferImageCopy *region,
4725 region[
i].bufferRowLength,
4729 region[
i].imageExtent.height);
4732 if (err != VK_SUCCESS) {
4739 if (err != VK_SUCCESS) {
4749 region[
i].bufferRowLength,
4751 region[
i].imageExtent.height);
4758 AVFrame *swf, VkBufferImageCopy *region,
int upload)
4765 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4766 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4768 size_t buf_offset = 0;
4772 region[
i] = (VkBufferImageCopy) {
4773 .bufferOffset = buf_offset,
4775 p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
4776 .bufferImageHeight = p_h,
4777 .imageSubresource.layerCount = 1,
4778 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4782 buf_offset +=
FFALIGN(p_h*region[
i].bufferRowLength,
4783 p->props.properties.limits.optimalBufferCopyOffsetAlignment);
4788 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
4789 p->vkctx.host_cached_flag);
4797 AVFrame *swf, VkBufferImageCopy *region,
int upload)
4805 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4806 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4810 while (swf->
buf[nb_src_bufs])
4814 if (nb_src_bufs == 1) {
4816 swf->
data[0], VK_WHOLE_SIZE, swf->
buf[0],
4823 region[
i].bufferOffset =
dst[0]->virtual_offset +
4825 }
else if (nb_src_bufs ==
planes) {
4828 swf->
data[
i], VK_WHOLE_SIZE,
4829 swf->
buf[
i], buf_usage);
4834 region[
i].bufferOffset =
dst[
i]->virtual_offset;
4855 for (
int i = 0;
i < (*nb_bufs);
i++)
4876 int nb_layout_ch = 0;
4880 for (
int i = 0;
i < nb_images;
i++) {
4882 for (
int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
4883 if (hwf_vk->
layout[
i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
4893 layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
4894 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
4895 .image = hwf_vk->
img[
i],
4896 .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
4897 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
4898 .subresourceRange = {
4899 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
4905 hwf_vk->
layout[
i] = layout_ch_info[nb_layout_ch].newLayout;
4910 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4911 .pSemaphores = hwf_vk->
sem,
4913 .semaphoreCount = nb_images,
4919 vk->TransitionImageLayoutEXT(hwctx->
act_dev,
4920 nb_layout_ch, layout_ch_info);
4923 VkMemoryToImageCopyEXT region_info = {
4924 .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
4925 .imageSubresource = {
4929 VkCopyMemoryToImageInfoEXT copy_info = {
4930 .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
4932 .pRegions = ®ion_info,
4935 int img_idx =
FFMIN(
i, (nb_images - 1));
4939 region_info.pHostPointer = swf->
data[
i];
4940 region_info.memoryRowLength = swf->
linesize[
i] /
desc->comp[
i].step;
4942 region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4943 copy_info.dstImage = hwf_vk->
img[img_idx];
4944 copy_info.dstImageLayout = hwf_vk->
layout[img_idx];
4946 vk->CopyMemoryToImageEXT(hwctx->
act_dev, ©_info);
4949 VkImageToMemoryCopyEXT region_info = {
4950 .sType = VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,
4951 .imageSubresource = {
4955 VkCopyImageToMemoryInfoEXT copy_info = {
4956 .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,
4958 .pRegions = ®ion_info,
4961 int img_idx =
FFMIN(
i, (nb_images - 1));
4965 region_info.pHostPointer = swf->
data[
i];
4966 region_info.memoryRowLength = swf->
linesize[
i] /
desc->comp[
i].step;
4968 region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4969 copy_info.srcImage = hwf_vk->
img[img_idx];
4970 copy_info.srcImageLayout = hwf_vk->
layout[img_idx];
4972 vk->CopyImageToMemoryEXT(hwctx->
act_dev, ©_info);
4991 int host_mapped = 0;
5006 VkCommandBuffer cmd_buf;
5018 int host_copy = hwctx->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
5020 !p->avoid_host_import;
5026 host_copy = host_map = 0;
5029 if (!upload && host_copy) {
5030 for (
int i = 0;
i < nb_images;
i++) {
5032 for (
int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
5033 if (hwf_vk->
layout[
i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
5053 region[
i] = (VkBufferImageCopy) {
5056 .bufferImageHeight = p_h,
5057 .imageSubresource.layerCount = 1,
5058 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
5084 cmd_buf = exec->
buf;
5092 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
5093 VK_PIPELINE_STAGE_2_TRANSFER_BIT);
5111 for (
int i = 0;
i < nb_bufs;
i++)
5116 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
5117 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
5118 upload ? VK_ACCESS_TRANSFER_WRITE_BIT :
5119 VK_ACCESS_TRANSFER_READ_BIT,
5120 upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
5121 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5122 p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
5124 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
5125 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
5126 .pImageMemoryBarriers = img_bar,
5127 .imageMemoryBarrierCount = nb_img_bar,
5131 int buf_idx =
FFMIN(
i, (nb_bufs - 1));
5132 int img_idx =
FFMIN(
i, (nb_images - 1));
5135 uint32_t orig_stride = region[
i].bufferRowLength;
5136 region[
i].bufferRowLength /=
desc->comp[
i].step;
5140 vk->CmdCopyBufferToImage(cmd_buf, vkbuf->
buf,
5141 hwf_vk->
img[img_idx],
5142 img_bar[img_idx].newLayout,
5145 vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->
img[img_idx],
5146 img_bar[img_idx].newLayout,
5150 region[
i].bufferRowLength = orig_stride;
5154 if (err >= 0 && !upload) {
5161 for (
int i = 0;
i < nb_bufs;
i++)
5172 switch (
src->format) {
5182 return vulkan_transfer_data_from_cuda(hwfc,
dst,
src);
5186 if (
src->hw_frames_ctx)
5211 CudaFunctions *cu = cu_internal->
cuda_dl;
5222 err =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
5226 err = vulkan_export_to_cuda(hwfc,
dst->hw_frames_ctx,
src);
5232 dst_int = dst_f->internal;
5234 for (
int i = 0;
i < nb_images;
i++) {
5235 s_w_par[
i].params.fence.value = dst_f->sem_value[
i] + 0;
5236 s_s_par[
i].params.fence.value = dst_f->sem_value[
i] + 1;
5239 err =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
5240 nb_images, cuda_dev->stream));
5245 CUDA_MEMCPY2D cpy = {
5246 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
5247 .dstDevice = (CUdeviceptr)
dst->data[
i],
5248 .dstPitch =
dst->linesize[
i],
5251 .srcMemoryType = CU_MEMORYTYPE_ARRAY,
5252 .srcArray = dst_int->cu_array[
i],
5258 cpy.WidthInBytes =
w *
desc->comp[
i].step;
5261 err =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
5266 err =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
5267 nb_images, cuda_dev->stream));
5271 for (
int i = 0;
i < nb_images;
i++)
5272 dst_f->sem_value[
i]++;
5293 switch (
dst->format) {
5303 return vulkan_transfer_data_to_cuda(hwfc,
dst,
src);
5307 if (
dst->hw_frames_ctx)
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
static const char *const format[]
static AVFormatContext * ctx
static AVDictionary * opts
static av_cold void close(AVCodecParserContext *s)
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
static const uint8_t *BS_FUNC align(BSCTX *bc)
Skip bits to a byte boundary.
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
#define AV_CEIL_RSHIFT(a, b)
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static const uint16_t fc[]
#define AV_NUM_DATA_POINTERS
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
#define LIBAVUTIL_VERSION_MINOR
#define LIBAVUTIL_VERSION_MAJOR
#define LIBAVUTIL_VERSION_MICRO
static const int offsets[]
static const int weights[]
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
int ff_hwframe_map_replace(AVFrame *dst, const AVFrame *src)
Replace the current hwmap of dst with the one from src, used for indirect mappings like VAAPI->(DRM)-...
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
AVHWFrameTransferDirection
@ AV_HWDEVICE_TYPE_VULKAN
FFmpeg internal API for CUDA.
API-specific header for AV_HWDEVICE_TYPE_DRM.
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_vulkan
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the optimal per-plane Vulkan format for a given sw_format, one for each plane.
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
static int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf, VkQueueFlagBits flags)
AVVkFrame * av_vk_frame_alloc(void)
Allocates a single AVVkFrame and initializes everything as 0.
#define PICK_QF(type, vid_op)
static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
static void vulkan_free_internal(VulkanDevicePriv *p, AVVkFrame *f)
static int vulkan_frames_init(AVHWFramesContext *hwfc)
static VKAPI_ATTR VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *data, void *priv)
static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, const void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
#define RELEASE_PROPS(props, count)
static const struct FFVkFormatEntry vk_formats_list[]
static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf, AVFrame *swf, int upload)
static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *feats)
static const int nb_vk_formats_list
static int pick_video_queue_family(VkQueueFamilyProperties2 *qf, VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf, VkVideoCodecOperationFlagsKHR flags)
static const char * vk_dev_type(enum VkPhysicalDeviceType type)
static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, void *alloc_pnext, size_t alloc_pnext_stride)
static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceFeatures *src)
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the optimal per-plane Vulkan format for a given sw_format, one for each plane.
static int switch_layout(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkImageTiling tiling, VkImageUsageFlagBits usage, VkImageCreateFlags flags, int nb_layers, void *create_pnext)
static int vulkan_host_transfer_usable(AVHWFramesContext *hwfc)
static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select)
static void vulkan_frame_free_cb(void *opaque, uint8_t *data)
#define ADD_VAL_TO_LIST(list, count, val)
static void get_export_handle_types(AVHWFramesContext *hwfc, VkExternalMemoryHandleTypeFlags *comp_handle_types, VkExternalMemoryHandleTypeFlags *export_types)
static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
static int copy_buffer_data(AVHWFramesContext *hwfc, FFVkBuffer *vkbuf, AVFrame *swf, VkBufferImageCopy *region, int planes, int upload)
static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
static int vulkan_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
static int vulkan_device_init(AVHWDeviceContext *ctx)
static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc, AVHWFramesContext *src_fc, int flags)
@ FF_VULKAN_DEBUG_VALIDATE
@ FF_VULKAN_DEBUG_PRACTICES
static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static void switch_new_props(enum PrepMode pmode, VkImageLayout *new_layout, VkAccessFlags2 *new_access)
static int vulkan_transfer_frame(AVHWFramesContext *hwfc, AVFrame *swf, AVFrame *hwf, int upload)
static int host_map_frame(AVHWFramesContext *hwfc, FFVkBuffer **dst, int *nb_bufs, AVFrame *swf, VkBufferImageCopy *region, int upload)
static void lock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
static AVBufferRef * vulkan_pool_alloc(void *opaque, size_t size)
static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
static void vulkan_device_uninit(AVHWDeviceContext *ctx)
static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDeviceSelection *dev_select, int disable_multiplane, AVDictionary *opts, int flags)
static const struct FFVkFormatEntry * vk_find_format_entry(enum AVPixelFormat p)
static void try_export_flags(AVHWFramesContext *hwfc, VkExternalMemoryHandleTypeFlags *comp_handle_types, VkExternalMemoryHandleTypeFlags *iexp, VkExternalMemoryHandleTypeFlagBits exp)
static void vulkan_device_free(AVHWDeviceContext *ctx)
static void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format, int frame_w, int frame_h, int plane)
const char ** av_vk_get_optional_device_extensions(int *count)
Returns an array of optional Vulkan device extensions that FFmpeg may use if enabled.
static int load_libvulkan(AVHWDeviceContext *ctx)
static int get_plane_buf(AVHWFramesContext *hwfc, FFVkBuffer **dst, AVFrame *swf, VkBufferImageCopy *region, int upload)
static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
static int vulkan_device_has_rebar(AVHWDeviceContext *ctx)
static const VulkanOptExtension optional_instance_exts[]
static int check_layers(AVHWDeviceContext *ctx, AVDictionary *opts, const char *const **dst, uint32_t *num, enum FFVulkanDebugMode *debug_mode)
static int switch_layout_host(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *const **dst, uint32_t *num, enum FFVulkanDebugMode debug_mode)
const char ** av_vk_get_optional_instance_extensions(int *count)
Returns an array of optional Vulkan instance extensions that FFmpeg may use if enabled.
static int vkfmt_from_pixfmt2(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, VkImageTiling tiling, VkFormat fmts[AV_NUM_DATA_POINTERS], int *nb_images, VkImageAspectFlags *aspect, VkImageUsageFlags *supported_usage, int disable_multiplane, int need_storage)
static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts, enum FFVulkanDebugMode *debug_mode)
static const VulkanOptExtension optional_device_exts[]
@ PREP_MODE_EXTERNAL_EXPORT
@ PREP_MODE_EXTERNAL_IMPORT
static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
API-specific header for AV_HWDEVICE_TYPE_VULKAN.
@ AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE
enum AVPixelFormat pixfmt
#define FF_DISABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
Get the aspect flag for a plane from an image.
int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf, FFVkExecPool *pool, int nb_contexts, int nb_queries, VkQueryType query_type, int query_64bit, const void *query_create_pnext)
Allocates/frees an execution pool.
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f)
void ff_vk_frame_barrier(FFVulkanContext *s, FFVkExecContext *e, AVFrame *pic, VkImageMemoryBarrier2 *bar, int *nb_bar, VkPipelineStageFlags2 src_stage, VkPipelineStageFlags2 dst_stage, VkAccessFlagBits2 new_access, VkImageLayout new_layout, uint32_t new_qf)
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
int ff_vk_host_map_buffer(FFVulkanContext *s, FFVkBuffer **dst, uint8_t *src_data, VkDeviceSize size, const AVBufferRef *src_buf, VkBufferUsageFlags usage)
Maps a system RAM buffer into a Vulkan buffer.
void ff_vk_exec_add_dep_refstruct(FFVulkanContext *s, FFVkExecContext *e, void *obj)
Execution dependency management.
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVRefStructPool **buf_pool, FFVkBuffer **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
int ff_vk_flush_buffer(FFVulkanContext *s, FFVkBuffer *buf, VkDeviceSize offset, VkDeviceSize mem_size, int flush)
Flush or invalidate a single buffer, with a given size and offset.
void ff_vk_exec_discard(FFVulkanContext *s, FFVkExecContext *e)
void ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *sem, int nb, VkPipelineStageFlagBits2 stage, int wait)
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
void ff_vk_exec_add_dep_wait_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore sem, uint64_t val, VkPipelineStageFlagBits2 stage)
static const struct @257111027162314367033347246032313251342043035002 planes[]
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
#define AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_GBRPF32
#define AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_RGBF32
#define AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_RGBAF32
#define AV_PIX_FMT_RGBAF16
#define AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_GBRAP32
#define AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_GBRAP14
#define AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GRAY32
#define AV_PIX_FMT_RGBA128
#define AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GBRAPF16
#define AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_BAYER_RGGB16
#define AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_X2RGB10
#define AV_PIX_FMT_GRAYF32
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
@ AV_PIX_FMT_NV24
planar YUV 4:4:4, 24bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
#define AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GBRPF16
#define AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_XYZP12
#define AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_GBRAPF32
#define AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P10
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
static void av_refstruct_pool_uninit(AVRefStructPool **poolp)
Mark the pool as being available for freeing.
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
uint8_t * data
The data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
int fd
File descriptor of DRM device.
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
int nb_layers
Number of layers in the frame.
int nb_objects
Number of DRM objects making up this frame.
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
int nb_planes
Number of planes in the layer.
uint32_t format
Format of the layer (DRM_FORMAT_*).
int fd
DRM PRIME fd for the object.
size_t size
Total size of the object.
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
ptrdiff_t pitch
Pitch (linesize) of this plane.
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor.
ptrdiff_t offset
Offset within that object of this plane.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
int max_width
The maximum size of frames in this hw_frames_ctx.
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
int min_width
The minimum size of frames in this hw_frames_ctx.
This struct describes a set or pool of "hardware" frames (i.e.
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
int width
The allocated dimensions of the frames in this pool.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
AVRefStructPool is an API for a thread-safe pool of objects managed via the RefStruct API.
VAAPI connection details.
VADisplay display
The VADisplay handle, to be filled by the user.
pthread_mutex_t update_mutex
VkImageLayout layout[AV_NUM_DATA_POINTERS]
VkSemaphore sem[AV_NUM_DATA_POINTERS]
Synchronization timeline semaphores, one for each VkImage.
uint64_t sem_value[AV_NUM_DATA_POINTERS]
Up to date semaphore value at which each image becomes accessible.
struct AVVkFrameInternal * internal
Internal data.
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
VkPhysicalDevice phys_dev
Physical device.
AVVulkanDeviceQueueFamily qf[64]
Queue families used.
int nb_enabled_inst_extensions
const char *const * enabled_dev_extensions
Enabled device extensions.
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
VkDevice act_dev
Active device.
const char *const * enabled_inst_extensions
Enabled instance extensions.
VkInstance inst
Vulkan instance.
VkPhysicalDeviceFeatures2 device_features
This structure should be set to the set of features that present and enabled during device creation.
int nb_enabled_dev_extensions
VkDeviceQueueCreateFlags queue_flags
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
VkVideoCodecOperationFlagBitsKHR video_caps
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
void * create_pnext
Extension data for image creation.
VkImageTiling tiling
Controls the tiling of allocated frames.
VkImageCreateFlags img_flags
Flags to set during image creation.
void * alloc_pnext[AV_NUM_DATA_POINTERS]
Extension data for memory allocation.
VkImageUsageFlagBits usage
Defines extra usage of output frames.
AVVkFrameFlags flags
A combination of AVVkFrameFlags.
void(* lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Locks a frame, preventing other threads from changing frame properties.
int nb_layers
Number of layers each image will have.
void(* unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Similar to lock_frame(), unlocks a frame.
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
AVBufferPool * pool_internal
VkImageAspectFlags aspect
enum AVPixelFormat pixfmt
const VkFormat fallback[5]
void * priv
Hardware-specific private data associated with the mapping.
AVFrame * source
A reference to the original source of the mapping.
VkPhysicalDeviceVulkan11Features vulkan_1_1
VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow
VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1
VkPhysicalDeviceVulkan12Features vulkan_1_2
VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix
VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR explicit_mem_layout
VkPhysicalDeviceVulkan13Features vulkan_1_3
VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore
VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate
VkPhysicalDeviceShaderObjectFeaturesEXT shader_object
VkPhysicalDeviceFeatures2 device
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float
VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy
AVVulkanDeviceQueueFamily * compute_qf
pthread_mutex_t ** qf_mutex
VkPhysicalDeviceMemoryProperties mprops
VulkanDeviceFeatures feats
AVVulkanDeviceContext p
The public AVVulkanDeviceContext.
VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops
VkPhysicalDeviceDriverProperties dprops
VkPhysicalDeviceProperties2 props
VkDebugUtilsMessengerEXT debug_ctx
VkExternalSemaphoreProperties ext_sem_props_opaque
AVVulkanDeviceQueueFamily * transfer_qf
int transfer_offset_align
uint8_t uuid[VK_UUID_SIZE]
VkImageDrmFormatModifierListCreateInfoEXT * modifier_info
VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5]
FFVkExecPool compute_exec
FFVkExecPool download_exec
AVVulkanFramesContext p
The public AVVulkanFramesContext.
int export_requires_dedicated
#define av_malloc_array(a, b)
int av_uuid_parse(const char *in, AVUUID uu)
Parses a string representation of a UUID formatted according to IETF RFC 4122 into an AVUUID.
UUID parsing and serialization utilities.
static void lock_queue(void *priv, uint32_t qf, uint32_t qidx)
static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
static int mod(int a, int b)
Modulo operation with only positive remainders.
#define FF_VK_DEFAULT_EXEC_CONTEXTS
#define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE)
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
static int ff_vk_count_images(AVVkFrame *f)
VkImageUsageFlags ff_vk_map_feats_to_usage(VkFormatFeatureFlagBits2 feats)
Map between usage and features.
static void ff_vk_link_struct(void *chain, const void *in)
#define FF_VK_EXT_VIDEO_ENCODE_AV1
#define FF_VK_EXT_EXPLICIT_MEM_LAYOUT
#define FF_VK_EXT_VIDEO_DECODE_H265
#define FF_VK_EXT_RELAXED_EXTENDED_INSTR
#define FF_VK_EXT_EXTERNAL_FD_SEM
#define FF_VK_EXT_PORTABILITY_SUBSET
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_DRM_MODIFIER_FLAGS
#define FF_VK_EXT_SHADER_OBJECT
#define FF_VK_EXT_VIDEO_QUEUE
#define FF_VK_EXT_UNIFIED_IMAGE_LAYOUTS
uint64_t FFVulkanExtensions
#define FF_VK_EXT_COOP_MATRIX
#define FF_VK_EXT_INTERNAL_QUEUE_SYNC
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_NO_FLAG
#define FF_VK_EXT_VIDEO_DECODE_AV1
#define FF_VK_EXT_OPTICAL_FLOW
#define FF_VK_EXT_EXTERNAL_DMABUF_MEMORY
#define FF_VK_EXT_MAINTENANCE_11
#define FF_VK_EXT_SUBGROUP_ROTATE
#define FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_MAXIMAL_RECONVERGENCE
#define FF_VK_EXT_DEVICE_DRM
#define FF_VK_EXT_VIDEO_DECODE_H264
#define FF_VK_EXT_VIDEO_ENCODE_H264
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_LONG_VECTOR
#define FF_VK_EXT_VIDEO_DECODE_VP9
#define FF_VK_EXT_EXTERNAL_WIN32_SEM
#define FF_VK_EXT_MAINTENANCE_9
#define FF_VK_EXT_EXPECT_ASSUME
#define FF_VK_EXT_HOST_IMAGE_COPY
#define FF_VK_EXT_EXTERNAL_FD_MEMORY
#define FF_VK_EXT_ZERO_INITIALIZE
#define FF_VK_EXT_REPLICATED_COMPOSITES
#define FF_VK_EXT_VIDEO_ENCODE_H265
#define FF_VK_EXT_ATOMIC_FLOAT
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
#define FF_VK_EXT_EXTERNAL_WIN32_MEMORY
#define FF_VK_EXT_VIDEO_MAINTENANCE_2
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.