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_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 } },
519 { 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 } },
520 { 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 } },
521 { 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 } },
522 { 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 } },
523 { 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 } },
524 { 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 } },
525 { 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 } },
532 { 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 } },
533 { 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 } },
538 { 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 } },
539 { 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 } },
544 { 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 } },
545 { 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 } },
563 { VK_FORMAT_G8B8G8R8_422_UNORM,
AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
564 { VK_FORMAT_B8G8R8G8_422_UNORM,
AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
565 { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
566 { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
567 { VK_FORMAT_G16B16G16R16_422_UNORM,
AV_PIX_FMT_Y216, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
570 { 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 } },
571 { 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 } },
572 { 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 } },
575 { 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 } },
576 { 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 } },
577 { 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 } },
578 { 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 } },
581 { 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 } },
582 { 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 } },
583 { 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 } },
584 { 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 } },
587 { VK_FORMAT_A2R10G10B10_UNORM_PACK32,
AV_PIX_FMT_XV30, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
588 { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
589 { VK_FORMAT_R16G16B16A16_UNORM,
AV_PIX_FMT_XV48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
610 VkImageTiling tiling,
613 VkImageAspectFlags *
aspect,
614 VkImageUsageFlags *supported_usage,
615 int disable_multiplane,
int need_storage)
621 const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
622 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
623 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
627 VkFormatProperties3 fprops = {
628 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
630 VkFormatProperties2 prop = {
631 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
634 VkFormatFeatureFlagBits2 feats_primary, feats_secondary;
635 int basics_primary = 0, basics_secondary = 0;
636 int storage_primary = 0, storage_secondary = 0;
638 vk->GetPhysicalDeviceFormatProperties2(hwctx->
phys_dev,
642 feats_primary = tiling == VK_IMAGE_TILING_LINEAR ?
643 fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
644 basics_primary = (feats_primary & basic_flags) == basic_flags;
645 storage_primary = !!(feats_primary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
648 vk->GetPhysicalDeviceFormatProperties2(hwctx->
phys_dev,
651 feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ?
652 fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
653 basics_secondary = (feats_secondary & basic_flags) == basic_flags;
654 storage_secondary = !!(feats_secondary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
656 basics_secondary = basics_primary;
657 storage_secondary = storage_primary;
660 if (basics_primary &&
662 (!need_storage || (need_storage && (storage_primary | storage_secondary)))) {
677 ((need_storage && (storage_primary | storage_secondary)) ?
678 VK_IMAGE_USAGE_STORAGE_BIT : 0);
680 }
else if (basics_secondary &&
681 (!need_storage || (need_storage && storage_secondary))) {
702#if CONFIG_VULKAN_STATIC
703VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
712#if CONFIG_VULKAN_STATIC
715 static const char *lib_names[] = {
718#elif defined(__APPLE__)
729 p->libvulkan = dlopen(lib_names[
i], RTLD_NOW | RTLD_LOCAL);
739 hwctx->
get_proc_addr = (PFN_vkGetInstanceProcAddr)dlsym(p->libvulkan,
"vkGetInstanceProcAddr");
768#ifdef VK_KHR_shader_relaxed_extended_instruction
771#ifdef VK_EXT_shader_long_vector
774#ifdef VK_EXT_shader_replicated_composites
777#ifdef VK_EXT_zero_initialize_device_memory
780#ifdef VK_KHR_shader_expect_assume
783#ifdef VK_KHR_shader_maximal_reconvergence
786#ifdef VK_KHR_maintenance9
789#ifdef VK_KHR_maintenance11
792#ifdef VK_KHR_unified_image_layouts
796#ifdef VK_KHR_video_maintenance2
799#ifdef VK_KHR_internally_synchronized_queues
823#ifdef VK_KHR_video_decode_vp9
826#ifdef VK_KHR_video_encode_av1
862 VkDebugUtilsMessageTypeFlagsEXT messageType,
863 const VkDebugUtilsMessengerCallbackDataEXT *
data,
870 switch (
data->messageIdNumber) {
879 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l =
AV_LOG_VERBOSE;
break;
880 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l =
AV_LOG_INFO;
break;
881 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l =
AV_LOG_WARNING;
break;
882 case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: l =
AV_LOG_ERROR;
break;
887 for (
int i = 0;
i <
data->cmdBufLabelCount;
i++)
893#define ADD_VAL_TO_LIST(list, count, val) \
895 list = av_realloc_array(list, ++count, sizeof(*list)); \
897 err = AVERROR(ENOMEM); \
900 list[count - 1] = av_strdup(val); \
901 if (!list[count - 1]) { \
902 err = AVERROR(ENOMEM); \
907#define RELEASE_PROPS(props, count) \
909 for (int i = 0; i < count; i++) \
910 av_free((void *)((props)[i])); \
911 av_free((void *)props); \
917 VkDeviceSize max_vram = 0, max_visible_vram = 0;
921 for (
int i = 0;
i < p->mprops.memoryTypeCount;
i++) {
922 const VkMemoryType
type = p->mprops.memoryTypes[
i];
923 const VkMemoryHeap heap = p->mprops.memoryHeaps[
type.heapIndex];
924 if (!(
type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
926 max_vram =
FFMAX(max_vram, heap.size);
927 if (
type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
928 max_visible_vram =
FFMAX(max_visible_vram, heap.size);
931 return max_vram - max_visible_vram < 1024;
947 const char *
const **
dst, uint32_t *
num,
951 const char **extension_names =
NULL;
955 int err = 0, found, extensions_found = 0;
958 int optional_exts_num;
959 uint32_t sup_ext_count;
960 char *user_exts_str =
NULL;
962 VkExtensionProperties *sup_ext;
972 if (!user_exts_str) {
977 vk->EnumerateInstanceExtensionProperties(
NULL, &sup_ext_count,
NULL);
978 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
981 vk->EnumerateInstanceExtensionProperties(
NULL, &sup_ext_count, sup_ext);
989 if (!user_exts_str) {
994 vk->EnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
995 &sup_ext_count,
NULL);
996 sup_ext =
av_malloc_array(sup_ext_count,
sizeof(VkExtensionProperties));
999 vk->EnumerateDeviceExtensionProperties(hwctx->
phys_dev,
NULL,
1000 &sup_ext_count, sup_ext);
1003 for (
int i = 0;
i < optional_exts_num;
i++) {
1004 tstr = optional_exts[
i].
name;
1008 if (!strcmp(tstr, VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME) &&
1016 (!strcmp(tstr, VK_EXT_SHADER_OBJECT_EXTENSION_NAME))) {
1020 for (
int j = 0; j < sup_ext_count; j++) {
1021 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1030 p->vkctx.extensions |= optional_exts[
i].
flag;
1038 tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
1040 for (
int j = 0; j < sup_ext_count; j++) {
1041 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1057#ifdef VK_KHR_shader_relaxed_extended_instruction
1059 tstr = VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME;
1061 for (
int j = 0; j < sup_ext_count; j++) {
1062 if (!strcmp(tstr, sup_ext[j].extensionName)) {
1076 if (user_exts_str) {
1077 char *save, *token =
av_strtok(user_exts_str,
"+", &save);
1080 for (
int j = 0; j < sup_ext_count; j++) {
1081 if (!strcmp(token, sup_ext[j].extensionName)) {
1097 *
dst = extension_names;
1098 *
num = extensions_found;
1112 const char *
const **
dst, uint32_t *
num,
1119 static const char layer_standard_validation[] = {
"VK_LAYER_KHRONOS_validation" };
1120 int layer_standard_validation_found = 0;
1122 uint32_t sup_layer_count;
1123 VkLayerProperties *sup_layers;
1126 char *user_layers_str =
NULL;
1129 const char **enabled_layers =
NULL;
1130 uint32_t enabled_layers_count = 0;
1138 vk->EnumerateInstanceLayerProperties(&sup_layer_count,
NULL);
1139 sup_layers =
av_malloc_array(sup_layer_count,
sizeof(VkLayerProperties));
1142 vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers);
1145 for (
int i = 0;
i < sup_layer_count;
i++)
1149 if (!debug_opt && !user_layers)
1154 if (!strcmp(debug_opt->
value,
"printf")) {
1156 }
else if (!strcmp(debug_opt->
value,
"validate")) {
1158 }
else if (!strcmp(debug_opt->
value,
"practices")) {
1161 char *end_ptr =
NULL;
1162 int idx = strtol(debug_opt->
value, &end_ptr, 10);
1163 if (end_ptr == debug_opt->
value || end_ptr[0] !=
'\0' ||
1178 for (
int i = 0;
i < sup_layer_count;
i++) {
1179 if (!strcmp(layer_standard_validation, sup_layers[
i].layerName)) {
1181 layer_standard_validation);
1182 ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation);
1184 layer_standard_validation_found = 1;
1188 if (!layer_standard_validation_found) {
1190 "Validation Layer \"%s\" not supported\n", layer_standard_validation);
1201 if (!user_layers_str) {
1206 token =
av_strtok(user_layers_str,
"+", &save);
1211 if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) {
1217 for (
int j = 0; j < sup_layer_count; j++) {
1218 if (!strcmp(token, sup_layers[j].layerName)) {
1229 if (!strcmp(layer_standard_validation, token))
1233 "Layer \"%s\" not supported\n", token);
1250 *
dst = enabled_layers;
1251 *
num = enabled_layers_count;
1266 VkApplicationInfo application_info = {
1267 .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
1268 .pApplicationName =
"ffmpeg",
1272 .pEngineName =
"libavutil",
1273 .apiVersion = VK_API_VERSION_1_3,
1278 VkValidationFeaturesEXT validation_features = {
1279 .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
1281 VkInstanceCreateInfo inst_props = {
1282 .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
1283 .pApplicationInfo = &application_info,
1299 &inst_props.enabledLayerCount, debug_mode);
1305 &inst_props.enabledExtensionCount, *debug_mode);
1313 static const VkValidationFeatureEnableEXT feat_list_validate[] = {
1314 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1315 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1316 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
1318 validation_features.pEnabledValidationFeatures = feat_list_validate;
1319 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_validate);
1320 inst_props.pNext = &validation_features;
1322 static const VkValidationFeatureEnableEXT feat_list_debug[] = {
1323 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1324 VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1325 VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
1327 validation_features.pEnabledValidationFeatures = feat_list_debug;
1328 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_debug);
1329 inst_props.pNext = &validation_features;
1331 static const VkValidationFeatureEnableEXT feat_list_practices[] = {
1332 VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1333 VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
1335 validation_features.pEnabledValidationFeatures = feat_list_practices;
1336 validation_features.enabledValidationFeatureCount =
FF_ARRAY_ELEMS(feat_list_practices);
1337 inst_props.pNext = &validation_features;
1341 for (
int i = 0;
i < inst_props.enabledExtensionCount;
i++) {
1342 if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
1343 inst_props.ppEnabledExtensionNames[
i])) {
1344 inst_props.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
1351 ret = vk->CreateInstance(&inst_props, hwctx->
alloc, &hwctx->
inst);
1354 if (ret != VK_SUCCESS) {
1371 VkDebugUtilsMessengerCreateInfoEXT dbg = {
1372 .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
1373 .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
1374 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
1375 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
1376 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
1377 .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
1378 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
1379 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
1384 vk->CreateDebugUtilsMessengerEXT(hwctx->
inst, &dbg,
1385 hwctx->
alloc, &p->debug_ctx);
1391 RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount);
1410 case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
return "integrated";
1411 case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return "discrete";
1412 case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
return "virtual";
1413 case VK_PHYSICAL_DEVICE_TYPE_CPU:
return "software";
1414 default:
return "unknown";
1421 int err = 0, choice = -1;
1427 VkPhysicalDevice *devices =
NULL;
1428 VkPhysicalDeviceIDProperties *idp =
NULL;
1429 VkPhysicalDeviceProperties2 *prop =
NULL;
1430 VkPhysicalDeviceDriverProperties *driver_prop =
NULL;
1431 VkPhysicalDeviceDrmPropertiesEXT *drm_prop =
NULL;
1433 ret = vk->EnumeratePhysicalDevices(hwctx->
inst, &
num,
NULL);
1434 if (ret != VK_SUCCESS || !
num) {
1443 ret = vk->EnumeratePhysicalDevices(hwctx->
inst, &
num, devices);
1444 if (ret != VK_SUCCESS) {
1478 for (
int i = 0;
i <
num;
i++) {
1480 drm_prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
1481 driver_prop[
i].pNext = &drm_prop[
i];
1483 driver_prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
1484 idp[
i].pNext = &driver_prop[
i];
1485 idp[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1486 prop[
i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1487 prop[
i].pNext = &idp[
i];
1489 vk->GetPhysicalDeviceProperties2(devices[
i], &prop[
i]);
1491 prop[
i].properties.deviceName,
1493 prop[
i].properties.deviceID);
1497 for (
int i = 0;
i <
num;
i++) {
1498 if (!memcmp(idp[
i].deviceUUID, select->
uuid, VK_UUID_SIZE)) {
1507 for (
int i = 0;
i <
num;
i++) {
1508 if ((select->
drm_major == drm_prop[
i].primaryMajor &&
1509 select->
drm_minor == drm_prop[
i].primaryMinor) ||
1510 (select->
drm_major == drm_prop[
i].renderMajor &&
1511 select->
drm_minor == drm_prop[
i].renderMinor)) {
1520 }
else if (select->
name) {
1522 for (
int i = 0;
i <
num;
i++) {
1523 if (strstr(prop[
i].properties.deviceName, select->
name)) {
1534 for (
int i = 0;
i <
num;
i++) {
1535 if (select->
pci_device == prop[
i].properties.deviceID) {
1546 for (
int i = 0;
i <
num;
i++) {
1547 if (select->
vendor_id == prop[
i].properties.vendorID) {
1558 choice = select->
index;
1570 choice, prop[choice].properties.deviceName,
1572 prop[choice].properties.deviceID);
1574 p->props = prop[choice];
1575 p->props.pNext =
NULL;
1576 p->dprops = driver_prop[choice];
1577 p->dprops.pNext =
NULL;
1591 VkQueueFlagBits
flags)
1594 uint32_t min_score = UINT32_MAX;
1596 for (
int i = 0;
i < num_qf;
i++) {
1597 VkQueueFlagBits qflags = qf[
i].queueFamilyProperties.queueFlags;
1600 if ((
flags & VK_QUEUE_TRANSFER_BIT) &&
1601 (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
1602 qflags |= VK_QUEUE_TRANSFER_BIT;
1604 if (qflags &
flags) {
1605 uint32_t score =
av_popcount(qflags) + qf[
i].queueFamilyProperties.timestampValidBits;
1606 if (score < min_score) {
1614 qf[
index].queueFamilyProperties.timestampValidBits++;
1620 VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf,
1621 VkVideoCodecOperationFlagsKHR
flags)
1624 uint32_t min_score = UINT32_MAX;
1626 for (
int i = 0;
i < num_qf;
i++) {
1627 const VkQueueFlags qflags = qf[
i].queueFamilyProperties.queueFlags;
1628 const VkVideoCodecOperationFlagsKHR vflags = qf_vid[
i].videoCodecOperations;
1630 if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR)))
1633 if (vflags &
flags) {
1634 uint32_t score =
av_popcount(vflags) + qf[
i].queueFamilyProperties.timestampValidBits;
1635 if (score < min_score) {
1643 qf[
index].queueFamilyProperties.timestampValidBits++;
1655 VkQueueFamilyProperties2 *qf =
NULL;
1656 VkQueueFamilyVideoPropertiesKHR *qf_vid =
NULL;
1659 vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &
num,
NULL);
1674 for (uint32_t
i = 0;
i <
num;
i++) {
1675 qf_vid[
i] = (VkQueueFamilyVideoPropertiesKHR) {
1676 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
1678 qf[
i] = (VkQueueFamilyProperties2) {
1679 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
1685 vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->
phys_dev, &
num, qf);
1688 for (
int i = 0;
i <
num;
i++) {
1690 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ?
" graphics" :
"",
1691 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ?
" compute" :
"",
1692 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ?
" transfer" :
"",
1693 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ?
" encode" :
"",
1694 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ?
" decode" :
"",
1695 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ?
" sparse" :
"",
1696 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ?
" optical_flow" :
"",
1697 ((qf[
i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ?
" protected" :
"",
1698 qf[
i].queueFamilyProperties.queueCount);
1702 qf[
i].queueFamilyProperties.timestampValidBits = 0;
1707#ifdef VK_KHR_internally_synchronized_queues
1709 hwctx->
queue_flags |= VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR;
1713#define PICK_QF(type, vid_op) \
1719 idx = pick_video_queue_family(qf, qf_vid, num, vid_op); \
1721 idx = pick_queue_family(qf, num, type); \
1726 for (i = 0; i < hwctx->nb_qf; i++) { \
1727 if (hwctx->qf[i].idx == idx) { \
1728 hwctx->qf[i].flags |= type; \
1729 hwctx->qf[i].video_caps |= vid_op; \
1733 if (i == hwctx->nb_qf) { \
1734 hwctx->qf[i].idx = idx; \
1735 hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \
1736 if (p->limit_queues || \
1737 p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { \
1738 int max = p->limit_queues; \
1739 if (type == VK_QUEUE_GRAPHICS_BIT) \
1740 hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, \
1743 hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, max); \
1745 hwctx->qf[i].flags = type; \
1746 hwctx->qf[i].video_caps = vid_op; \
1751 PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1752 PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1753 PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1755 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR);
1756 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
1758 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR);
1759 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
1761#ifdef VK_KHR_video_decode_vp9
1762 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR);
1765#ifdef VK_KHR_video_encode_av1
1766 PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR);
1768 PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
1771 PICK_QF(VK_QUEUE_OPTICAL_FLOW_BIT_NV, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1779 sizeof(VkDeviceQueueCreateInfo));
1780 if (!cd->pQueueCreateInfos)
1783 for (uint32_t
i = 0;
i < hwctx->
nb_qf;
i++) {
1786 VkDeviceQueueCreateInfo *pc;
1787 for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) {
1788 if (hwctx->
qf[
i].
idx == cd->pQueueCreateInfos[j].queueFamilyIndex) {
1798 for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++)
1799 av_free((
void *)cd->pQueueCreateInfos[
i].pQueuePriorities);
1800 av_free((
void *)cd->pQueueCreateInfos);
1804 for (uint32_t j = 0; j < hwctx->
qf[
i].
num; j++)
1807 pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
1808 pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) {
1809 .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1811 .queueFamilyIndex = hwctx->
qf[
i].
idx,
1812 .queueCount = hwctx->
qf[
i].
num,
1835 vk->DestroyDebugUtilsMessengerEXT(hwctx->
inst, p->debug_ctx,
1839 vk->DestroyInstance(hwctx->
inst, hwctx->
alloc);
1842 dlclose(p->libvulkan);
1853 for (uint32_t
i = 0;
i < p->nb_tot_qfs;
i++) {
1865 int disable_multiplane,
1876 VkDeviceCreateInfo dev_info = {
1877 .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1889 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
1893 &dev_info.enabledExtensionCount, debug_mode))) {
1894 for (
int i = 0;
i < dev_info.queueCreateInfoCount;
i++)
1895 av_free((
void *)dev_info.pQueueCreateInfos[
i].pQueuePriorities);
1896 av_free((
void *)dev_info.pQueueCreateInfos);
1902 vk->GetPhysicalDeviceFeatures2(hwctx->
phys_dev, &supported_feats.
device);
1907 dev_info.pNext = p->feats.device.pNext;
1908 dev_info.pEnabledFeatures = &p->feats.device.features;
1913 p->limit_queues = strtol(opt_d->
value,
NULL, 10);
1920 ret = vk->CreateDevice(hwctx->
phys_dev, &dev_info, hwctx->
alloc,
1923 for (
int i = 0;
i < dev_info.queueCreateInfoCount;
i++)
1924 av_free((
void *)dev_info.pQueueCreateInfos[
i].pQueuePriorities);
1925 av_free((
void *)dev_info.pQueueCreateInfos);
1927 if (ret != VK_SUCCESS) {
1930 for (
int i = 0;
i < dev_info.enabledExtensionCount;
i++)
1931 av_free((
void *)dev_info.ppEnabledExtensionNames[
i]);
1932 av_free((
void *)dev_info.ppEnabledExtensionNames);
1940 p->use_linear_images = strtol(opt_d->
value,
NULL, 10);
1943 p->disable_multiplane = disable_multiplane;
1944 if (!p->disable_multiplane) {
1947 p->disable_multiplane = strtol(opt_d->
value,
NULL, 10);
1951 p->avoid_host_import = p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
1954 p->avoid_host_import = strtol(opt_d->
value,
NULL, 10);
1991 VkQueueFamilyProperties2 *qf;
1992 VkQueueFamilyVideoPropertiesKHR *qf_vid;
1993 VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info;
2012 p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
2013 p->props.pNext = &p->hprops;
2014 p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
2015 p->hprops.pNext = &p->dprops;
2016 p->dprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
2018 vk->GetPhysicalDeviceProperties2(hwctx->
phys_dev, &p->props);
2020 p->props.properties.deviceName);
2023 p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
2025 p->props.properties.limits.minMemoryMapAlignment);
2027 p->props.properties.limits.nonCoherentAtomSize);
2030 p->hprops.minImportedHostPointerAlignment);
2032 vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->
phys_dev, &qf_num,
NULL);
2038 ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) {
2039 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
2043 ext_sem_props_info.handleType =
2045 IsWindows8OrGreater()
2046 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
2047 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
2049 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
2051 p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
2052 vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->
phys_dev,
2053 &ext_sem_props_info,
2054 &p->ext_sem_props_opaque);
2060 qf_vid =
av_malloc_array(qf_num,
sizeof(VkQueueFamilyVideoPropertiesKHR));
2066 for (uint32_t
i = 0;
i < qf_num;
i++) {
2067 qf_vid[
i] = (VkQueueFamilyVideoPropertiesKHR) {
2068 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
2070 qf[
i] = (VkQueueFamilyProperties2) {
2071 .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
2076 vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->
phys_dev, &qf_num, qf);
2078 p->nb_tot_qfs = qf_num;
2081 p->qf_mutex =
av_calloc(qf_num,
sizeof(*p->qf_mutex));
2087 for (uint32_t
i = 0;
i < qf_num;
i++) {
2088 p->qf_mutex[
i] =
av_calloc(qf[
i].queueFamilyProperties.queueCount,
2089 sizeof(**p->qf_mutex));
2090 if (!p->qf_mutex[
i]) {
2094 for (uint32_t j = 0; j < qf[
i].queueFamilyProperties.queueCount; j++) {
2106 for (
int i = 0;
i < hwctx->
nb_qf;
i++) {
2108 hwctx->
qf[
i].
flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
2109 VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
2116 for (
int i = 0;
i < hwctx->
nb_qf;
i++) {
2120 for (
int j = (
i - 1); j >= 0; j--) {
2127 p->img_qfs[p->nb_img_qfs++] = hwctx->
qf[
i].
idx;
2130#if FF_API_VULKAN_SYNC_QUEUES
2132 if (!hwctx->lock_queue)
2134 if (!hwctx->unlock_queue)
2140 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
2142 p->vkctx.device =
ctx;
2143 p->vkctx.hwctx = hwctx;
2146 p->compute_qf =
ff_vk_qf_find(&p->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
2147 p->transfer_qf =
ff_vk_qf_find(&p->vkctx, VK_QUEUE_TRANSFER_BIT, 0);
2150 p->transfer_offset_align = 1;
2151 if (p->transfer_qf) {
2152 VkQueueFlags
flags = p->vkctx.qf_props[p->transfer_qf->idx].queueFamilyProperties.queueFlags;
2153 if (!(
flags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
2154 p->transfer_offset_align = 4;
2156#ifdef VK_KHR_maintenance11
2157 if (p->vkctx.maintenance_11_feats.maintenance11)
2158 p->transfer_offset_align = 1;
2162 vk->GetPhysicalDeviceMemoryProperties(hwctx->
phys_dev, &p->mprops);
2174 if (device && device[0]) {
2180 dev_select.
index = strtol(device, &end, 10);
2181 if (end == device || *end) {
2182 dev_select.
index = 0;
2183 dev_select.
name = device;
2200 switch(src_ctx->
type) {
2204 VADisplay dpy = src_hwctx->
display;
2205#if VA_CHECK_VERSION(1, 15, 0)
2207 VADisplayAttribute attr = {
2208 .type = VADisplayPCIID,
2213#if VA_CHECK_VERSION(1, 15, 0)
2214 vas = vaGetDisplayAttributes(dpy, &attr, 1);
2215 if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED)
2216 dev_select.pci_device = (attr.value & 0xFFFF);
2219 if (!dev_select.pci_device) {
2220 vendor = vaQueryVendorString(dpy);
2226 if (strstr(vendor,
"AMD"))
2227 dev_select.vendor_id = 0x1002;
2236 struct stat drm_node_info;
2237 drmDevice *drm_dev_info;
2240 err = fstat(src_hwctx->
fd, &drm_node_info);
2247 dev_select.drm_major = major(drm_node_info.st_dev);
2248 dev_select.drm_minor = minor(drm_node_info.st_dev);
2249 dev_select.has_drm = 1;
2251 err = drmGetDevice(src_hwctx->
fd, &drm_dev_info);
2258 if (drm_dev_info->bustype == DRM_BUS_PCI)
2259 dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
2261 drmFreeDevice(&drm_dev_info);
2271 CudaFunctions *cu = cu_internal->
cuda_dl;
2273 int ret =
CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
2280 dev_select.has_uuid = 1;
2295 const void *hwconfig,
2303 p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2304 VK_IMAGE_TILING_OPTIMAL,
2316 p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2317 VK_IMAGE_TILING_OPTIMAL,
2331 constraints->
max_width = p->props.properties.limits.maxImageDimension2D;
2332 constraints->
max_height = p->props.properties.limits.maxImageDimension2D;
2345 VkMemoryPropertyFlagBits req_flags,
const void *alloc_extension,
2346 VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
2353 VkMemoryAllocateInfo alloc_info = {
2354 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2355 .pNext = alloc_extension,
2356 .allocationSize = req->size,
2361 for (
int i = 0;
i < p->mprops.memoryTypeCount;
i++) {
2362 const VkMemoryType *
type = &p->mprops.memoryTypes[
i];
2365 if (!(req->memoryTypeBits & (1 <<
i)))
2369 if ((
type->propertyFlags & req_flags) != req_flags)
2373 if (req->size > p->mprops.memoryHeaps[
type->heapIndex].size)
2387 alloc_info.memoryTypeIndex =
index;
2389 ret = vk->AllocateMemory(dev_hwctx->
act_dev, &alloc_info,
2390 dev_hwctx->
alloc, mem);
2391 if (ret != VK_SUCCESS) {
2397 *mem_flags |= p->mprops.memoryTypes[
index].propertyFlags;
2411 if (internal->cuda_fc_ref) {
2417 CudaFunctions *cu = cu_internal->
cuda_dl;
2420 if (internal->cu_sem[
i])
2421 CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[
i]));
2422 if (internal->cu_mma[
i])
2423 CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[
i]));
2424 if (internal->ext_mem[
i])
2425 CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[
i]));
2427 if (internal->ext_sem_handle[
i])
2428 CloseHandle(internal->ext_sem_handle[
i]);
2429 if (internal->ext_mem_handle[
i])
2430 CloseHandle(internal->ext_mem_handle[
i]);
2438 if (internal->drm_sync_sem != VK_NULL_HANDLE)
2439 p->vkctx.vkfn.DestroySemaphore(p->p.act_dev, internal->drm_sync_sem,
2459 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
2461 .pSemaphores =
f->sem,
2462 .pValues =
f->sem_value,
2463 .semaphoreCount = nb_sems,
2471 for (
int i = 0;
i < nb_images;
i++) {
2486 void *alloc_pnext,
size_t alloc_pnext_stride)
2488 int img_cnt = 0, err;
2496 while (
f->img[img_cnt]) {
2498 VkImageMemoryRequirementsInfo2 req_desc = {
2499 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2500 .image =
f->img[img_cnt],
2502 VkMemoryDedicatedAllocateInfo ded_alloc = {
2503 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
2504 .pNext = (
void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride),
2506 VkMemoryDedicatedRequirements ded_req = {
2507 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
2509 VkMemoryRequirements2 req = {
2510 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
2514 vk->GetImageMemoryRequirements2(hwctx->
act_dev, &req_desc, &req);
2517 "plane %d: driver reports prefersDedicatedAllocation=%i requiresDedicatedAllocation=%i\n",
2518 img_cnt, ded_req.prefersDedicatedAllocation, ded_req.requiresDedicatedAllocation);
2520 if (
f->tiling == VK_IMAGE_TILING_LINEAR)
2521 req.memoryRequirements.size =
FFALIGN(req.memoryRequirements.size,
2522 p->props.properties.limits.minMemoryMapAlignment);
2525 use_ded_mem = ded_req.prefersDedicatedAllocation |
2526 ded_req.requiresDedicatedAllocation;
2530 ded_alloc.image =
f->img[img_cnt];
2534 f->tiling == VK_IMAGE_TILING_LINEAR ?
2535 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
2536 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
2537 use_ded_mem ? &ded_alloc : (
void *)ded_alloc.pNext,
2538 &
f->flags, &
f->mem[img_cnt])))
2541 f->size[img_cnt] = req.memoryRequirements.size;
2542 bind_info[img_cnt].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
2543 bind_info[img_cnt].image =
f->img[img_cnt];
2544 bind_info[img_cnt].memory =
f->mem[img_cnt];
2550 ret = vk->BindImageMemory2(hwctx->
act_dev, img_cnt, bind_info);
2551 if (ret != VK_SUCCESS) {
2571 VkAccessFlags2 *new_access)
2575 *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2576 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2579 *new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2580 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2583 *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2584 *new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_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_VIDEO_DECODE_DST_KHR;
2592 *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2595 *new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
2596 *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2599 *new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
2600 *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2614 VkImageLayout new_layout;
2615 VkAccessFlags2 new_access;
2618 uint32_t dst_qf = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2619 VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE;
2621 dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR;
2622 src_stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
2629 .data = (uint8_t *)hwfc,
2632 .data[0] = (uint8_t *)
frame,
2633 .hw_frames_ctx = &tmp_ref,
2636 VkCommandBuffer cmd_buf;
2638 cmd_buf = exec->
buf;
2644 VK_PIPELINE_STAGE_2_NONE,
2645 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
2651 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
2652 new_access, new_layout, dst_qf);
2654 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
2655 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2656 .pImageMemoryBarriers = img_bar,
2657 .imageMemoryBarrierCount = nb_img_bar,
2679 VkImageLayout new_layout;
2680 VkAccessFlags2 new_access;
2684 for (
i = 0;
i < p->vkctx.host_image_props.copyDstLayoutCount;
i++) {
2685 if (p->vkctx.host_image_props.pCopyDstLayouts[
i] == new_layout)
2688 if (
i == p->vkctx.host_image_props.copyDstLayoutCount)
2691 for (
i = 0;
i < nb_images;
i++) {
2692 layout_change[
i] = (VkHostImageLayoutTransitionInfoEXT) {
2693 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
2695 .oldLayout =
frame->layout[
i],
2696 .newLayout = new_layout,
2697 .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2698 .subresourceRange.layerCount = 1,
2699 .subresourceRange.levelCount = 1,
2701 frame->layout[
i] = new_layout;
2704 ret = vk->TransitionImageLayoutEXT(p->vkctx.hwctx->act_dev,
2705 nb_images, layout_change);
2706 if (ret != VK_SUCCESS) {
2720 if (hwfc_vk->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
2732 int frame_w,
int frame_h,
int plane)
2749 VkImageTiling tiling, VkImageUsageFlagBits
usage,
2750 VkImageCreateFlags
flags,
int nb_layers,
2762 VkSemaphoreTypeCreateInfo sem_type_info = {
2763 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
2764 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
2767 VkSemaphoreCreateInfo sem_spawn = {
2768 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
2769 .pNext = &sem_type_info,
2772 VkExportSemaphoreCreateInfo ext_sem_info_opaque = {
2773 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
2775 .handleTypes = IsWindows8OrGreater()
2776 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
2777 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
2779 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
2784 if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) {
2798 for (
int i = 0; (hwfc_vk->
format[
i] != VK_FORMAT_UNDEFINED);
i++) {
2799 VkImageCreateInfo create_info = {
2800 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2801 .pNext = create_pnext,
2802 .imageType = VK_IMAGE_TYPE_2D,
2806 .arrayLayers = nb_layers,
2809 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
2811 .samples = VK_SAMPLE_COUNT_1_BIT,
2812 .pQueueFamilyIndices = p->img_qfs,
2813 .queueFamilyIndexCount = p->nb_img_qfs,
2814 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2815 VK_SHARING_MODE_EXCLUSIVE,
2818 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
2821 ret = vk->CreateImage(hwctx->
act_dev, &create_info,
2823 if (ret != VK_SUCCESS) {
2831 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_spawn,
2833 if (ret != VK_SUCCESS) {
2840 f->queue_family[
i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2841 f->layout[
i] = create_info.initialLayout;
2843 f->sem_value[
i] = 0;
2859 VkExternalMemoryHandleTypeFlags *comp_handle_types,
2860 VkExternalMemoryHandleTypeFlags *iexp,
2861 VkExternalMemoryHandleTypeFlagBits
exp)
2869 const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info =
2871 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
2872 int has_mods = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info;
2875 VkExternalImageFormatProperties eprops = {
2876 .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
2878 VkImageFormatProperties2 props = {
2879 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
2882 VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
2883 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
2885 .pQueueFamilyIndices = p->img_qfs,
2886 .queueFamilyIndexCount = p->nb_img_qfs,
2887 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2888 VK_SHARING_MODE_EXCLUSIVE,
2890 VkPhysicalDeviceExternalImageFormatInfo enext = {
2891 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
2893 .pNext = has_mods ? &phy_dev_mod_info :
NULL,
2895 VkPhysicalDeviceImageFormatInfo2 pinfo = {
2896 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
2897 .pNext = !
exp ?
NULL : &enext,
2898 .format = hwctx->
format[0],
2899 .type = VK_IMAGE_TYPE_2D,
2901 .usage = hwctx->
usage,
2902 .flags = (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && has_mods) ?
2906 nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
2907 for (
int i = 0;
i < nb_mods;
i++) {
2909 phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[
i];
2911 ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->
phys_dev,
2915 av_log(hwfc,
AV_LOG_VERBOSE,
"GetPhysicalDeviceImageFormatProperties2: mod[%d]=0x%llx -> %s\n",
2916 i, (
unsigned long long)phy_dev_mod_info.drmFormatModifier,
2917 ret == VK_SUCCESS ?
"OK" :
"FAIL");
2918 if (ret == VK_SUCCESS) {
2920 *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
2921 if (
exp == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
2924 VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
2932 VkExternalMemoryHandleTypeFlags *comp_handle_types,
2933 VkExternalMemoryHandleTypeFlags *export_types)
2938 *comp_handle_types = 0x0;
2939 *export_types = 0x0;
2943 try_export_flags(hwfc, comp_handle_types, export_types, IsWindows8OrGreater()
2944 ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
2945 : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
2948 (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
2950 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
2953 hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
2955 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2967 VkExternalMemoryHandleTypeFlags e;
2970 VkExternalMemoryImageCreateInfo eiinfo = {
2971 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
2978 eminfo[
i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
2980 eminfo[
i].handleTypes = e;
2987 av_log(hwfc,
AV_LOG_ERROR,
"vulkan_pool_alloc failed: create_frame failed: %d\n", err);
2995 if ( (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
2996 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))
2998 else if (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)
3000 else if (hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)
3002 else if (hwctx->
usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
3069 if (p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY &&
3072 "NVIDIA drivers mishandle multi-plane images\n");
3076 const VkImageDrmFormatModifierListCreateInfoEXT *mod_list =
3078 VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
3079 int has_mods = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
3080 mod_list && mod_list->drmFormatModifierCount;
3081 int nb_mods = has_mods ? mod_list->drmFormatModifierCount : 1;
3084 if (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && !has_mods)
3087 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
3088 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
3089 .pQueueFamilyIndices = p->img_qfs,
3090 .queueFamilyIndexCount = p->nb_img_qfs,
3091 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3092 VK_SHARING_MODE_EXCLUSIVE,
3094 VkPhysicalDeviceImageFormatInfo2 pinfo = {
3095 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3096 .type = VK_IMAGE_TYPE_2D,
3098 .usage = hwctx->
usage,
3105 VkVideoProfileListInfoKHR profile_list;
3106 const VkVideoProfileListInfoKHR *pl =
3108 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
3111 profile_list.pNext =
NULL;
3115 VkImageFormatListCreateInfo format_list;
3116 const VkImageFormatListCreateInfo *fl =
3118 VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
3121 format_list.pNext =
NULL;
3128 hwctx->
format[
i] != VK_FORMAT_UNDEFINED;
i++) {
3129 pinfo.format = hwctx->
format[
i];
3133 for (
int j = 0; j < nb_mods; j++) {
3134 VkHostImageCopyDevicePerformanceQueryEXT perf = {
3135 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_COPY_DEVICE_PERFORMANCE_QUERY_EXT,
3137 VkImageFormatProperties2 props = {
3138 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3143 mod_info.drmFormatModifier = mod_list->pDrmFormatModifiers[j];
3145 ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->
phys_dev,
3147 if (ret != VK_SUCCESS) {
3149 "format %i is not supported: %s\n",
3154 if (!perf.optimalDeviceAccess) {
3156 "format %i has no optimal device access (identical "
3157 "memory layout: %i)\n",
3158 pinfo.format, perf.identicalMemoryLayout);
3164 if (!p->vkctx.host_image_props.identicalMemoryTypeRequirements) {
3166 VkExternalMemoryHandleTypeFlags e;
3167 VkExternalMemoryImageCreateInfo eiinfo = {
3168 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
3172 VkImageCreateInfo create_info = {
3173 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3174 .pNext = eiinfo.handleTypes ? &eiinfo : hwctx->
create_pnext,
3175 .imageType = VK_IMAGE_TYPE_2D,
3176 .format = hwctx->
format[0],
3182 .usage = hwctx->
usage,
3183 .samples = VK_SAMPLE_COUNT_1_BIT,
3184 .pQueueFamilyIndices = p->img_qfs,
3185 .queueFamilyIndexCount = p->nb_img_qfs,
3186 .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3187 VK_SHARING_MODE_EXCLUSIVE,
3189 VkDeviceImageMemoryRequirements req_info = {
3190 .sType = VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS,
3191 .pCreateInfo = &create_info,
3192 .planeAspect = hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT ?
3193 VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : 0,
3195 VkMemoryRequirements2 req = {
3196 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
3199 vk->GetDeviceImageMemoryRequirements(dev_hwctx->
act_dev, &req_info, &req);
3201 VkMemoryPropertyFlags req_flags = hwctx->
tiling == VK_IMAGE_TILING_LINEAR ?
3202 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
3203 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
3205 if (!(req.memoryRequirements.memoryTypeBits & (1U <<
index)))
3207 if ((p->mprops.memoryTypes[
index].propertyFlags & req_flags) == req_flags)
3210 if (
index == p->mprops.memoryTypeCount) {
3212 "no compatible memory type\n");
3228 VkImageUsageFlags supported_usage;
3231 int disable_multiplane = p->disable_multiplane ||
3233 int is_lone_dpb = ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) ||
3234 ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
3235 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)));
3242 if (p->use_linear_images &&
3243 (hwctx->
tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
3244 hwctx->
tiling = VK_IMAGE_TILING_LINEAR;
3254 if (hwctx->
format[0] != VK_FORMAT_UNDEFINED) {
3259 "for the current sw_format %s!\n",
3271 (hwctx->
usage & VK_IMAGE_USAGE_STORAGE_BIT));
3280 NULL, &supported_usage,
3283 (hwctx->
usage & VK_IMAGE_USAGE_STORAGE_BIT));
3292 int drm_mod_with_video = (hwctx->
tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
3294 VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR));
3296 if (!is_lone_dpb && !drm_mod_with_video) {
3298 hwctx->
usage |= supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
3299 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3300 VK_IMAGE_USAGE_STORAGE_BIT |
3301 VK_IMAGE_USAGE_SAMPLED_BIT);
3309 !(hwctx->
usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR))
3310 hwctx->
usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
3313 if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3316 hwctx->
usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
3322 int sampleable = hwctx->
usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
3323 VK_IMAGE_USAGE_STORAGE_BIT);
3324 hwctx->
img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
3326 hwctx->
img_flags |= VK_IMAGE_CREATE_ALIAS_BIT;
3328 hwctx->
img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
3337 if ((hwctx->
usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3340 const VkVideoProfileListInfoKHR *pl;
3343 hwctx->
img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3346 for (
i = 0;
i < pl->profileCount;
i++) {
3348 if (pl->pProfiles[
i].videoCodecOperation & 0xFFFF0000)
3351 if (
i == pl->profileCount)
3352 hwctx->
img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3357 if ((hwctx->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) &&
3359 hwctx->
usage &= ~VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
3390 VkImageDrmFormatModifierPropertiesEXT drm_mod = {
3391 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
3393 err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->
act_dev,
f->img[0],
3395 if (err != VK_SUCCESS) {
3401 VkDrmFormatModifierPropertiesListEXT modp;
3402 VkFormatProperties2 fmtp;
3403 VkDrmFormatModifierPropertiesEXT *mod_props =
NULL;
3405 modp = (VkDrmFormatModifierPropertiesListEXT) {
3406 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
3408 fmtp = (VkFormatProperties2) {
3409 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
3414 vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->
phys_dev, fmt->
fallback[
i], &fmtp);
3416 modp.pDrmFormatModifierProperties =
3417 av_calloc(modp.drmFormatModifierCount,
sizeof(*modp.pDrmFormatModifierProperties));
3418 if (!modp.pDrmFormatModifierProperties) {
3422 vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->
phys_dev, fmt->
fallback[
i], &fmtp);
3424 for (uint32_t j = 0; j < modp.drmFormatModifierCount; ++j) {
3425 VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[j];
3426 if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
3432 if (mod_props ==
NULL) {
3433 av_log(hwfc,
AV_LOG_ERROR,
"No DRM format modifier properties found for modifier 0x%016"PRIx64
"\n",
3434 drm_mod.drmFormatModifier);
3435 av_free(modp.pDrmFormatModifierProperties);
3441 av_free(modp.pDrmFormatModifierProperties);
3505static const struct {
3506 uint32_t drm_fourcc;
3508} vulkan_drm_format_map[] = {
3509 { DRM_FORMAT_R8, VK_FORMAT_R8_UNORM },
3510 { DRM_FORMAT_R16, VK_FORMAT_R16_UNORM },
3511 { DRM_FORMAT_GR88, VK_FORMAT_R8G8_UNORM },
3512 { DRM_FORMAT_RG88, VK_FORMAT_R8G8_UNORM },
3513 { DRM_FORMAT_GR1616, VK_FORMAT_R16G16_UNORM },
3514 { DRM_FORMAT_RG1616, VK_FORMAT_R16G16_UNORM },
3515 { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3516 { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3517 { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3518 { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3519 { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3520 { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3521 { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3522 { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3525#ifdef DRM_FORMAT_XYUV8888
3526 { DRM_FORMAT_XYUV8888, VK_FORMAT_R8G8B8A8_UNORM },
3527 { DRM_FORMAT_XVYU2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 } ,
3528 { DRM_FORMAT_XVYU12_16161616, VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 } ,
3529 { DRM_FORMAT_XVYU16161616, VK_FORMAT_R16G16B16A16_UNORM } ,
3533static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
3536 if (vulkan_drm_format_map[
i].drm_fourcc == drm_fourcc)
3537 return vulkan_drm_format_map[
i].vk_format;
3538 return VK_FORMAT_UNDEFINED;
3547 int bind_counts = 0;
3556 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3557 if (drm_to_vulkan_fmt(
desc->layers[
i].format) == VK_FORMAT_UNDEFINED) {
3559 desc->layers[
i].format);
3570 f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
3572 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3576 VkSemaphoreTypeCreateInfo sem_type_info = {
3577 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3578 .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
3581 VkSemaphoreCreateInfo sem_spawn = {
3582 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3583 .pNext = &sem_type_info,
3588 VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = {
3589 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
3590 .drmFormatModifier =
desc->objects[0].format_modifier,
3591 .drmFormatModifierPlaneCount =
planes,
3592 .pPlaneLayouts = (
const VkSubresourceLayout *)&ext_img_layouts,
3594 VkExternalMemoryImageCreateInfo ext_img_spec = {
3595 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
3596 .pNext = &ext_img_mod_spec,
3597 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3599 VkImageCreateInfo create_info = {
3600 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3601 .pNext = &ext_img_spec,
3602 .imageType = VK_IMAGE_TYPE_2D,
3603 .format = drm_to_vulkan_fmt(
desc->layers[
i].format),
3608 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
3609 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
3611 .samples = VK_SAMPLE_COUNT_1_BIT,
3612 .pQueueFamilyIndices =
p->img_qfs,
3613 .queueFamilyIndexCount =
p->nb_img_qfs,
3614 .sharingMode =
p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3615 VK_SHARING_MODE_EXCLUSIVE,
3626 if (sw_vkfmts && sw_vkfmts[
i] != VK_FORMAT_UNDEFINED)
3627 create_info.format = sw_vkfmts[
i];
3631 VkExternalImageFormatProperties ext_props = {
3632 .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
3634 VkImageFormatProperties2 props_ret = {
3635 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3636 .pNext = &ext_props,
3638 VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = {
3639 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
3640 .drmFormatModifier = ext_img_mod_spec.drmFormatModifier,
3641 .pQueueFamilyIndices = create_info.pQueueFamilyIndices,
3642 .queueFamilyIndexCount = create_info.queueFamilyIndexCount,
3643 .sharingMode = create_info.sharingMode,
3645 VkPhysicalDeviceExternalImageFormatInfo props_ext = {
3646 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3647 .pNext = &props_drm_mod,
3648 .handleType = ext_img_spec.handleTypes,
3650 VkPhysicalDeviceImageFormatInfo2 fmt_props;
3653 create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT |
3654 VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3656 create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT |
3657 VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3659 fmt_props = (VkPhysicalDeviceImageFormatInfo2) {
3660 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3661 .pNext = &props_ext,
3662 .format = create_info.format,
3663 .type = create_info.imageType,
3664 .tiling = create_info.tiling,
3665 .usage = create_info.usage,
3666 .flags = create_info.flags,
3670 ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev,
3671 &fmt_props, &props_ret);
3672 if (ret != VK_SUCCESS) {
3680 get_plane_wh(&create_info.extent.width, &create_info.extent.height,
3681 hwfc->sw_format,
src->width,
src->height,
i);
3684 for (
int j = 0; j <
planes; j++) {
3685 ext_img_layouts[j].offset =
desc->layers[
i].planes[j].offset;
3686 ext_img_layouts[j].rowPitch =
desc->layers[
i].planes[j].pitch;
3687 ext_img_layouts[j].size = 0;
3688 ext_img_layouts[j].arrayPitch = 0;
3689 ext_img_layouts[j].depthPitch = 0;
3693 ret = vk->CreateImage(hwctx->act_dev, &create_info,
3694 hwctx->alloc, &
f->img[
i]);
3695 if (ret != VK_SUCCESS) {
3702 ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
3703 hwctx->alloc, &
f->sem[
i]);
3704 if (ret != VK_SUCCESS) {
3711 f->queue_family[
i] = VK_QUEUE_FAMILY_EXTERNAL;
3712 f->layout[
i] = create_info.initialLayout;
3714 f->sem_value[
i] = 0;
3717 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3719 VkImageMemoryRequirementsInfo2 req_desc = {
3720 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
3723 VkMemoryDedicatedRequirements ded_req = {
3724 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
3726 VkMemoryRequirements2 req2 = {
3727 .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
3732 VkMemoryFdPropertiesKHR fdmp = {
3733 .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
3739 VkImportMemoryFdInfoKHR idesc = {
3740 .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
3741 .fd = dup(
desc->objects[
desc->layers[
i].planes[0].object_index].fd),
3742 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3744 VkMemoryDedicatedAllocateInfo ded_alloc = {
3745 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
3747 .image = req_desc.image,
3751 ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev,
3752 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3754 if (ret != VK_SUCCESS) {
3762 vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2);
3765 req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits;
3768 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
3769 (ded_req.prefersDedicatedAllocation ||
3770 ded_req.requiresDedicatedAllocation) ?
3771 &ded_alloc : ded_alloc.pNext,
3772 &
f->flags, &
f->mem[
i]);
3778 f->size[
i] = req2.memoryRequirements.size;
3781 for (
int i = 0;
i <
desc->nb_layers;
i++) {
3783 for (
int j = 0; j <
planes; j++) {
3784 VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
3785 j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
3786 VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
3788 plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
3790 plane_info[bind_counts].planeAspect = aspect;
3792 bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
3794 bind_info[bind_counts].image =
f->img[
i];
3795 bind_info[bind_counts].memory =
f->mem[
i];
3798 bind_info[bind_counts].memoryOffset = 0;
3805 ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
3806 if (ret != VK_SUCCESS) {
3834#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
3836 VkCommandBuffer cmd_buf;
3842 for (
int i = 0;
i <
desc->nb_objects;
i++) {
3843 VkSemaphoreTypeCreateInfo sem_type_info = {
3844 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3845 .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
3847 VkSemaphoreCreateInfo sem_spawn = {
3848 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3849 .pNext = &sem_type_info,
3851 VkImportSemaphoreFdInfoKHR import_info;
3852 struct dma_buf_export_sync_file implicit_fd_info = {
3853 .flags = DMA_BUF_SYNC_READ,
3857 if (ioctl(
desc->objects[
i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
3858 &implicit_fd_info)) {
3863 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3867 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_spawn,
3868 hwctx->
alloc, &drm_sync_sem[
i]);
3869 if (ret != VK_SUCCESS) {
3874 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3878 import_info = (VkImportSemaphoreFdInfoKHR) {
3879 .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
3880 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
3881 .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
3882 .semaphore = drm_sync_sem[
i],
3883 .fd = implicit_fd_info.fd,
3886 ret = vk->ImportSemaphoreFdKHR(hwctx->
act_dev, &import_info);
3887 if (ret != VK_SUCCESS) {
3892 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3898 cmd_buf = exec->
buf;
3902 for (
int i = 0;
i <
desc->nb_objects;
i++)
3903 vk->DestroySemaphore(hwctx->
act_dev, drm_sync_sem[
i], hwctx->
alloc);
3909 drm_sync_sem,
desc->nb_objects,
3910 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 1);
3913 VK_PIPELINE_STAGE_2_NONE,
3914 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
3921 VK_PIPELINE_STAGE_2_NONE,
3922 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
3924 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : 0x0) |
3926 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT : 0x0),
3927 VK_IMAGE_LAYOUT_GENERAL,
3928 p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED :
p->img_qfs[0]);
3930 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
3931 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
3932 .pImageMemoryBarriers = img_bar,
3933 .imageMemoryBarrierCount = nb_img_bar,
3944 "image may be corrupted.\n");
3960 if ((err = vulkan_map_from_drm_frame_desc(hwfc, &
f,
src,
flags)))
3964 dst->data[0] = (uint8_t *)
f;
3966 dst->height =
src->height;
3969 &vulkan_unmap_from_drm,
f);
3973 err = vulkan_map_from_drm_frame_sync(hwfc,
dst,
desc,
flags);
3996 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)
src->data[3];
4002 vaSyncSurface(vaapi_ctx->
display, surface_id);
4010 err = vulkan_map_from_drm(dst_fc,
dst,
tmp,
flags);
4027 VkDeviceMemory mem,
size_t size)
4035 CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
4036 .type = IsWindows8OrGreater()
4037 ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
4038 : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
4041 VkMemoryGetWin32HandleInfoKHR export_info = {
4042 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
4044 .handleType = IsWindows8OrGreater()
4045 ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
4046 : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
4049 ret = vk->GetMemoryWin32HandleKHR(hwctx->
act_dev, &export_info,
4050 &ext_desc.handle.win32.handle);
4051 if (ret != VK_SUCCESS) {
4056 dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
4058 CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
4059 .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
4062 VkMemoryGetFdInfoKHR export_info = {
4063 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
4065 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
4068 ret = vk->GetMemoryFdKHR(hwctx->
act_dev, &export_info,
4069 &ext_desc.handle.fd);
4070 if (ret != VK_SUCCESS) {
4077 ret =
CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
4080 close(ext_desc.handle.fd);
4099 VkSemaphoreGetWin32HandleInfoKHR sem_export = {
4100 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
4102 .handleType = IsWindows8OrGreater()
4103 ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
4104 : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
4106 CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
4110 VkSemaphoreGetFdInfoKHR sem_export = {
4111 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
4113 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
4115 CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
4121 ret = vk->GetSemaphoreWin32HandleKHR(hwctx->
act_dev, &sem_export,
4122 &ext_sem_desc.handle.win32.handle);
4124 ret = vk->GetSemaphoreFdKHR(hwctx->
act_dev, &sem_export,
4125 &ext_sem_desc.handle.fd);
4127 if (ret != VK_SUCCESS) {
4133 dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
4136 ret =
CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
4140 close(ext_sem_desc.handle.fd);
4168 CudaFunctions *cu = cu_internal->
cuda_dl;
4169 CUarray_format cufmt =
desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
4170 CU_AD_FORMAT_UNSIGNED_INT8;
4171 const int elem_size = 1 + (
desc->comp[0].depth > 8);
4174 dst_int = dst_f->internal;
4176 if (!dst_int->cuda_fc_ref) {
4180 if (!dst_int->cuda_fc_ref)
4184 for (
int i = 0;
i < nb_images;
i++) {
4185 err = export_mem_to_cuda(
ctx, cuda_cu, cu, dst_int,
i,
4186 dst_f->mem[
i], dst_f->size[
i]);
4190 err = export_sem_to_cuda(
ctx, cuda_cu, cu, dst_int,
i,
4196 if (nb_images !=
planes) {
4200 if (
desc->comp[
i].step / elem_size > 1) {
4202 "Cannot map a multiplane Vulkan image (%d image(s) "
4203 "for %d plane(s)) to CUDA; create the Vulkan device "
4204 "with the disable_multiplane=1 option (one image per "
4205 "plane) for CUDA interop.\n", nb_images,
planes);
4210 VkImageSubresource subres = {
4211 .aspectMask =
i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
4212 i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
4213 VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
4215 VkSubresourceLayout
layout = { 0 };
4216 vk->GetImageSubresourceLayout(hwctx->
act_dev, dst_f->img[
FFMIN(
i, nb_images - 1)],
4223 CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
4228 .NumChannels =
desc->comp[
i].step / elem_size,
4236 tex_desc.arrayDesc.Width = p_w;
4237 tex_desc.arrayDesc.Height = p_h;
4239 ret =
CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[
i],
4240 dst_int->ext_mem[
FFMIN(
i, nb_images - 1)],
4247 ret =
CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[
i],
4248 dst_int->cu_mma[
i], 0));
4281 CudaFunctions *cu = cu_internal->
cuda_dl;
4292 err =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
4296 err = vulkan_export_to_cuda(hwfc,
src->hw_frames_ctx,
dst);
4302 dst_int = dst_f->internal;
4304 for (
int i = 0;
i < nb_images;
i++) {
4305 s_w_par[
i].params.fence.value = dst_f->sem_value[
i] + 0;
4306 s_s_par[
i].params.fence.value = dst_f->sem_value[
i] + 1;
4309 err =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
4310 nb_images, cuda_dev->stream));
4315 CUDA_MEMCPY2D cpy = {
4316 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
4317 .srcDevice = (CUdeviceptr)
src->data[
i],
4318 .srcPitch =
src->linesize[
i],
4321 .dstMemoryType = CU_MEMORYTYPE_ARRAY,
4322 .dstArray = dst_int->cu_array[
i],
4328 cpy.WidthInBytes = p_w *
desc->comp[
i].step;
4331 err =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
4336 err =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
4337 nb_images, cuda_dev->stream));
4341 for (
int i = 0;
i < nb_images;
i++)
4342 dst_f->sem_value[
i]++;
4363 switch (
src->format) {
4368 return vulkan_map_from_vaapi(hwfc,
dst,
src,
flags);
4374 return vulkan_map_from_drm(hwfc,
dst,
src,
flags);
4384typedef struct VulkanDRMMapping {
4385 AVDRMFrameDescriptor drm_desc;
4403static inline uint32_t vulkan_fmt_to_drm(
VkFormat vkfmt)
4406 if (vulkan_drm_format_map[
i].vk_format == vkfmt)
4407 return vulkan_drm_format_map[
i].drm_fourcc;
4408 return DRM_FORMAT_INVALID;
4411#define MAX_MEMORY_PLANES 4
4412static VkImageAspectFlags plane_index_to_aspect(
int plane) {
4413 if (plane == 0)
return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4414 if (plane == 1)
return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
4415 if (plane == 2)
return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
4416 if (plane == 3)
return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT;
4419 return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4422#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
4432 if (
f->internal->drm_sync_sem == VK_NULL_HANDLE) {
4433 VkExportSemaphoreCreateInfo exp_info = {
4434 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
4435 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
4437 VkSemaphoreTypeCreateInfo type_info = {
4438 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
4440 .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
4442 VkSemaphoreCreateInfo sem_create = {
4443 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
4444 .pNext = &type_info,
4446 ret = vk->CreateSemaphore(hwctx->
act_dev, &sem_create, hwctx->
alloc,
4447 &
f->internal->drm_sync_sem);
4448 if (ret != VK_SUCCESS) {
4460 for (
int i = 0;
i < nb_sems;
i++)
4463 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
4465 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 0);
4467 VkSemaphoreGetFdInfoKHR get_fd_info = {
4468 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
4469 .semaphore =
f->internal->drm_sync_sem,
4470 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
4472 ret = vk->GetSemaphoreFdKHR(hwctx->
act_dev, &get_fd_info, &sync_fd);
4473 if (ret != VK_SUCCESS) {
4475 "Failed to get sync fd from DRM map export semaphore: %s\n",
4498 VkImageDrmFormatModifierPropertiesEXT drm_mod = {
4499 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
4501 const int nb_sems = nb_images;
4502 int free_drm_desc_on_err = 1;
4513#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
4515 f->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
4516 vk->GetSemaphoreFdKHR && vk->CreateSemaphore) {
4517 err = vulkan_drm_export_sync_fd(hwfc,
f, fp, nb_sems);
4526 VkSemaphoreWaitInfo wait_info = {
4527 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4529 .semaphoreCount = nb_sems,
4530 .pSemaphores =
f->sem,
4531 .pValues =
f->sem_value,
4533 vk->WaitSemaphores(hwctx->
act_dev, &wait_info, UINT64_MAX);
4541 free_drm_desc_on_err = 0;
4543 ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->
act_dev,
f->img[0],
4545 if (ret != VK_SUCCESS) {
4551 for (
int i = 0; (
i <
planes) && (
f->mem[
i]);
i++) {
4552 VkMemoryGetFdInfoKHR export_info = {
4553 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
4554 .memory =
f->mem[
i],
4555 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
4558 ret = vk->GetMemoryFdKHR(hwctx->
act_dev, &export_info,
4560 if (ret != VK_SUCCESS) {
4566#if HAVE_LINUX_DMA_BUF_H && defined(DMA_BUF_IOCTL_IMPORT_SYNC_FILE)
4568 int dup_fd = dup(sync_fd);
4570 struct dma_buf_import_sync_file import_info = {
4571 .flags = DMA_BUF_SYNC_WRITE,
4574 if (ioctl(drm_desc->
objects[
i].
fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import_info) < 0)
4593 drm_desc->
layers[
i].
format = vulkan_fmt_to_drm(plane_vkfmt);
4603 VkSubresourceLayout
layout;
4604 int aspect_plane = (nb_images == 1) ?
i : j;
4605 VkImageSubresource sub = {
4606 .aspectMask = plane_index_to_aspect(aspect_plane),
4623 if (
f->tiling == VK_IMAGE_TILING_OPTIMAL)
4629 dst->height =
src->height;
4630 dst->data[0] = (uint8_t *)drm_desc;
4643 if (free_drm_desc_on_err)
4683 switch (
dst->format) {
4693 return vulkan_map_to_vaapi(hwfc,
dst,
src,
flags);
4705 AVFrame *swf, VkBufferImageCopy *region,
4714 region[
i].bufferRowLength,
4718 region[
i].imageExtent.height);
4721 if (err != VK_SUCCESS) {
4728 if (err != VK_SUCCESS) {
4738 region[
i].bufferRowLength,
4740 region[
i].imageExtent.height);
4747 AVFrame *swf, VkBufferImageCopy *region,
int upload)
4754 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4755 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4757 size_t buf_offset = 0;
4761 region[
i] = (VkBufferImageCopy) {
4762 .bufferOffset = buf_offset,
4764 p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
4765 .bufferImageHeight = p_h,
4766 .imageSubresource.layerCount = 1,
4767 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4771 buf_offset +=
FFALIGN(p_h*region[
i].bufferRowLength,
4772 p->props.properties.limits.optimalBufferCopyOffsetAlignment);
4777 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
4778 p->vkctx.host_cached_flag);
4786 AVFrame *swf, VkBufferImageCopy *region,
int upload)
4794 VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4795 VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4799 while (swf->
buf[nb_src_bufs])
4803 if (nb_src_bufs == 1) {
4805 swf->
data[0], VK_WHOLE_SIZE, swf->
buf[0],
4812 region[
i].bufferOffset =
dst[0]->virtual_offset +
4814 }
else if (nb_src_bufs ==
planes) {
4817 swf->
data[
i], VK_WHOLE_SIZE,
4818 swf->
buf[
i], buf_usage);
4823 region[
i].bufferOffset =
dst[
i]->virtual_offset;
4844 for (
int i = 0;
i < (*nb_bufs);
i++)
4865 int nb_layout_ch = 0;
4869 for (
int i = 0;
i < nb_images;
i++) {
4871 for (
int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
4872 if (hwf_vk->
layout[
i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
4882 layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
4883 .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
4884 .image = hwf_vk->
img[
i],
4885 .oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
4886 .newLayout = VK_IMAGE_LAYOUT_GENERAL,
4887 .subresourceRange = {
4888 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
4894 hwf_vk->
layout[
i] = layout_ch_info[nb_layout_ch].newLayout;
4899 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4900 .pSemaphores = hwf_vk->
sem,
4902 .semaphoreCount = nb_images,
4908 vk->TransitionImageLayoutEXT(hwctx->
act_dev,
4909 nb_layout_ch, layout_ch_info);
4912 VkMemoryToImageCopyEXT region_info = {
4913 .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
4914 .imageSubresource = {
4918 VkCopyMemoryToImageInfoEXT copy_info = {
4919 .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
4921 .pRegions = ®ion_info,
4924 int img_idx =
FFMIN(
i, (nb_images - 1));
4928 region_info.pHostPointer = swf->
data[
i];
4929 region_info.memoryRowLength = swf->
linesize[
i] /
desc->comp[
i].step;
4931 region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4932 copy_info.dstImage = hwf_vk->
img[img_idx];
4933 copy_info.dstImageLayout = hwf_vk->
layout[img_idx];
4935 vk->CopyMemoryToImageEXT(hwctx->
act_dev, ©_info);
4938 VkImageToMemoryCopyEXT region_info = {
4939 .sType = VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,
4940 .imageSubresource = {
4944 VkCopyImageToMemoryInfoEXT copy_info = {
4945 .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,
4947 .pRegions = ®ion_info,
4950 int img_idx =
FFMIN(
i, (nb_images - 1));
4954 region_info.pHostPointer = swf->
data[
i];
4955 region_info.memoryRowLength = swf->
linesize[
i] /
desc->comp[
i].step;
4957 region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4958 copy_info.srcImage = hwf_vk->
img[img_idx];
4959 copy_info.srcImageLayout = hwf_vk->
layout[img_idx];
4961 vk->CopyImageToMemoryEXT(hwctx->
act_dev, ©_info);
4980 int host_mapped = 0;
4995 VkCommandBuffer cmd_buf;
5007 int host_copy = hwctx->
usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
5009 !p->avoid_host_import;
5015 host_copy = host_map = 0;
5018 if (!upload && host_copy) {
5019 for (
int i = 0;
i < nb_images;
i++) {
5021 for (
int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
5022 if (hwf_vk->
layout[
i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
5042 region[
i] = (VkBufferImageCopy) {
5045 .bufferImageHeight = p_h,
5046 .imageSubresource.layerCount = 1,
5047 .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
5073 cmd_buf = exec->
buf;
5081 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
5082 VK_PIPELINE_STAGE_2_TRANSFER_BIT);
5100 for (
int i = 0;
i < nb_bufs;
i++)
5105 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
5106 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
5107 upload ? VK_ACCESS_TRANSFER_WRITE_BIT :
5108 VK_ACCESS_TRANSFER_READ_BIT,
5109 upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
5110 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
5111 p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
5113 vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
5114 .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
5115 .pImageMemoryBarriers = img_bar,
5116 .imageMemoryBarrierCount = nb_img_bar,
5120 int buf_idx =
FFMIN(
i, (nb_bufs - 1));
5121 int img_idx =
FFMIN(
i, (nb_images - 1));
5124 uint32_t orig_stride = region[
i].bufferRowLength;
5125 region[
i].bufferRowLength /=
desc->comp[
i].step;
5129 vk->CmdCopyBufferToImage(cmd_buf, vkbuf->
buf,
5130 hwf_vk->
img[img_idx],
5131 img_bar[img_idx].newLayout,
5134 vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->
img[img_idx],
5135 img_bar[img_idx].newLayout,
5139 region[
i].bufferRowLength = orig_stride;
5143 if (err >= 0 && !upload) {
5150 for (
int i = 0;
i < nb_bufs;
i++)
5161 switch (
src->format) {
5171 return vulkan_transfer_data_from_cuda(hwfc,
dst,
src);
5175 if (
src->hw_frames_ctx)
5200 CudaFunctions *cu = cu_internal->
cuda_dl;
5211 err =
CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
5215 err = vulkan_export_to_cuda(hwfc,
dst->hw_frames_ctx,
src);
5221 dst_int = dst_f->internal;
5223 for (
int i = 0;
i < nb_images;
i++) {
5224 s_w_par[
i].params.fence.value = dst_f->sem_value[
i] + 0;
5225 s_s_par[
i].params.fence.value = dst_f->sem_value[
i] + 1;
5228 err =
CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
5229 nb_images, cuda_dev->stream));
5234 CUDA_MEMCPY2D cpy = {
5235 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
5236 .dstDevice = (CUdeviceptr)
dst->data[
i],
5237 .dstPitch =
dst->linesize[
i],
5240 .srcMemoryType = CU_MEMORYTYPE_ARRAY,
5241 .srcArray = dst_int->cu_array[
i],
5247 cpy.WidthInBytes =
w *
desc->comp[
i].step;
5250 err =
CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
5255 err =
CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
5256 nb_images, cuda_dev->stream));
5260 for (
int i = 0;
i < nb_images;
i++)
5261 dst_f->sem_value[
i]++;
5282 switch (
dst->format) {
5292 return vulkan_transfer_data_to_cuda(hwfc,
dst,
src);
5296 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_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.