FFmpeg
hwcontext_vulkan.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Lynne
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #define VK_NO_PROTOTYPES
22 #define VK_ENABLE_BETA_EXTENSIONS
23 
24 #ifdef _WIN32
25 #include <windows.h> /* Included to prevent conflicts with CreateSemaphore */
26 #include <versionhelpers.h>
27 #include "compat/w32dlfcn.h"
28 #else
29 #include <dlfcn.h>
30 #include <unistd.h>
31 #endif
32 
33 #include "thread.h"
34 
35 #include "config.h"
36 #include "pixdesc.h"
37 #include "avstring.h"
38 #include "imgutils.h"
39 #include "hwcontext.h"
40 #include "hwcontext_internal.h"
41 #include "hwcontext_vulkan.h"
42 #include "mem.h"
43 
44 #include "vulkan.h"
45 #include "vulkan_loader.h"
46 
47 #if CONFIG_VAAPI
48 #include "hwcontext_vaapi.h"
49 #endif
50 
51 #if CONFIG_LIBDRM
52 #if CONFIG_VAAPI
53 #include <va/va_drmcommon.h>
54 #endif
55 #ifdef __linux__
56 #include <sys/sysmacros.h>
57 #endif
58 #include <sys/stat.h>
59 #include <xf86drm.h>
60 #include <drm_fourcc.h>
61 #include "hwcontext_drm.h"
62 #endif
63 
64 #if HAVE_LINUX_DMA_BUF_H
65 #include <sys/ioctl.h>
66 #include <linux/dma-buf.h>
67 #endif
68 
69 #if CONFIG_CUDA
71 #include "cuda_check.h"
72 #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x)
73 #endif
74 
75 typedef struct VulkanDeviceFeatures {
76  VkPhysicalDeviceFeatures2 device;
77 
78  VkPhysicalDeviceVulkan11Features vulkan_1_1;
79  VkPhysicalDeviceVulkan12Features vulkan_1_2;
80  VkPhysicalDeviceVulkan13Features vulkan_1_3;
81  VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore;
82  VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate;
83  VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy;
84  VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR explicit_mem_layout;
85 
86 #ifdef VK_EXT_shader_long_vector
87  VkPhysicalDeviceShaderLongVectorFeaturesEXT long_vector;
88 #endif
89 
90 #ifdef VK_EXT_shader_replicated_composites
91  VkPhysicalDeviceShaderReplicatedCompositesFeaturesEXT replicated_composites;
92 #endif
93 
94 #ifdef VK_EXT_zero_initialize_device_memory
95  VkPhysicalDeviceZeroInitializeDeviceMemoryFeaturesEXT zero_initialize;
96 #endif
97 
98 #ifdef VK_KHR_shader_expect_assume
99  VkPhysicalDeviceShaderExpectAssumeFeaturesKHR expect_assume;
100 #endif
101 
102  VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1;
103 #ifdef VK_KHR_video_maintenance2
104  VkPhysicalDeviceVideoMaintenance2FeaturesKHR video_maintenance_2;
105 #endif
106 #ifdef VK_KHR_video_decode_vp9
107  VkPhysicalDeviceVideoDecodeVP9FeaturesKHR vp9_decode;
108 #endif
109 #ifdef VK_KHR_video_encode_av1
110  VkPhysicalDeviceVideoEncodeAV1FeaturesKHR av1_encode;
111 #endif
112 
113  VkPhysicalDeviceShaderObjectFeaturesEXT shader_object;
114  VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix;
115  VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float;
116 
117 #ifdef VK_KHR_shader_relaxed_extended_instruction
118  VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instruction;
119 #endif
121 
122 typedef struct VulkanDevicePriv {
123  /**
124  * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it.
125  */
127 
128  /* Vulkan library and loader functions */
129  void *libvulkan;
130 
134 
135  /* Properties */
136  VkPhysicalDeviceProperties2 props;
137  VkPhysicalDeviceMemoryProperties mprops;
138  VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
139  VkPhysicalDeviceDriverProperties dprops;
140 
141  /* Opaque FD external semaphore properties */
142  VkExternalSemaphoreProperties ext_sem_props_opaque;
143 
144  /* Enabled features */
146 
147  /* Queues */
149  uint32_t nb_tot_qfs;
150  uint32_t img_qfs[64];
151  uint32_t nb_img_qfs;
152 
153  /* Debug callback */
154  VkDebugUtilsMessengerEXT debug_ctx;
155 
156  /* Settings */
158 
159  /* Option to allocate all image planes in a single allocation */
161 
162  /* Disable multiplane images */
164 
165  /* Prefer memcpy over dynamic host pointer imports */
167 
168  /* Maximum queues */
171 
172 typedef struct VulkanFramesPriv {
173  /**
174  * The public AVVulkanFramesContext. See hwcontext_vulkan.h for it.
175  */
177 
178  /* Image conversions */
180 
181  /* Image transfers */
184 
185  /* Temporary buffer pools */
187 
188  /* Modifier info list to free at uninit */
189  VkImageDrmFormatModifierListCreateInfoEXT *modifier_info;
190 
191  /* Properties for DRM modifier for each plane in the image */
192  VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5];
194 
195 typedef struct AVVkFrameInternal {
197 
198 #if CONFIG_CUDA
199  /* Importing external memory into cuda is really expensive so we keep the
200  * memory imported all the time */
201  AVBufferRef *cuda_fc_ref; /* Need to keep it around for uninit */
202  CUexternalMemory ext_mem[AV_NUM_DATA_POINTERS];
203  CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS];
204  CUarray cu_array[AV_NUM_DATA_POINTERS];
205  CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS];
206 #ifdef _WIN32
207  HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS];
208  HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS];
209 #endif
210 #endif
212 
213 /* Initialize all structs in VulkanDeviceFeatures */
215 {
216  VulkanDevicePriv *p = ctx->hwctx;
217  FFVulkanContext *s = &p->vkctx;
218 
219  feats->device = (VkPhysicalDeviceFeatures2) {
220  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
221  };
222 
224  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
226  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
228  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
229 
231  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES);
233  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_ROTATE_FEATURES_KHR);
235  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_FEATURES_EXT);
236 
237 #ifdef VK_EXT_shader_long_vector
238  FF_VK_STRUCT_EXT(s, &feats->device, &feats->long_vector, FF_VK_EXT_LONG_VECTOR,
239  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_LONG_VECTOR_FEATURES_EXT);
240 #endif
241 
242 #ifdef VK_EXT_shader_replicated_composites
243  FF_VK_STRUCT_EXT(s, &feats->device, &feats->replicated_composites, FF_VK_EXT_REPLICATED_COMPOSITES,
244  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_REPLICATED_COMPOSITES_FEATURES_EXT);
245 #endif
246 
247 #ifdef VK_EXT_zero_initialize_device_memory
248  FF_VK_STRUCT_EXT(s, &feats->device, &feats->zero_initialize, FF_VK_EXT_ZERO_INITIALIZE,
249  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_DEVICE_MEMORY_FEATURES_EXT);
250 #endif
251 
252 #ifdef VK_KHR_shader_expect_assume
253  FF_VK_STRUCT_EXT(s, &feats->device, &feats->expect_assume, FF_VK_EXT_EXPECT_ASSUME,
254  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_EXPECT_ASSUME_FEATURES_KHR);
255 #endif
256 
258  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
259 #ifdef VK_KHR_video_maintenance2
260  FF_VK_STRUCT_EXT(s, &feats->device, &feats->video_maintenance_2, FF_VK_EXT_VIDEO_MAINTENANCE_2,
261  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_2_FEATURES_KHR);
262 #endif
263 #ifdef VK_KHR_video_decode_vp9
264  FF_VK_STRUCT_EXT(s, &feats->device, &feats->vp9_decode, FF_VK_EXT_VIDEO_DECODE_VP9,
265  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_DECODE_VP9_FEATURES_KHR);
266 #endif
267 #ifdef VK_KHR_video_encode_av1
268  FF_VK_STRUCT_EXT(s, &feats->device, &feats->av1_encode, FF_VK_EXT_VIDEO_ENCODE_AV1,
269  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_ENCODE_AV1_FEATURES_KHR);
270 #endif
271 
273  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
275  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
277  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
279  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR);
280 
281 #ifdef VK_KHR_shader_relaxed_extended_instruction
282  FF_VK_STRUCT_EXT(s, &feats->device, &feats->relaxed_extended_instruction, FF_VK_EXT_RELAXED_EXTENDED_INSTR,
283  VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR);
284 #endif
285 }
286 
287 /* Copy all needed device features */
289 {
290 #define COPY_VAL(VAL) \
291  do { \
292  dst->VAL = src->VAL; \
293  } while (0) \
294 
295  COPY_VAL(device.features.shaderImageGatherExtended);
296  COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
297  COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
298  COPY_VAL(device.features.fragmentStoresAndAtomics);
299  COPY_VAL(device.features.vertexPipelineStoresAndAtomics);
300  COPY_VAL(device.features.shaderInt64);
301  COPY_VAL(device.features.shaderInt16);
302  COPY_VAL(device.features.shaderFloat64);
303  COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
304  COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
305 
306  COPY_VAL(vulkan_1_1.samplerYcbcrConversion);
307  COPY_VAL(vulkan_1_1.storagePushConstant16);
308  COPY_VAL(vulkan_1_1.storageBuffer16BitAccess);
309  COPY_VAL(vulkan_1_1.uniformAndStorageBuffer16BitAccess);
310 
311  COPY_VAL(vulkan_1_2.timelineSemaphore);
312  COPY_VAL(vulkan_1_2.scalarBlockLayout);
313  COPY_VAL(vulkan_1_2.bufferDeviceAddress);
314  COPY_VAL(vulkan_1_2.hostQueryReset);
315  COPY_VAL(vulkan_1_2.storagePushConstant8);
316  COPY_VAL(vulkan_1_2.shaderInt8);
317  COPY_VAL(vulkan_1_2.storageBuffer8BitAccess);
318  COPY_VAL(vulkan_1_2.uniformAndStorageBuffer8BitAccess);
319  COPY_VAL(vulkan_1_2.shaderFloat16);
320  COPY_VAL(vulkan_1_2.shaderBufferInt64Atomics);
321  COPY_VAL(vulkan_1_2.shaderSharedInt64Atomics);
322  COPY_VAL(vulkan_1_2.vulkanMemoryModel);
323  COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
324  COPY_VAL(vulkan_1_2.vulkanMemoryModelAvailabilityVisibilityChains);
325  COPY_VAL(vulkan_1_2.uniformBufferStandardLayout);
326  COPY_VAL(vulkan_1_2.runtimeDescriptorArray);
327  COPY_VAL(vulkan_1_2.shaderSubgroupExtendedTypes);
328  COPY_VAL(vulkan_1_2.shaderUniformBufferArrayNonUniformIndexing);
329  COPY_VAL(vulkan_1_2.shaderSampledImageArrayNonUniformIndexing);
330  COPY_VAL(vulkan_1_2.shaderStorageBufferArrayNonUniformIndexing);
331  COPY_VAL(vulkan_1_2.shaderStorageImageArrayNonUniformIndexing);
332 
333  COPY_VAL(vulkan_1_3.dynamicRendering);
334  COPY_VAL(vulkan_1_3.maintenance4);
335  COPY_VAL(vulkan_1_3.synchronization2);
336  COPY_VAL(vulkan_1_3.computeFullSubgroups);
337  COPY_VAL(vulkan_1_3.subgroupSizeControl);
338  COPY_VAL(vulkan_1_3.shaderZeroInitializeWorkgroupMemory);
339  COPY_VAL(vulkan_1_3.dynamicRendering);
340 
341  COPY_VAL(timeline_semaphore.timelineSemaphore);
342  COPY_VAL(subgroup_rotate.shaderSubgroupRotate);
343  COPY_VAL(host_image_copy.hostImageCopy);
344 
345 #ifdef VK_EXT_shader_long_vector
346  COPY_VAL(long_vector.longVector);
347 #endif
348 
349 #ifdef VK_EXT_shader_replicated_composites
350  COPY_VAL(replicated_composites.shaderReplicatedComposites);
351 #endif
352 
353 #ifdef VK_EXT_zero_initialize_device_memory
354  COPY_VAL(zero_initialize.zeroInitializeDeviceMemory);
355 #endif
356 
357  COPY_VAL(video_maintenance_1.videoMaintenance1);
358 #ifdef VK_KHR_video_maintenance2
359  COPY_VAL(video_maintenance_2.videoMaintenance2);
360 #endif
361 
362 #ifdef VK_KHR_video_decode_vp9
363  COPY_VAL(vp9_decode.videoDecodeVP9);
364 #endif
365 
366 #ifdef VK_KHR_video_encode_av1
367  COPY_VAL(av1_encode.videoEncodeAV1);
368 #endif
369 
370  COPY_VAL(shader_object.shaderObject);
371 
372  COPY_VAL(cooperative_matrix.cooperativeMatrix);
373 
374  COPY_VAL(atomic_float.shaderBufferFloat32Atomics);
375  COPY_VAL(atomic_float.shaderBufferFloat32AtomicAdd);
376 
377  COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout);
378  COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayoutScalarBlockLayout);
379  COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout8BitAccess);
380  COPY_VAL(explicit_mem_layout.workgroupMemoryExplicitLayout16BitAccess);
381 
382 #ifdef VK_KHR_shader_relaxed_extended_instruction
383  COPY_VAL(relaxed_extended_instruction.shaderRelaxedExtendedInstruction);
384 #endif
385 
386 #ifdef VK_KHR_shader_expect_assume
387  COPY_VAL(expect_assume.shaderExpectAssume);
388 #endif
389 
390 #undef COPY_VAL
391 }
392 
393 #define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
394 #define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
395 
396 static const struct FFVkFormatEntry {
399  VkImageAspectFlags aspect;
403  const VkFormat fallback[5];
404 } vk_formats_list[] = {
405  /* Gray formats */
406  { VK_FORMAT_R8_UNORM, AV_PIX_FMT_GRAY8, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8_UNORM } },
407  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
408  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY12, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
409  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY14, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
410  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GRAY16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
411  { VK_FORMAT_R32_UINT, AV_PIX_FMT_GRAY32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_UINT } },
412  { VK_FORMAT_R32_SFLOAT, AV_PIX_FMT_GRAYF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32_SFLOAT } },
413 
414  /* RGB formats */
415  { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGRA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM } },
416  { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGBA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
417  { VK_FORMAT_R8G8B8_UNORM, AV_PIX_FMT_RGB24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8_UNORM } },
418  { VK_FORMAT_B8G8R8_UNORM, AV_PIX_FMT_BGR24, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8_UNORM } },
419  { VK_FORMAT_R16G16B16_UNORM, AV_PIX_FMT_RGB48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16_UNORM } },
420  { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_RGBA64, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
421  { VK_FORMAT_R5G6B5_UNORM_PACK16, AV_PIX_FMT_RGB565, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R5G6B5_UNORM_PACK16 } },
422  { VK_FORMAT_B5G6R5_UNORM_PACK16, AV_PIX_FMT_BGR565, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B5G6R5_UNORM_PACK16 } },
423  { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_BGR0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM } },
424  { VK_FORMAT_R8G8B8A8_UNORM, AV_PIX_FMT_RGB0, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
425  { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_X2RGB10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2R10G10B10_UNORM_PACK32 } },
426  { VK_FORMAT_A2B10G10R10_UNORM_PACK32, AV_PIX_FMT_X2BGR10, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_A2B10G10R10_UNORM_PACK32 } },
427  { VK_FORMAT_R32G32B32_SFLOAT, AV_PIX_FMT_RGBF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_SFLOAT } },
428  { VK_FORMAT_R32G32B32A32_SFLOAT, AV_PIX_FMT_RGBAF32, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_SFLOAT } },
429  { VK_FORMAT_R32G32B32_UINT, AV_PIX_FMT_RGB96, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32_UINT } },
430  { VK_FORMAT_R32G32B32A32_UINT, AV_PIX_FMT_RGBA128, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R32G32B32A32_UINT } },
431 
432  /* Planar RGB */
433  { 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 } },
434  { 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 } },
435  { 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 } },
436  { 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 } },
437  { 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 } },
438  { 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 } },
439  { 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 } },
440 
441  /* Planar RGB + Alpha */
442  { 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 } },
443  { 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 } },
444  { 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 } },
445  { 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 } },
446  { 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 } },
447  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_GBRAPF16, VK_IMAGE_ASPECT_COLOR_BIT, 4, 4, 4, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
448  { 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 } },
449  { 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 } },
450 
451  /* Bayer */
452  { VK_FORMAT_R16_UNORM, AV_PIX_FMT_BAYER_RGGB16, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16_UNORM } },
453 
454  /* Two-plane 420 YUV at 8, 10, 12 and 16 bits */
455  { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, AV_PIX_FMT_NV12, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
456  { 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 } },
457  { 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 } },
458  { VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, AV_PIX_FMT_P016, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
459 
460  /* Two-plane 422 YUV at 8, 10 and 16 bits */
461  { VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, AV_PIX_FMT_NV16, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
462  { 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 } },
463  { 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 } },
464  { VK_FORMAT_G16_B16R16_2PLANE_422_UNORM, AV_PIX_FMT_P216, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
465 
466  /* Two-plane 444 YUV at 8, 10 and 16 bits */
467  { VK_FORMAT_G8_B8R8_2PLANE_444_UNORM, AV_PIX_FMT_NV24, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8G8_UNORM } },
468  { 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 } },
469  { 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 } },
470  { VK_FORMAT_G16_B16R16_2PLANE_444_UNORM, AV_PIX_FMT_P416, ASPECT_2PLANE, 2, 1, 2, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16G16_UNORM } },
471 
472  /* Three-plane 420, 422, 444 at 8, 10, 12 and 16 bits */
473  { VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
474  { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
475  { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
476  { VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM, AV_PIX_FMT_YUV420P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
477  { VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
478  { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
479  { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
480  { VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM, AV_PIX_FMT_YUV422P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
481  { VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM, VK_FORMAT_R8_UNORM } },
482  { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P10, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
483  { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P12, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
484  { VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM, AV_PIX_FMT_YUV444P16, ASPECT_3PLANE, 3, 1, 3, { VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM, VK_FORMAT_R16_UNORM } },
485 
486  /* Single plane 422 at 8, 10, 12 and 16 bits */
487  { VK_FORMAT_G8B8G8R8_422_UNORM, AV_PIX_FMT_YUYV422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
488  { VK_FORMAT_B8G8R8G8_422_UNORM, AV_PIX_FMT_UYVY422, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R8G8B8A8_UNORM } },
489  { VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, AV_PIX_FMT_Y210, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
490  { VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, AV_PIX_FMT_Y212, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
491  { VK_FORMAT_G16B16G16R16_422_UNORM, AV_PIX_FMT_Y216, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
492 
493  /* Planar YUVA 420 at 8, 10 and 16 bits */
494  { 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 } },
495  { 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 } },
496  { 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 } },
497 
498  /* Planar YUVA 422 at 8, 10, 12 and 16 bits */
499  { 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 } },
500  { 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 } },
501  { 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 } },
502  { 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 } },
503 
504  /* Planar YUVA 444 at 8, 10, 12 and 16 bits */
505  { 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 } },
506  { 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 } },
507  { 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 } },
508  { 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 } },
509 
510  /* Single plane 444 at 8, 10, 12 and 16 bits */
511  { VK_FORMAT_B8G8R8A8_UNORM, AV_PIX_FMT_UYVA, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_B8G8R8A8_UNORM } },
512  { VK_FORMAT_A2R10G10B10_UNORM_PACK32, AV_PIX_FMT_XV30, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
513  { VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, AV_PIX_FMT_XV36, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
514  { VK_FORMAT_R16G16B16A16_UNORM, AV_PIX_FMT_XV48, VK_IMAGE_ASPECT_COLOR_BIT, 1, 1, 1, { VK_FORMAT_R16G16B16A16_UNORM } },
515 };
517 
519 {
520  for (int i = 0; i < nb_vk_formats_list; i++)
521  if (vk_formats_list[i].pixfmt == p)
522  return vk_formats_list[i].fallback;
523  return NULL;
524 }
525 
527 {
528  for (int i = 0; i < nb_vk_formats_list; i++)
529  if (vk_formats_list[i].pixfmt == p)
530  return &vk_formats_list[i];
531  return NULL;
532 }
533 
535  VkImageTiling tiling,
536  VkFormat fmts[AV_NUM_DATA_POINTERS], /* Output format list */
537  int *nb_images, /* Output number of images */
538  VkImageAspectFlags *aspect, /* Output aspect */
539  VkImageUsageFlags *supported_usage, /* Output supported usage */
540  int disable_multiplane, int need_storage)
541 {
542  VulkanDevicePriv *priv = dev_ctx->hwctx;
543  AVVulkanDeviceContext *hwctx = &priv->p;
544  FFVulkanFunctions *vk = &priv->vkctx.vkfn;
545 
546  const VkFormatFeatureFlagBits2 basic_flags = VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT |
547  VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT |
548  VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
549 
550  for (int i = 0; i < nb_vk_formats_list; i++) {
551  if (vk_formats_list[i].pixfmt == p) {
552  VkFormatProperties3 fprops = {
553  .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3,
554  };
555  VkFormatProperties2 prop = {
556  .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
557  .pNext = &fprops,
558  };
559  VkFormatFeatureFlagBits2 feats_primary, feats_secondary;
560  int basics_primary = 0, basics_secondary = 0;
561  int storage_primary = 0, storage_secondary = 0;
562 
563  vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
565  &prop);
566 
567  feats_primary = tiling == VK_IMAGE_TILING_LINEAR ?
568  fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
569  basics_primary = (feats_primary & basic_flags) == basic_flags;
570  storage_primary = !!(feats_primary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
571 
573  vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev,
575  &prop);
576  feats_secondary = tiling == VK_IMAGE_TILING_LINEAR ?
577  fprops.linearTilingFeatures : fprops.optimalTilingFeatures;
578  basics_secondary = (feats_secondary & basic_flags) == basic_flags;
579  storage_secondary = !!(feats_secondary & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT);
580  } else {
581  basics_secondary = basics_primary;
582  storage_secondary = storage_primary;
583  }
584 
585  if (basics_primary &&
586  !(disable_multiplane && vk_formats_list[i].vk_planes > 1) &&
587  (!need_storage || (need_storage && (storage_primary | storage_secondary)))) {
588  if (fmts) {
589  if (vk_formats_list[i].nb_images > 1) {
590  for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
591  fmts[j] = vk_formats_list[i].fallback[j];
592  } else {
593  fmts[0] = vk_formats_list[i].vkf;
594  }
595  }
596  if (nb_images)
597  *nb_images = 1;
598  if (aspect)
600  if (supported_usage)
601  *supported_usage = ff_vk_map_feats_to_usage(feats_primary) |
602  ((need_storage && (storage_primary | storage_secondary)) ?
603  VK_IMAGE_USAGE_STORAGE_BIT : 0);
604  return 0;
605  } else if (basics_secondary &&
606  (!need_storage || (need_storage && storage_secondary))) {
607  if (fmts) {
608  for (int j = 0; j < vk_formats_list[i].nb_images_fallback; j++)
609  fmts[j] = vk_formats_list[i].fallback[j];
610  }
611  if (nb_images)
613  if (aspect)
615  if (supported_usage)
616  *supported_usage = ff_vk_map_feats_to_usage(feats_secondary);
617  return 0;
618  } else {
619  return AVERROR(ENOTSUP);
620  }
621  }
622  }
623 
624  return AVERROR(EINVAL);
625 }
626 
627 #if CONFIG_VULKAN_STATIC
628 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
629  const char *pName);
630 #endif
631 
633 {
634  VulkanDevicePriv *p = ctx->hwctx;
635  AVVulkanDeviceContext *hwctx = &p->p;
636 
637 #if CONFIG_VULKAN_STATIC
638  hwctx->get_proc_addr = vkGetInstanceProcAddr;
639 #else
640  static const char *lib_names[] = {
641 #if defined(_WIN32)
642  "vulkan-1.dll",
643 #elif defined(__APPLE__)
644  "libvulkan.dylib",
645  "libvulkan.1.dylib",
646  "libMoltenVK.dylib",
647 #else
648  "libvulkan.so.1",
649  "libvulkan.so",
650 #endif
651  };
652 
653  for (int i = 0; i < FF_ARRAY_ELEMS(lib_names); i++) {
654  p->libvulkan = dlopen(lib_names[i], RTLD_NOW | RTLD_LOCAL);
655  if (p->libvulkan)
656  break;
657  }
658 
659  if (!p->libvulkan) {
660  av_log(ctx, AV_LOG_ERROR, "Unable to open the libvulkan library!\n");
661  return AVERROR_UNKNOWN;
662  }
663 
664  hwctx->get_proc_addr = (PFN_vkGetInstanceProcAddr)dlsym(p->libvulkan, "vkGetInstanceProcAddr");
665 #endif /* CONFIG_VULKAN_STATIC */
666 
667  return 0;
668 }
669 
670 typedef struct VulkanOptExtension {
671  const char *name;
674 
676 #ifdef __APPLE__
677  { VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG },
678 #endif
679  { 0 },
680 };
681 
683  /* Misc or required by other extensions */
684  { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, FF_VK_EXT_PORTABILITY_SUBSET },
685  { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_PUSH_DESCRIPTOR },
686  { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM },
687  { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT },
688  { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX },
689  { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT },
690  { VK_KHR_SHADER_SUBGROUP_ROTATE_EXTENSION_NAME, FF_VK_EXT_SUBGROUP_ROTATE },
691  { VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME, FF_VK_EXT_HOST_IMAGE_COPY },
692  { VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME, FF_VK_EXT_EXPLICIT_MEM_LAYOUT },
693 #ifdef VK_KHR_shader_relaxed_extended_instruction
694  { VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME, FF_VK_EXT_RELAXED_EXTENDED_INSTR },
695 #endif
696 #ifdef VK_EXT_shader_long_vector
697  { VK_EXT_SHADER_LONG_VECTOR_EXTENSION_NAME, FF_VK_EXT_LONG_VECTOR },
698 #endif
699 #ifdef VK_EXT_shader_replicated_composites
700  { VK_EXT_SHADER_REPLICATED_COMPOSITES_EXTENSION_NAME, FF_VK_EXT_REPLICATED_COMPOSITES },
701 #endif
702 #ifdef VK_EXT_zero_initialize_device_memory
703  { VK_EXT_ZERO_INITIALIZE_DEVICE_MEMORY_EXTENSION_NAME, FF_VK_EXT_ZERO_INITIALIZE },
704 #endif
705 #ifdef VK_KHR_shader_expect_assume
706  { VK_KHR_SHADER_EXPECT_ASSUME_EXTENSION_NAME, FF_VK_EXT_EXPECT_ASSUME },
707 #endif
708  { VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_1 },
709 #ifdef VK_KHR_video_maintenance2
710  { VK_KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_2 },
711 #endif
712 
713  /* Imports/exports */
714  { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY },
715  { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
716  { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS },
717  { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM },
718  { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY },
719 #ifdef _WIN32
720  { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY },
721  { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM },
722 #endif
723 
724  /* Video encoding/decoding */
725  { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE },
726  { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_QUEUE },
727  { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE },
728  { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H264 },
729  { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 },
730  { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H265 },
731  { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 },
732 #ifdef VK_KHR_video_decode_vp9
733  { VK_KHR_VIDEO_DECODE_VP9_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_VP9 },
734 #endif
735 #ifdef VK_KHR_video_encode_av1
736  { VK_KHR_VIDEO_ENCODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_AV1 },
737 #endif
738  { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_AV1 },
739 };
740 
742 {
743  const char **exts = av_malloc_array(sizeof(*exts),
745  if (!exts)
746  return NULL;
747 
748  for (int i = 0; i < FF_ARRAY_ELEMS(optional_instance_exts) - 1; i++)
749  exts[i] = optional_instance_exts[i].name;
750 
752  return exts;
753 }
754 
755 const char **av_vk_get_optional_device_extensions(int *count)
756 {
757  const char **exts = av_malloc_array(sizeof(*exts),
759  if (!exts)
760  return NULL;
761 
762  for (int i = 0; i < FF_ARRAY_ELEMS(optional_device_exts); i++)
763  exts[i] = optional_device_exts[i].name;
764 
766  return exts;
767 }
768 
769 static VKAPI_ATTR
770 VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
771  VkDebugUtilsMessageTypeFlagsEXT messageType,
772  const VkDebugUtilsMessengerCallbackDataEXT *data,
773  void *priv)
774 {
775  int l;
776  AVHWDeviceContext *ctx = priv;
777 
778  /* Ignore false positives */
779  switch (data->messageIdNumber) {
780  case 0x086974c1: /* BestPractices-vkCreateCommandPool-command-buffer-reset */
781  case 0xfd92477a: /* BestPractices-vkAllocateMemory-small-allocation */
782  return VK_FALSE;
783  default:
784  break;
785  }
786 
787  switch (severity) {
788  case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: l = AV_LOG_VERBOSE; break;
789  case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: l = AV_LOG_INFO; break;
790  case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: l = AV_LOG_WARNING; break;
791  case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: l = AV_LOG_ERROR; break;
792  default: l = AV_LOG_DEBUG; break;
793  }
794 
795  av_log(ctx, l, "%s\n", data->pMessage);
796  for (int i = 0; i < data->cmdBufLabelCount; i++)
797  av_log(ctx, l, "\t%i: %s\n", i, data->pCmdBufLabels[i].pLabelName);
798 
799  return VK_FALSE;
800 }
801 
802 #define ADD_VAL_TO_LIST(list, count, val) \
803  do { \
804  list = av_realloc_array(list, ++count, sizeof(*list)); \
805  if (!list) { \
806  err = AVERROR(ENOMEM); \
807  goto fail; \
808  } \
809  list[count - 1] = av_strdup(val); \
810  if (!list[count - 1]) { \
811  err = AVERROR(ENOMEM); \
812  goto fail; \
813  } \
814  } while(0)
815 
816 #define RELEASE_PROPS(props, count) \
817  if (props) { \
818  for (int i = 0; i < count; i++) \
819  av_free((void *)((props)[i])); \
820  av_free((void *)props); \
821  }
822 
824 {
825  VulkanDevicePriv *p = ctx->hwctx;
826  VkDeviceSize max_vram = 0, max_visible_vram = 0;
827 
828  /* Get device memory properties */
829  av_assert0(p->mprops.memoryTypeCount);
830  for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
831  const VkMemoryType type = p->mprops.memoryTypes[i];
832  const VkMemoryHeap heap = p->mprops.memoryHeaps[type.heapIndex];
833  if (!(type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT))
834  continue;
835  max_vram = FFMAX(max_vram, heap.size);
836  if (type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
837  max_visible_vram = FFMAX(max_visible_vram, heap.size);
838  }
839 
840  return max_vram - max_visible_vram < 1024; /* 1 kB tolerance */
841 }
842 
845  /* Standard GPU-assisted validation */
847  /* Passes printfs in shaders to the debug callback */
849  /* Enables extra printouts */
851 
853 };
854 
856  const char * const **dst, uint32_t *num,
857  enum FFVulkanDebugMode debug_mode)
858 {
859  const char *tstr;
860  const char **extension_names = NULL;
861  VulkanDevicePriv *p = ctx->hwctx;
862  AVVulkanDeviceContext *hwctx = &p->p;
863  FFVulkanFunctions *vk = &p->vkctx.vkfn;
864  int err = 0, found, extensions_found = 0;
865 
866  const char *mod;
867  int optional_exts_num;
868  uint32_t sup_ext_count;
869  char *user_exts_str = NULL;
870  AVDictionaryEntry *user_exts;
871  VkExtensionProperties *sup_ext;
872  const VulkanOptExtension *optional_exts;
873 
874  if (!dev) {
875  mod = "instance";
876  optional_exts = optional_instance_exts;
877  optional_exts_num = FF_ARRAY_ELEMS(optional_instance_exts) - 1;
878  user_exts = av_dict_get(opts, "instance_extensions", NULL, 0);
879  if (user_exts) {
880  user_exts_str = av_strdup(user_exts->value);
881  if (!user_exts_str) {
882  err = AVERROR(ENOMEM);
883  goto fail;
884  }
885  }
886  vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, NULL);
887  sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
888  if (!sup_ext)
889  return AVERROR(ENOMEM);
890  vk->EnumerateInstanceExtensionProperties(NULL, &sup_ext_count, sup_ext);
891  } else {
892  mod = "device";
893  optional_exts = optional_device_exts;
894  optional_exts_num = FF_ARRAY_ELEMS(optional_device_exts);
895  user_exts = av_dict_get(opts, "device_extensions", NULL, 0);
896  if (user_exts) {
897  user_exts_str = av_strdup(user_exts->value);
898  if (!user_exts_str) {
899  err = AVERROR(ENOMEM);
900  goto fail;
901  }
902  }
903  vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
904  &sup_ext_count, NULL);
905  sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties));
906  if (!sup_ext)
907  return AVERROR(ENOMEM);
908  vk->EnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL,
909  &sup_ext_count, sup_ext);
910  }
911 
912  for (int i = 0; i < optional_exts_num; i++) {
913  tstr = optional_exts[i].name;
914  found = 0;
915 
916  /* Check if the device has ReBAR for host image copies */
917  if (!strcmp(tstr, VK_EXT_HOST_IMAGE_COPY_EXTENSION_NAME) &&
919  continue;
920 
921  if (dev &&
922  ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
923  (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
924  (debug_mode == FF_VULKAN_DEBUG_PRACTICES)) &&
925  (!strcmp(tstr, VK_EXT_SHADER_OBJECT_EXTENSION_NAME))) {
926  continue;
927  }
928 
929  for (int j = 0; j < sup_ext_count; j++) {
930  if (!strcmp(tstr, sup_ext[j].extensionName)) {
931  found = 1;
932  break;
933  }
934  }
935  if (!found)
936  continue;
937 
938  av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
939  p->vkctx.extensions |= optional_exts[i].flag;
940  ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
941  }
942 
943  if (!dev &&
944  ((debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
945  (debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
946  (debug_mode == FF_VULKAN_DEBUG_PRACTICES))) {
947  tstr = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
948  found = 0;
949  for (int j = 0; j < sup_ext_count; j++) {
950  if (!strcmp(tstr, sup_ext[j].extensionName)) {
951  found = 1;
952  break;
953  }
954  }
955  if (found) {
956  av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr);
957  ADD_VAL_TO_LIST(extension_names, extensions_found, tstr);
958  } else {
959  av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n",
960  tstr);
961  err = AVERROR(EINVAL);
962  goto fail;
963  }
964  }
965 
966 #ifdef VK_KHR_shader_relaxed_extended_instruction
967  if ((debug_mode == FF_VULKAN_DEBUG_PRINTF) && dev) {
968  tstr = VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME;
969  found = 0;
970  for (int j = 0; j < sup_ext_count; j++) {
971  if (!strcmp(tstr, sup_ext[j].extensionName)) {
972  found = 1;
973  break;
974  }
975  }
976  if (!found) {
977  av_log(ctx, AV_LOG_ERROR, "Debug_printf/profile enabled, but extension \"%s\" not found!\n",
978  tstr);
979  err = AVERROR(EINVAL);
980  goto fail;
981  }
982  }
983 #endif
984 
985  if (user_exts_str) {
986  char *save, *token = av_strtok(user_exts_str, "+", &save);
987  while (token) {
988  found = 0;
989  for (int j = 0; j < sup_ext_count; j++) {
990  if (!strcmp(token, sup_ext[j].extensionName)) {
991  found = 1;
992  break;
993  }
994  }
995  if (found) {
996  av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, token);
997  ADD_VAL_TO_LIST(extension_names, extensions_found, token);
998  } else {
999  av_log(ctx, AV_LOG_WARNING, "%s extension \"%s\" not found, excluding.\n",
1000  mod, token);
1001  }
1002  token = av_strtok(NULL, "+", &save);
1003  }
1004  }
1005 
1006  *dst = extension_names;
1007  *num = extensions_found;
1008 
1009  av_free(user_exts_str);
1010  av_free(sup_ext);
1011  return 0;
1012 
1013 fail:
1014  RELEASE_PROPS(extension_names, extensions_found);
1015  av_free(user_exts_str);
1016  av_free(sup_ext);
1017  return err;
1018 }
1019 
1021  const char * const **dst, uint32_t *num,
1022  enum FFVulkanDebugMode *debug_mode)
1023 {
1024  int err = 0;
1025  VulkanDevicePriv *priv = ctx->hwctx;
1026  FFVulkanFunctions *vk = &priv->vkctx.vkfn;
1027 
1028  static const char layer_standard_validation[] = { "VK_LAYER_KHRONOS_validation" };
1029  int layer_standard_validation_found = 0;
1030 
1031  uint32_t sup_layer_count;
1032  VkLayerProperties *sup_layers;
1033 
1034  AVDictionaryEntry *user_layers = av_dict_get(opts, "layers", NULL, 0);
1035  char *user_layers_str = NULL;
1036  char *save, *token;
1037 
1038  const char **enabled_layers = NULL;
1039  uint32_t enabled_layers_count = 0;
1040 
1041  AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0);
1042  enum FFVulkanDebugMode mode;
1043 
1044  *debug_mode = mode = FF_VULKAN_DEBUG_NONE;
1045 
1046  /* Get a list of all layers */
1047  vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL);
1048  sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties));
1049  if (!sup_layers)
1050  return AVERROR(ENOMEM);
1051  vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers);
1052 
1053  av_log(ctx, AV_LOG_VERBOSE, "Supported layers:\n");
1054  for (int i = 0; i < sup_layer_count; i++)
1055  av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName);
1056 
1057  /* If no user layers or debug layers are given, return */
1058  if (!debug_opt && !user_layers)
1059  goto end;
1060 
1061  /* Check for any properly supported validation layer */
1062  if (debug_opt) {
1063  if (!strcmp(debug_opt->value, "printf")) {
1065  } else if (!strcmp(debug_opt->value, "validate")) {
1067  } else if (!strcmp(debug_opt->value, "practices")) {
1069  } else {
1070  char *end_ptr = NULL;
1071  int idx = strtol(debug_opt->value, &end_ptr, 10);
1072  if (end_ptr == debug_opt->value || end_ptr[0] != '\0' ||
1073  idx < 0 || idx >= FF_VULKAN_DEBUG_NB) {
1074  av_log(ctx, AV_LOG_ERROR, "Invalid debugging mode \"%s\"\n",
1075  debug_opt->value);
1076  err = AVERROR(EINVAL);
1077  goto end;
1078  }
1079  mode = idx;
1080  }
1081  }
1082 
1083  /* If mode is VALIDATE or PRINTF, try to find the standard validation layer extension */
1084  if ((mode == FF_VULKAN_DEBUG_VALIDATE) ||
1087  for (int i = 0; i < sup_layer_count; i++) {
1088  if (!strcmp(layer_standard_validation, sup_layers[i].layerName)) {
1089  av_log(ctx, AV_LOG_VERBOSE, "Standard validation layer %s is enabled\n",
1090  layer_standard_validation);
1091  ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, layer_standard_validation);
1092  *debug_mode = mode;
1093  layer_standard_validation_found = 1;
1094  break;
1095  }
1096  }
1097  if (!layer_standard_validation_found) {
1099  "Validation Layer \"%s\" not supported\n", layer_standard_validation);
1100  err = AVERROR(ENOTSUP);
1101  goto end;
1102  }
1103  }
1104 
1105  /* Process any custom layers enabled */
1106  if (user_layers) {
1107  int found;
1108 
1109  user_layers_str = av_strdup(user_layers->value);
1110  if (!user_layers_str) {
1111  err = AVERROR(ENOMEM);
1112  goto fail;
1113  }
1114 
1115  token = av_strtok(user_layers_str, "+", &save);
1116  while (token) {
1117  found = 0;
1118 
1119  /* If debug=1/2 was specified as an option, skip this layer */
1120  if (!strcmp(layer_standard_validation, token) && layer_standard_validation_found) {
1121  token = av_strtok(NULL, "+", &save);
1122  break;
1123  }
1124 
1125  /* Try to find the layer in the list of supported layers */
1126  for (int j = 0; j < sup_layer_count; j++) {
1127  if (!strcmp(token, sup_layers[j].layerName)) {
1128  found = 1;
1129  break;
1130  }
1131  }
1132 
1133  if (found) {
1134  av_log(ctx, AV_LOG_VERBOSE, "Using layer: %s\n", token);
1135  ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token);
1136 
1137  /* If debug was not set as an option, force it */
1138  if (!strcmp(layer_standard_validation, token))
1139  *debug_mode = FF_VULKAN_DEBUG_VALIDATE;
1140  } else {
1142  "Layer \"%s\" not supported\n", token);
1143  err = AVERROR(EINVAL);
1144  goto end;
1145  }
1146 
1147  token = av_strtok(NULL, "+", &save);
1148  }
1149  }
1150 
1151 fail:
1152 end:
1153  av_free(sup_layers);
1154  av_free(user_layers_str);
1155 
1156  if (err < 0) {
1157  RELEASE_PROPS(enabled_layers, enabled_layers_count);
1158  } else {
1159  *dst = enabled_layers;
1160  *num = enabled_layers_count;
1161  }
1162 
1163  return err;
1164 }
1165 
1166 /* Creates a VkInstance */
1168  enum FFVulkanDebugMode *debug_mode)
1169 {
1170  int err = 0;
1171  VkResult ret;
1172  VulkanDevicePriv *p = ctx->hwctx;
1173  AVVulkanDeviceContext *hwctx = &p->p;
1174  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1175  VkApplicationInfo application_info = {
1176  .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
1177  .pApplicationName = "ffmpeg",
1178  .applicationVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
1181  .pEngineName = "libavutil",
1182  .apiVersion = VK_API_VERSION_1_3,
1183  .engineVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR,
1186  };
1187  VkValidationFeaturesEXT validation_features = {
1188  .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
1189  };
1190  VkInstanceCreateInfo inst_props = {
1191  .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
1192  .pApplicationInfo = &application_info,
1193  };
1194 
1195  if (!hwctx->get_proc_addr) {
1196  err = load_libvulkan(ctx);
1197  if (err < 0)
1198  return err;
1199  }
1200 
1201  err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 0, 0);
1202  if (err < 0) {
1203  av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n");
1204  return err;
1205  }
1206 
1207  err = check_layers(ctx, opts, &inst_props.ppEnabledLayerNames,
1208  &inst_props.enabledLayerCount, debug_mode);
1209  if (err)
1210  goto fail;
1211 
1212  /* Check for present/missing extensions */
1213  err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames,
1214  &inst_props.enabledExtensionCount, *debug_mode);
1215  hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames;
1216  hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount;
1217  if (err < 0)
1218  goto fail;
1219 
1220  /* Enable debug features if needed */
1221  if (*debug_mode == FF_VULKAN_DEBUG_VALIDATE) {
1222  static const VkValidationFeatureEnableEXT feat_list_validate[] = {
1223  VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1224  VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1225  VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT,
1226  };
1227  validation_features.pEnabledValidationFeatures = feat_list_validate;
1228  validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_validate);
1229  inst_props.pNext = &validation_features;
1230  } else if (*debug_mode == FF_VULKAN_DEBUG_PRINTF) {
1231  static const VkValidationFeatureEnableEXT feat_list_debug[] = {
1232  VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1233  VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT,
1234  VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT,
1235  };
1236  validation_features.pEnabledValidationFeatures = feat_list_debug;
1237  validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_debug);
1238  inst_props.pNext = &validation_features;
1239  } else if (*debug_mode == FF_VULKAN_DEBUG_PRACTICES) {
1240  static const VkValidationFeatureEnableEXT feat_list_practices[] = {
1241  VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
1242  VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
1243  };
1244  validation_features.pEnabledValidationFeatures = feat_list_practices;
1245  validation_features.enabledValidationFeatureCount = FF_ARRAY_ELEMS(feat_list_practices);
1246  inst_props.pNext = &validation_features;
1247  }
1248 
1249 #ifdef __APPLE__
1250  for (int i = 0; i < inst_props.enabledExtensionCount; i++) {
1251  if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
1252  inst_props.ppEnabledExtensionNames[i])) {
1253  inst_props.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
1254  break;
1255  }
1256  }
1257 #endif
1258 
1259  /* Try to create the instance */
1260  ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst);
1261 
1262  /* Check for errors */
1263  if (ret != VK_SUCCESS) {
1264  av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n",
1265  ff_vk_ret2str(ret));
1266  err = AVERROR_EXTERNAL;
1267  goto fail;
1268  }
1269 
1270  err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 0);
1271  if (err < 0) {
1272  av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n");
1273  goto fail;
1274  }
1275 
1276  /* Setup debugging callback if needed */
1277  if ((*debug_mode == FF_VULKAN_DEBUG_VALIDATE) ||
1278  (*debug_mode == FF_VULKAN_DEBUG_PRINTF) ||
1279  (*debug_mode == FF_VULKAN_DEBUG_PRACTICES)) {
1280  VkDebugUtilsMessengerCreateInfoEXT dbg = {
1281  .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
1282  .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
1283  VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
1284  VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
1285  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
1286  .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
1287  VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
1288  VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
1289  .pfnUserCallback = vk_dbg_callback,
1290  .pUserData = ctx,
1291  };
1292 
1293  vk->CreateDebugUtilsMessengerEXT(hwctx->inst, &dbg,
1294  hwctx->alloc, &p->debug_ctx);
1295  }
1296 
1297  err = 0;
1298 
1299 fail:
1300  RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount);
1301  return err;
1302 }
1303 
1304 typedef struct VulkanDeviceSelection {
1305  uint8_t uuid[VK_UUID_SIZE]; /* Will use this first unless !has_uuid */
1307  uint32_t drm_major; /* Will use this second unless !has_drm */
1308  uint32_t drm_minor; /* Will use this second unless !has_drm */
1309  uint32_t has_drm; /* has drm node info */
1310  const char *name; /* Will use this third unless NULL */
1311  uint32_t pci_device; /* Will use this fourth unless 0x0 */
1312  uint32_t vendor_id; /* Last resort to find something deterministic */
1313  int index; /* Finally fall back to index */
1315 
1316 static const char *vk_dev_type(enum VkPhysicalDeviceType type)
1317 {
1318  switch (type) {
1319  case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: return "integrated";
1320  case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: return "discrete";
1321  case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: return "virtual";
1322  case VK_PHYSICAL_DEVICE_TYPE_CPU: return "software";
1323  default: return "unknown";
1324  }
1325 }
1326 
1327 /* Finds a device */
1329 {
1330  int err = 0, choice = -1;
1331  uint32_t num;
1332  VkResult ret;
1333  VulkanDevicePriv *p = ctx->hwctx;
1334  AVVulkanDeviceContext *hwctx = &p->p;
1335  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1336  VkPhysicalDevice *devices = NULL;
1337  VkPhysicalDeviceIDProperties *idp = NULL;
1338  VkPhysicalDeviceProperties2 *prop = NULL;
1339  VkPhysicalDeviceDriverProperties *driver_prop = NULL;
1340  VkPhysicalDeviceDrmPropertiesEXT *drm_prop = NULL;
1341 
1342  ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, NULL);
1343  if (ret != VK_SUCCESS || !num) {
1344  av_log(ctx, AV_LOG_ERROR, "No devices found: %s!\n", ff_vk_ret2str(ret));
1345  return AVERROR(ENODEV);
1346  }
1347 
1348  devices = av_malloc_array(num, sizeof(VkPhysicalDevice));
1349  if (!devices)
1350  return AVERROR(ENOMEM);
1351 
1352  ret = vk->EnumeratePhysicalDevices(hwctx->inst, &num, devices);
1353  if (ret != VK_SUCCESS) {
1354  av_log(ctx, AV_LOG_ERROR, "Failed enumerating devices: %s\n",
1355  ff_vk_ret2str(ret));
1356  err = AVERROR(ENODEV);
1357  goto end;
1358  }
1359 
1360  prop = av_calloc(num, sizeof(*prop));
1361  if (!prop) {
1362  err = AVERROR(ENOMEM);
1363  goto end;
1364  }
1365 
1366  idp = av_calloc(num, sizeof(*idp));
1367  if (!idp) {
1368  err = AVERROR(ENOMEM);
1369  goto end;
1370  }
1371 
1372  driver_prop = av_calloc(num, sizeof(*driver_prop));
1373  if (!driver_prop) {
1374  err = AVERROR(ENOMEM);
1375  goto end;
1376  }
1377 
1378  if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
1379  drm_prop = av_calloc(num, sizeof(*drm_prop));
1380  if (!drm_prop) {
1381  err = AVERROR(ENOMEM);
1382  goto end;
1383  }
1384  }
1385 
1386  av_log(ctx, AV_LOG_VERBOSE, "GPU listing:\n");
1387  for (int i = 0; i < num; i++) {
1388  if (p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) {
1389  drm_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
1390  driver_prop[i].pNext = &drm_prop[i];
1391  }
1392  driver_prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
1393  idp[i].pNext = &driver_prop[i];
1394  idp[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
1395  prop[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1396  prop[i].pNext = &idp[i];
1397 
1398  vk->GetPhysicalDeviceProperties2(devices[i], &prop[i]);
1399  av_log(ctx, AV_LOG_VERBOSE, " %d: %s (%s) (0x%x)\n", i,
1400  prop[i].properties.deviceName,
1401  vk_dev_type(prop[i].properties.deviceType),
1402  prop[i].properties.deviceID);
1403  }
1404 
1405  if (select->has_uuid) {
1406  for (int i = 0; i < num; i++) {
1407  if (!strncmp(idp[i].deviceUUID, select->uuid, VK_UUID_SIZE)) {
1408  choice = i;
1409  goto end;
1410  }
1411  }
1412  av_log(ctx, AV_LOG_ERROR, "Unable to find device by given UUID!\n");
1413  err = AVERROR(ENODEV);
1414  goto end;
1415  } else if ((p->vkctx.extensions & FF_VK_EXT_DEVICE_DRM) && select->has_drm) {
1416  for (int i = 0; i < num; i++) {
1417  if ((select->drm_major == drm_prop[i].primaryMajor &&
1418  select->drm_minor == drm_prop[i].primaryMinor) ||
1419  (select->drm_major == drm_prop[i].renderMajor &&
1420  select->drm_minor == drm_prop[i].renderMinor)) {
1421  choice = i;
1422  goto end;
1423  }
1424  }
1425  av_log(ctx, AV_LOG_ERROR, "Unable to find device by given DRM node numbers %i:%i!\n",
1426  select->drm_major, select->drm_minor);
1427  err = AVERROR(ENODEV);
1428  goto end;
1429  } else if (select->name) {
1430  av_log(ctx, AV_LOG_VERBOSE, "Requested device: %s\n", select->name);
1431  for (int i = 0; i < num; i++) {
1432  if (strstr(prop[i].properties.deviceName, select->name)) {
1433  choice = i;
1434  goto end;
1435  }
1436  }
1437  av_log(ctx, AV_LOG_ERROR, "Unable to find device \"%s\"!\n",
1438  select->name);
1439  err = AVERROR(ENODEV);
1440  goto end;
1441  } else if (select->pci_device) {
1442  av_log(ctx, AV_LOG_VERBOSE, "Requested device: 0x%x\n", select->pci_device);
1443  for (int i = 0; i < num; i++) {
1444  if (select->pci_device == prop[i].properties.deviceID) {
1445  choice = i;
1446  goto end;
1447  }
1448  }
1449  av_log(ctx, AV_LOG_ERROR, "Unable to find device with PCI ID 0x%x!\n",
1450  select->pci_device);
1451  err = AVERROR(EINVAL);
1452  goto end;
1453  } else if (select->vendor_id) {
1454  av_log(ctx, AV_LOG_VERBOSE, "Requested vendor: 0x%x\n", select->vendor_id);
1455  for (int i = 0; i < num; i++) {
1456  if (select->vendor_id == prop[i].properties.vendorID) {
1457  choice = i;
1458  goto end;
1459  }
1460  }
1461  av_log(ctx, AV_LOG_ERROR, "Unable to find device with Vendor ID 0x%x!\n",
1462  select->vendor_id);
1463  err = AVERROR(ENODEV);
1464  goto end;
1465  } else {
1466  if (select->index < num) {
1467  choice = select->index;
1468  goto end;
1469  }
1470  av_log(ctx, AV_LOG_ERROR, "Unable to find device with index %i!\n",
1471  select->index);
1472  err = AVERROR(ENODEV);
1473  goto end;
1474  }
1475 
1476 end:
1477  if (choice > -1) {
1478  av_log(ctx, AV_LOG_VERBOSE, "Device %d selected: %s (%s) (0x%x)\n",
1479  choice, prop[choice].properties.deviceName,
1480  vk_dev_type(prop[choice].properties.deviceType),
1481  prop[choice].properties.deviceID);
1482  hwctx->phys_dev = devices[choice];
1483  p->props = prop[choice];
1484  p->props.pNext = NULL;
1485  p->dprops = driver_prop[choice];
1486  p->dprops.pNext = NULL;
1487  }
1488 
1489  av_free(devices);
1490  av_free(prop);
1491  av_free(idp);
1492  av_free(drm_prop);
1493  av_free(driver_prop);
1494 
1495  return err;
1496 }
1497 
1498 /* Picks the least used qf with the fewest unneeded flags, or -1 if none found */
1499 static inline int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf,
1500  VkQueueFlagBits flags)
1501 {
1502  int index = -1;
1503  uint32_t min_score = UINT32_MAX;
1504 
1505  for (int i = 0; i < num_qf; i++) {
1506  VkQueueFlagBits qflags = qf[i].queueFamilyProperties.queueFlags;
1507 
1508  /* Per the spec, reporting transfer caps is optional for these 2 types */
1509  if ((flags & VK_QUEUE_TRANSFER_BIT) &&
1510  (qflags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT)))
1511  qflags |= VK_QUEUE_TRANSFER_BIT;
1512 
1513  if (qflags & flags) {
1514  uint32_t score = av_popcount(qflags) + qf[i].queueFamilyProperties.timestampValidBits;
1515  if (score < min_score) {
1516  index = i;
1517  min_score = score;
1518  }
1519  }
1520  }
1521 
1522  if (index > -1)
1523  qf[index].queueFamilyProperties.timestampValidBits++;
1524 
1525  return index;
1526 }
1527 
1528 static inline int pick_video_queue_family(VkQueueFamilyProperties2 *qf,
1529  VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf,
1530  VkVideoCodecOperationFlagsKHR flags)
1531 {
1532  int index = -1;
1533  uint32_t min_score = UINT32_MAX;
1534 
1535  for (int i = 0; i < num_qf; i++) {
1536  const VkQueueFlags qflags = qf[i].queueFamilyProperties.queueFlags;
1537  const VkVideoCodecOperationFlagsKHR vflags = qf_vid[i].videoCodecOperations;
1538 
1539  if (!(qflags & (VK_QUEUE_VIDEO_ENCODE_BIT_KHR | VK_QUEUE_VIDEO_DECODE_BIT_KHR)))
1540  continue;
1541 
1542  if (vflags & flags) {
1543  uint32_t score = av_popcount(vflags) + qf[i].queueFamilyProperties.timestampValidBits;
1544  if (score < min_score) {
1545  index = i;
1546  min_score = score;
1547  }
1548  }
1549  }
1550 
1551  if (index > -1)
1552  qf[index].queueFamilyProperties.timestampValidBits++;
1553 
1554  return index;
1555 }
1556 
1557 static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
1558 {
1559  uint32_t num;
1560  VulkanDevicePriv *p = ctx->hwctx;
1561  AVVulkanDeviceContext *hwctx = &p->p;
1562  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1563 
1564  VkQueueFamilyProperties2 *qf = NULL;
1565  VkQueueFamilyVideoPropertiesKHR *qf_vid = NULL;
1566 
1567  /* First get the number of queue families */
1568  vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL);
1569  if (!num) {
1570  av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
1571  return AVERROR_EXTERNAL;
1572  }
1573 
1574  /* Then allocate memory */
1575  qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties2));
1576  if (!qf)
1577  return AVERROR(ENOMEM);
1578 
1579  qf_vid = av_malloc_array(num, sizeof(VkQueueFamilyVideoPropertiesKHR));
1580  if (!qf_vid)
1581  return AVERROR(ENOMEM);
1582 
1583  for (uint32_t i = 0; i < num; i++) {
1584  qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
1585  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
1586  };
1587  qf[i] = (VkQueueFamilyProperties2) {
1588  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
1589  .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
1590  };
1591  }
1592 
1593  /* Finally retrieve the queue families */
1594  vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &num, qf);
1595 
1596  av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n");
1597  for (int i = 0; i < num; i++) {
1598  av_log(ctx, AV_LOG_VERBOSE, " %i:%s%s%s%s%s%s%s%s (queues: %i)\n", i,
1599  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "",
1600  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "",
1601  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "",
1602  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "",
1603  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "",
1604  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "",
1605  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_OPTICAL_FLOW_BIT_NV) ? " optical_flow" : "",
1606  ((qf[i].queueFamilyProperties.queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "",
1607  qf[i].queueFamilyProperties.queueCount);
1608 
1609  /* We use this field to keep a score of how many times we've used that
1610  * queue family in order to make better choices. */
1611  qf[i].queueFamilyProperties.timestampValidBits = 0;
1612  }
1613 
1614  hwctx->nb_qf = 0;
1615 
1616  /* Pick each queue family to use. */
1617 #define PICK_QF(type, vid_op) \
1618  do { \
1619  uint32_t i; \
1620  uint32_t idx; \
1621  \
1622  if (vid_op) \
1623  idx = pick_video_queue_family(qf, qf_vid, num, vid_op); \
1624  else \
1625  idx = pick_queue_family(qf, num, type); \
1626  \
1627  if (idx == -1) \
1628  continue; \
1629  \
1630  for (i = 0; i < hwctx->nb_qf; i++) { \
1631  if (hwctx->qf[i].idx == idx) { \
1632  hwctx->qf[i].flags |= type; \
1633  hwctx->qf[i].video_caps |= vid_op; \
1634  break; \
1635  } \
1636  } \
1637  if (i == hwctx->nb_qf) { \
1638  hwctx->qf[i].idx = idx; \
1639  hwctx->qf[i].num = qf[idx].queueFamilyProperties.queueCount; \
1640  if (p->limit_queues || \
1641  p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { \
1642  int max = p->limit_queues; \
1643  if (type == VK_QUEUE_GRAPHICS_BIT) \
1644  hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, \
1645  max ? max : 1); \
1646  else if (max) \
1647  hwctx->qf[i].num = FFMIN(hwctx->qf[i].num, max); \
1648  } \
1649  hwctx->qf[i].flags = type; \
1650  hwctx->qf[i].video_caps = vid_op; \
1651  hwctx->nb_qf++; \
1652  } \
1653  } while (0)
1654 
1655  PICK_QF(VK_QUEUE_GRAPHICS_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1656  PICK_QF(VK_QUEUE_COMPUTE_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1657  PICK_QF(VK_QUEUE_TRANSFER_BIT, VK_VIDEO_CODEC_OPERATION_NONE_KHR);
1658 
1659  PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR);
1660  PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR);
1661 
1662  PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR);
1663  PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR);
1664 
1665 #ifdef VK_KHR_video_decode_vp9
1666  PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_VP9_BIT_KHR);
1667 #endif
1668 
1669 #ifdef VK_KHR_video_encode_av1
1670  PICK_QF(VK_QUEUE_VIDEO_ENCODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR);
1671 #endif
1672  PICK_QF(VK_QUEUE_VIDEO_DECODE_BIT_KHR, VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR);
1673 
1674  av_free(qf);
1675  av_free(qf_vid);
1676 
1677 #undef PICK_QF
1678 
1679  cd->pQueueCreateInfos = av_malloc_array(hwctx->nb_qf,
1680  sizeof(VkDeviceQueueCreateInfo));
1681  if (!cd->pQueueCreateInfos)
1682  return AVERROR(ENOMEM);
1683 
1684  for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
1685  int dup = 0;
1686  float *weights = NULL;
1687  VkDeviceQueueCreateInfo *pc;
1688  for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++) {
1689  if (hwctx->qf[i].idx == cd->pQueueCreateInfos[j].queueFamilyIndex) {
1690  dup = 1;
1691  break;
1692  }
1693  }
1694  if (dup)
1695  continue;
1696 
1697  weights = av_malloc_array(hwctx->qf[i].num, sizeof(float));
1698  if (!weights) {
1699  for (uint32_t j = 0; j < cd->queueCreateInfoCount; j++)
1700  av_free((void *)cd->pQueueCreateInfos[i].pQueuePriorities);
1701  av_free((void *)cd->pQueueCreateInfos);
1702  return AVERROR(ENOMEM);
1703  }
1704 
1705  for (uint32_t j = 0; j < hwctx->qf[i].num; j++)
1706  weights[j] = 1.0;
1707 
1708  pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos;
1709  pc[cd->queueCreateInfoCount++] = (VkDeviceQueueCreateInfo) {
1710  .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
1711  .queueFamilyIndex = hwctx->qf[i].idx,
1712  .queueCount = hwctx->qf[i].num,
1713  .pQueuePriorities = weights,
1714  };
1715  }
1716 
1717 #if FF_API_VULKAN_FIXED_QUEUES
1719  /* Setup deprecated fields */
1720  hwctx->queue_family_index = -1;
1721  hwctx->queue_family_comp_index = -1;
1722  hwctx->queue_family_tx_index = -1;
1723  hwctx->queue_family_encode_index = -1;
1724  hwctx->queue_family_decode_index = -1;
1725 
1726 #define SET_OLD_QF(field, nb_field, type) \
1727  do { \
1728  if (field < 0 && hwctx->qf[i].flags & type) { \
1729  field = hwctx->qf[i].idx; \
1730  nb_field = hwctx->qf[i].num; \
1731  } \
1732  } while (0)
1733 
1734  for (uint32_t i = 0; i < hwctx->nb_qf; i++) {
1735  SET_OLD_QF(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
1736  SET_OLD_QF(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
1737  SET_OLD_QF(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
1738  SET_OLD_QF(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
1739  SET_OLD_QF(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
1740  }
1741 
1742 #undef SET_OLD_QF
1744 #endif
1745 
1746  return 0;
1747 }
1748 
1749 /* Only resources created by vulkan_device_create should be released here,
1750  * resources created by vulkan_device_init should be released by
1751  * vulkan_device_uninit, to make sure we don't free user provided resources,
1752  * and there is no leak.
1753  */
1755 {
1756  VulkanDevicePriv *p = ctx->hwctx;
1757  AVVulkanDeviceContext *hwctx = &p->p;
1758  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1759 
1760  if (hwctx->act_dev)
1761  vk->DestroyDevice(hwctx->act_dev, hwctx->alloc);
1762 
1763  if (p->debug_ctx)
1764  vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx,
1765  hwctx->alloc);
1766 
1767  if (hwctx->inst)
1768  vk->DestroyInstance(hwctx->inst, hwctx->alloc);
1769 
1770  if (p->libvulkan)
1771  dlclose(p->libvulkan);
1772 
1775 }
1776 
1778 {
1779  VulkanDevicePriv *p = ctx->hwctx;
1780 
1781  for (uint32_t i = 0; i < p->nb_tot_qfs; i++) {
1782  pthread_mutex_destroy(p->qf_mutex[i]);
1783  av_freep(&p->qf_mutex[i]);
1784  }
1785  av_freep(&p->qf_mutex);
1786 
1787  ff_vk_uninit(&p->vkctx);
1788 }
1789 
1791  VulkanDeviceSelection *dev_select,
1792  int disable_multiplane,
1793  AVDictionary *opts, int flags)
1794 {
1795  int err = 0;
1796  VkResult ret;
1797  AVDictionaryEntry *opt_d;
1798  VulkanDevicePriv *p = ctx->hwctx;
1799  AVVulkanDeviceContext *hwctx = &p->p;
1800  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1801  enum FFVulkanDebugMode debug_mode = FF_VULKAN_DEBUG_NONE;
1802  VulkanDeviceFeatures supported_feats = { 0 };
1803  VkDeviceCreateInfo dev_info = {
1804  .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
1805  };
1806 
1807  /* Create an instance if not given one */
1808  if ((err = create_instance(ctx, opts, &debug_mode)))
1809  goto end;
1810 
1811  /* Find a physical device (if not given one) */
1812  if ((err = find_device(ctx, dev_select)))
1813  goto end;
1814 
1815  /* Get supported memory types */
1816  vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
1817 
1818  /* Find and enable extensions for the physical device */
1819  if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames,
1820  &dev_info.enabledExtensionCount, debug_mode))) {
1821  for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
1822  av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
1823  av_free((void *)dev_info.pQueueCreateInfos);
1824  goto end;
1825  }
1826 
1827  /* Get all supported features for the physical device */
1828  device_features_init(ctx, &supported_feats);
1829  vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &supported_feats.device);
1830 
1831  /* Copy all needed features from those supported and activate them */
1832  device_features_init(ctx, &p->feats);
1833  device_features_copy_needed(&p->feats, &supported_feats);
1834  dev_info.pNext = p->feats.device.pNext;
1835  dev_info.pEnabledFeatures = &p->feats.device.features;
1836 
1837  /* Limit queues to a given number if needed */
1838  opt_d = av_dict_get(opts, "limit_queues", NULL, 0);
1839  if (opt_d)
1840  p->limit_queues = strtol(opt_d->value, NULL, 10);
1841 
1842  /* Setup enabled queue families */
1843  if ((err = setup_queue_families(ctx, &dev_info)))
1844  goto end;
1845 
1846  /* Finally create the device */
1847  ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc,
1848  &hwctx->act_dev);
1849 
1850  for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
1851  av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities);
1852  av_free((void *)dev_info.pQueueCreateInfos);
1853 
1854  if (ret != VK_SUCCESS) {
1855  av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n",
1856  ff_vk_ret2str(ret));
1857  for (int i = 0; i < dev_info.enabledExtensionCount; i++)
1858  av_free((void *)dev_info.ppEnabledExtensionNames[i]);
1859  av_free((void *)dev_info.ppEnabledExtensionNames);
1860  err = AVERROR_EXTERNAL;
1861  goto end;
1862  }
1863 
1864  /* Tiled images setting, use them by default */
1865  opt_d = av_dict_get(opts, "linear_images", NULL, 0);
1866  if (opt_d)
1867  p->use_linear_images = strtol(opt_d->value, NULL, 10);
1868 
1869  /* The disable_multiplane argument takes precedent over the option */
1870  p->disable_multiplane = disable_multiplane;
1871  if (!p->disable_multiplane) {
1872  opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0);
1873  if (opt_d)
1874  p->disable_multiplane = strtol(opt_d->value, NULL, 10);
1875  }
1876 
1877  /* Disable host pointer imports (by default on nvidia) */
1878  p->avoid_host_import = p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
1879  opt_d = av_dict_get(opts, "avoid_host_import", NULL, 0);
1880  if (opt_d)
1881  p->avoid_host_import = strtol(opt_d->value, NULL, 10);
1882 
1883  /* Set the public device feature struct and its pNext chain */
1884  hwctx->device_features = p->feats.device;
1885 
1886  /* Set the list of all active extensions */
1887  hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames;
1888  hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount;
1889 
1890  /* The extension lists need to be freed */
1891  ctx->free = vulkan_device_free;
1892 
1893 end:
1894  return err;
1895 }
1896 
1897 static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
1898 {
1899  VulkanDevicePriv *p = ctx->hwctx;
1900  pthread_mutex_lock(&p->qf_mutex[queue_family][index]);
1901 }
1902 
1903 static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
1904 {
1905  VulkanDevicePriv *p = ctx->hwctx;
1906  pthread_mutex_unlock(&p->qf_mutex[queue_family][index]);
1907 }
1908 
1910 {
1911  int err = 0;
1912  uint32_t qf_num;
1913  VulkanDevicePriv *p = ctx->hwctx;
1914  AVVulkanDeviceContext *hwctx = &p->p;
1915  FFVulkanFunctions *vk = &p->vkctx.vkfn;
1916  VkQueueFamilyProperties2 *qf;
1917  VkQueueFamilyVideoPropertiesKHR *qf_vid;
1918  VkPhysicalDeviceExternalSemaphoreInfo ext_sem_props_info;
1919  int graph_index, comp_index, tx_index, enc_index, dec_index;
1920 
1921  /* Set device extension flags */
1922  for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) {
1923  for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) {
1924  if (!strcmp(hwctx->enabled_dev_extensions[i],
1925  optional_device_exts[j].name)) {
1926  p->vkctx.extensions |= optional_device_exts[j].flag;
1927  break;
1928  }
1929  }
1930  }
1931 
1932  err = ff_vk_load_functions(ctx, vk, p->vkctx.extensions, 1, 1);
1933  if (err < 0) {
1934  av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n");
1935  return err;
1936  }
1937 
1938  p->props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
1939  p->props.pNext = &p->hprops;
1940  p->hprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
1941  p->hprops.pNext = &p->dprops;
1942  p->dprops.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
1943 
1944  vk->GetPhysicalDeviceProperties2(hwctx->phys_dev, &p->props);
1945  av_log(ctx, AV_LOG_VERBOSE, "Using device: %s\n",
1946  p->props.properties.deviceName);
1947  av_log(ctx, AV_LOG_VERBOSE, "Alignments:\n");
1948  av_log(ctx, AV_LOG_VERBOSE, " optimalBufferCopyRowPitchAlignment: %"PRIu64"\n",
1949  p->props.properties.limits.optimalBufferCopyRowPitchAlignment);
1950  av_log(ctx, AV_LOG_VERBOSE, " minMemoryMapAlignment: %zu\n",
1951  p->props.properties.limits.minMemoryMapAlignment);
1952  av_log(ctx, AV_LOG_VERBOSE, " nonCoherentAtomSize: %"PRIu64"\n",
1953  p->props.properties.limits.nonCoherentAtomSize);
1954  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY)
1955  av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n",
1956  p->hprops.minImportedHostPointerAlignment);
1957 
1958  vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &qf_num, NULL);
1959  if (!qf_num) {
1960  av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n");
1961  return AVERROR_EXTERNAL;
1962  }
1963 
1964  ext_sem_props_info = (VkPhysicalDeviceExternalSemaphoreInfo) {
1965  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
1966  };
1967 
1968  /* Opaque FD semaphore properties */
1969  ext_sem_props_info.handleType =
1970 #ifdef _WIN32
1971  IsWindows8OrGreater()
1972  ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
1973  : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT;
1974 #else
1975  VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
1976 #endif
1977  p->ext_sem_props_opaque.sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES;
1978  vk->GetPhysicalDeviceExternalSemaphoreProperties(hwctx->phys_dev,
1979  &ext_sem_props_info,
1980  &p->ext_sem_props_opaque);
1981 
1982  qf = av_malloc_array(qf_num, sizeof(VkQueueFamilyProperties2));
1983  if (!qf)
1984  return AVERROR(ENOMEM);
1985 
1986  qf_vid = av_malloc_array(qf_num, sizeof(VkQueueFamilyVideoPropertiesKHR));
1987  if (!qf_vid) {
1988  av_free(qf);
1989  return AVERROR(ENOMEM);
1990  }
1991 
1992  for (uint32_t i = 0; i < qf_num; i++) {
1993  qf_vid[i] = (VkQueueFamilyVideoPropertiesKHR) {
1994  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,
1995  };
1996  qf[i] = (VkQueueFamilyProperties2) {
1997  .sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,
1998  .pNext = p->vkctx.extensions & FF_VK_EXT_VIDEO_QUEUE ? &qf_vid[i] : NULL,
1999  };
2000  }
2001 
2002  vk->GetPhysicalDeviceQueueFamilyProperties2(hwctx->phys_dev, &qf_num, qf);
2003 
2004  p->qf_mutex = av_calloc(qf_num, sizeof(*p->qf_mutex));
2005  if (!p->qf_mutex) {
2006  err = AVERROR(ENOMEM);
2007  goto end;
2008  }
2009  p->nb_tot_qfs = qf_num;
2010 
2011  for (uint32_t i = 0; i < qf_num; i++) {
2012  p->qf_mutex[i] = av_calloc(qf[i].queueFamilyProperties.queueCount,
2013  sizeof(**p->qf_mutex));
2014  if (!p->qf_mutex[i]) {
2015  err = AVERROR(ENOMEM);
2016  goto end;
2017  }
2018  for (uint32_t j = 0; j < qf[i].queueFamilyProperties.queueCount; j++) {
2019  err = pthread_mutex_init(&p->qf_mutex[i][j], NULL);
2020  if (err != 0) {
2021  av_log(ctx, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n",
2022  av_err2str(err));
2023  err = AVERROR(err);
2024  goto end;
2025  }
2026  }
2027  }
2028 
2029 #if FF_API_VULKAN_FIXED_QUEUES
2031  graph_index = hwctx->nb_graphics_queues ? hwctx->queue_family_index : -1;
2032  comp_index = hwctx->nb_comp_queues ? hwctx->queue_family_comp_index : -1;
2033  tx_index = hwctx->nb_tx_queues ? hwctx->queue_family_tx_index : -1;
2034  dec_index = hwctx->nb_decode_queues ? hwctx->queue_family_decode_index : -1;
2035  enc_index = hwctx->nb_encode_queues ? hwctx->queue_family_encode_index : -1;
2036 
2037 #define CHECK_QUEUE(type, required, fidx, ctx_qf, qc) \
2038  do { \
2039  if (ctx_qf < 0 && required) { \
2040  av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing" \
2041  " in the context!\n", type); \
2042  err = AVERROR(EINVAL); \
2043  goto end; \
2044  } else if (fidx < 0 || ctx_qf < 0) { \
2045  break; \
2046  } else if (ctx_qf >= qf_num) { \
2047  av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \
2048  type, ctx_qf, qf_num); \
2049  err = AVERROR(EINVAL); \
2050  goto end; \
2051  } \
2052  \
2053  av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)" \
2054  " for%s%s%s%s%s\n", \
2055  ctx_qf, qc, \
2056  ctx_qf == graph_index ? " graphics" : "", \
2057  ctx_qf == comp_index ? " compute" : "", \
2058  ctx_qf == tx_index ? " transfers" : "", \
2059  ctx_qf == enc_index ? " encode" : "", \
2060  ctx_qf == dec_index ? " decode" : ""); \
2061  graph_index = (ctx_qf == graph_index) ? -1 : graph_index; \
2062  comp_index = (ctx_qf == comp_index) ? -1 : comp_index; \
2063  tx_index = (ctx_qf == tx_index) ? -1 : tx_index; \
2064  enc_index = (ctx_qf == enc_index) ? -1 : enc_index; \
2065  dec_index = (ctx_qf == dec_index) ? -1 : dec_index; \
2066  } while (0)
2067 
2068  CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index, hwctx->nb_graphics_queues);
2069  CHECK_QUEUE("compute", 1, comp_index, hwctx->queue_family_comp_index, hwctx->nb_comp_queues);
2070  CHECK_QUEUE("upload", 1, tx_index, hwctx->queue_family_tx_index, hwctx->nb_tx_queues);
2071  CHECK_QUEUE("decode", 0, dec_index, hwctx->queue_family_decode_index, hwctx->nb_decode_queues);
2072  CHECK_QUEUE("encode", 0, enc_index, hwctx->queue_family_encode_index, hwctx->nb_encode_queues);
2073 
2074 #undef CHECK_QUEUE
2075 
2076  /* Update the new queue family fields. If non-zero already,
2077  * it means API users have set it. */
2078  if (!hwctx->nb_qf) {
2079 #define ADD_QUEUE(ctx_qf, qc, flag) \
2080  do { \
2081  if (ctx_qf != -1) { \
2082  hwctx->qf[hwctx->nb_qf++] = (AVVulkanDeviceQueueFamily) { \
2083  .idx = ctx_qf, \
2084  .num = qc, \
2085  .flags = flag, \
2086  }; \
2087  } \
2088  } while (0)
2089 
2090  ADD_QUEUE(hwctx->queue_family_index, hwctx->nb_graphics_queues, VK_QUEUE_GRAPHICS_BIT);
2091  ADD_QUEUE(hwctx->queue_family_comp_index, hwctx->nb_comp_queues, VK_QUEUE_COMPUTE_BIT);
2092  ADD_QUEUE(hwctx->queue_family_tx_index, hwctx->nb_tx_queues, VK_QUEUE_TRANSFER_BIT);
2093  ADD_QUEUE(hwctx->queue_family_decode_index, hwctx->nb_decode_queues, VK_QUEUE_VIDEO_DECODE_BIT_KHR);
2094  ADD_QUEUE(hwctx->queue_family_encode_index, hwctx->nb_encode_queues, VK_QUEUE_VIDEO_ENCODE_BIT_KHR);
2095 #undef ADD_QUEUE
2096  }
2098 #endif
2099 
2100  for (int i = 0; i < hwctx->nb_qf; i++) {
2101  if (!hwctx->qf[i].video_caps &&
2102  hwctx->qf[i].flags & (VK_QUEUE_VIDEO_DECODE_BIT_KHR |
2103  VK_QUEUE_VIDEO_ENCODE_BIT_KHR)) {
2104  hwctx->qf[i].video_caps = qf_vid[hwctx->qf[i].idx].videoCodecOperations;
2105  }
2106  }
2107 
2108  /* Setup array for pQueueFamilyIndices with used queue families */
2109  p->nb_img_qfs = 0;
2110  for (int i = 0; i < hwctx->nb_qf; i++) {
2111  int seen = 0;
2112  /* Make sure each entry is unique
2113  * (VUID-VkBufferCreateInfo-sharingMode-01419) */
2114  for (int j = (i - 1); j >= 0; j--) {
2115  if (hwctx->qf[i].idx == hwctx->qf[j].idx) {
2116  seen = 1;
2117  break;
2118  }
2119  }
2120  if (!seen)
2121  p->img_qfs[p->nb_img_qfs++] = hwctx->qf[i].idx;
2122  }
2123 
2124 #if FF_API_VULKAN_SYNC_QUEUES
2126  if (!hwctx->lock_queue)
2127  hwctx->lock_queue = lock_queue;
2128  if (!hwctx->unlock_queue)
2129  hwctx->unlock_queue = unlock_queue;
2131 #endif
2132 
2133  /* Re-query device capabilities, in case the device was created externally */
2134  vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
2135 
2136  p->vkctx.device = ctx;
2137  p->vkctx.hwctx = hwctx;
2138 
2139  ff_vk_load_props(&p->vkctx);
2140  p->compute_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_COMPUTE_BIT, 0);
2141  p->transfer_qf = ff_vk_qf_find(&p->vkctx, VK_QUEUE_TRANSFER_BIT, 0);
2142 
2143  /* Re-query device capabilities, in case the device was created externally */
2144  vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops);
2145 
2146 end:
2147  av_free(qf_vid);
2148  av_free(qf);
2149  return err;
2150 }
2151 
2152 static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device,
2153  AVDictionary *opts, int flags)
2154 {
2155  VulkanDeviceSelection dev_select = { 0 };
2156  if (device && device[0]) {
2157  char *end = NULL;
2158  dev_select.index = strtol(device, &end, 10);
2159  if (end == device) {
2160  dev_select.index = 0;
2161  dev_select.name = device;
2162  }
2163  }
2164 
2165  return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
2166 }
2167 
2169  AVHWDeviceContext *src_ctx,
2170  AVDictionary *opts, int flags)
2171 {
2172  av_unused VulkanDeviceSelection dev_select = { 0 };
2173 
2174  /* If there's only one device on the system, then even if its not covered
2175  * by the following checks (e.g. non-PCIe ARM GPU), having an empty
2176  * dev_select will mean it'll get picked. */
2177  switch(src_ctx->type) {
2178 #if CONFIG_VAAPI
2179  case AV_HWDEVICE_TYPE_VAAPI: {
2180  AVVAAPIDeviceContext *src_hwctx = src_ctx->hwctx;
2181  VADisplay dpy = src_hwctx->display;
2182 #if VA_CHECK_VERSION(1, 15, 0)
2183  VAStatus vas;
2184  VADisplayAttribute attr = {
2185  .type = VADisplayPCIID,
2186  };
2187 #endif
2188  const char *vendor;
2189 
2190 #if VA_CHECK_VERSION(1, 15, 0)
2191  vas = vaGetDisplayAttributes(dpy, &attr, 1);
2192  if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED)
2193  dev_select.pci_device = (attr.value & 0xFFFF);
2194 #endif
2195 
2196  if (!dev_select.pci_device) {
2197  vendor = vaQueryVendorString(dpy);
2198  if (!vendor) {
2199  av_log(ctx, AV_LOG_ERROR, "Unable to get device info from VAAPI!\n");
2200  return AVERROR_EXTERNAL;
2201  }
2202 
2203  if (strstr(vendor, "AMD"))
2204  dev_select.vendor_id = 0x1002;
2205  }
2206 
2207  return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
2208  }
2209 #endif
2210 #if CONFIG_LIBDRM
2211  case AV_HWDEVICE_TYPE_DRM: {
2212  int err;
2213  struct stat drm_node_info;
2214  drmDevice *drm_dev_info;
2215  AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
2216 
2217  err = fstat(src_hwctx->fd, &drm_node_info);
2218  if (err) {
2219  av_log(ctx, AV_LOG_ERROR, "Unable to get node info from DRM fd: %s!\n",
2220  av_err2str(AVERROR(errno)));
2221  return AVERROR_EXTERNAL;
2222  }
2223 
2224  dev_select.drm_major = major(drm_node_info.st_dev);
2225  dev_select.drm_minor = minor(drm_node_info.st_dev);
2226  dev_select.has_drm = 1;
2227 
2228  err = drmGetDevice(src_hwctx->fd, &drm_dev_info);
2229  if (err) {
2230  av_log(ctx, AV_LOG_ERROR, "Unable to get device info from DRM fd: %s!\n",
2231  av_err2str(AVERROR(errno)));
2232  return AVERROR_EXTERNAL;
2233  }
2234 
2235  if (drm_dev_info->bustype == DRM_BUS_PCI)
2236  dev_select.pci_device = drm_dev_info->deviceinfo.pci->device_id;
2237 
2238  drmFreeDevice(&drm_dev_info);
2239 
2240  return vulkan_device_create_internal(ctx, &dev_select, 0, opts, flags);
2241  }
2242 #endif
2243 #if CONFIG_CUDA
2244  case AV_HWDEVICE_TYPE_CUDA: {
2245  AVHWDeviceContext *cuda_cu = src_ctx;
2246  AVCUDADeviceContext *src_hwctx = src_ctx->hwctx;
2247  AVCUDADeviceContextInternal *cu_internal = src_hwctx->internal;
2248  CudaFunctions *cu = cu_internal->cuda_dl;
2249 
2250  int ret = CHECK_CU(cu->cuDeviceGetUuid((CUuuid *)&dev_select.uuid,
2251  cu_internal->cuda_device));
2252  if (ret < 0) {
2253  av_log(ctx, AV_LOG_ERROR, "Unable to get UUID from CUDA!\n");
2254  return AVERROR_EXTERNAL;
2255  }
2256 
2257  dev_select.has_uuid = 1;
2258 
2259  /*
2260  * CUDA is not able to import multiplane images, so always derive a
2261  * Vulkan device with multiplane disabled.
2262  */
2263  return vulkan_device_create_internal(ctx, &dev_select, 1, opts, flags);
2264  }
2265 #endif
2266  default:
2267  return AVERROR(ENOSYS);
2268  }
2269 }
2270 
2272  const void *hwconfig,
2273  AVHWFramesConstraints *constraints)
2274 {
2275  int count = 0;
2276  VulkanDevicePriv *p = ctx->hwctx;
2277 
2278  for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
2280  p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2281  VK_IMAGE_TILING_OPTIMAL,
2282  NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0;
2283  }
2284 
2285  constraints->valid_sw_formats = av_malloc_array(count + 1,
2286  sizeof(enum AVPixelFormat));
2287  if (!constraints->valid_sw_formats)
2288  return AVERROR(ENOMEM);
2289 
2290  count = 0;
2291  for (enum AVPixelFormat i = 0; i < nb_vk_formats_list; i++) {
2293  p->use_linear_images ? VK_IMAGE_TILING_LINEAR :
2294  VK_IMAGE_TILING_OPTIMAL,
2295  NULL, NULL, NULL, NULL, p->disable_multiplane, 1) >= 0) {
2296  constraints->valid_sw_formats[count++] = vk_formats_list[i].pixfmt;
2297  }
2298  }
2299 
2300  constraints->valid_sw_formats[count++] = AV_PIX_FMT_NONE;
2301 
2302  constraints->min_width = 1;
2303  constraints->min_height = 1;
2304  constraints->max_width = p->props.properties.limits.maxImageDimension2D;
2305  constraints->max_height = p->props.properties.limits.maxImageDimension2D;
2306 
2307  constraints->valid_hw_formats = av_malloc_array(2, sizeof(enum AVPixelFormat));
2308  if (!constraints->valid_hw_formats)
2309  return AVERROR(ENOMEM);
2310 
2311  constraints->valid_hw_formats[0] = AV_PIX_FMT_VULKAN;
2312  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
2313 
2314  return 0;
2315 }
2316 
2317 static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req,
2318  VkMemoryPropertyFlagBits req_flags, const void *alloc_extension,
2319  VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
2320 {
2321  VkResult ret;
2322  int index = -1;
2323  VulkanDevicePriv *p = ctx->hwctx;
2324  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2325  AVVulkanDeviceContext *dev_hwctx = &p->p;
2326  VkMemoryAllocateInfo alloc_info = {
2327  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
2328  .pNext = alloc_extension,
2329  .allocationSize = req->size,
2330  };
2331 
2332  /* The vulkan spec requires memory types to be sorted in the "optimal"
2333  * order, so the first matching type we find will be the best/fastest one */
2334  for (int i = 0; i < p->mprops.memoryTypeCount; i++) {
2335  const VkMemoryType *type = &p->mprops.memoryTypes[i];
2336 
2337  /* The memory type must be supported by the requirements (bitfield) */
2338  if (!(req->memoryTypeBits & (1 << i)))
2339  continue;
2340 
2341  /* The memory type flags must include our properties */
2342  if ((type->propertyFlags & req_flags) != req_flags)
2343  continue;
2344 
2345  /* The memory type must be large enough */
2346  if (req->size > p->mprops.memoryHeaps[type->heapIndex].size)
2347  continue;
2348 
2349  /* Found a suitable memory type */
2350  index = i;
2351  break;
2352  }
2353 
2354  if (index < 0) {
2355  av_log(ctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n",
2356  req_flags);
2357  return AVERROR(EINVAL);
2358  }
2359 
2360  alloc_info.memoryTypeIndex = index;
2361 
2362  ret = vk->AllocateMemory(dev_hwctx->act_dev, &alloc_info,
2363  dev_hwctx->alloc, mem);
2364  if (ret != VK_SUCCESS) {
2365  av_log(ctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n",
2366  ff_vk_ret2str(ret));
2367  return AVERROR(ENOMEM);
2368  }
2369 
2370  *mem_flags |= p->mprops.memoryTypes[index].propertyFlags;
2371 
2372  return 0;
2373 }
2374 
2376 {
2377  av_unused AVVkFrameInternal *internal = f->internal;
2378 
2379 #if CONFIG_CUDA
2380  if (internal->cuda_fc_ref) {
2381  AVHWFramesContext *cuda_fc = (AVHWFramesContext *)internal->cuda_fc_ref->data;
2382  int planes = av_pix_fmt_count_planes(cuda_fc->sw_format);
2383  AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
2384  AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
2385  AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
2386  CudaFunctions *cu = cu_internal->cuda_dl;
2387 
2388  for (int i = 0; i < planes; i++) {
2389  if (internal->cu_sem[i])
2390  CHECK_CU(cu->cuDestroyExternalSemaphore(internal->cu_sem[i]));
2391  if (internal->cu_mma[i])
2392  CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i]));
2393  if (internal->ext_mem[i])
2394  CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i]));
2395 #ifdef _WIN32
2396  if (internal->ext_sem_handle[i])
2397  CloseHandle(internal->ext_sem_handle[i]);
2398  if (internal->ext_mem_handle[i])
2399  CloseHandle(internal->ext_mem_handle[i]);
2400 #endif
2401  }
2402 
2403  av_buffer_unref(&internal->cuda_fc_ref);
2404  }
2405 #endif
2406 
2407  pthread_mutex_destroy(&internal->update_mutex);
2408  av_freep(&f->internal);
2409 }
2410 
2412 {
2413  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2414  AVVulkanDeviceContext *hwctx = &p->p;
2415  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2416  int nb_images = ff_vk_count_images(f);
2417  int nb_sems = 0;
2418 
2419  while (nb_sems < FF_ARRAY_ELEMS(f->sem) && f->sem[nb_sems])
2420  nb_sems++;
2421 
2422  if (nb_sems) {
2423  VkSemaphoreWaitInfo sem_wait = {
2424  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
2425  .flags = 0x0,
2426  .pSemaphores = f->sem,
2427  .pValues = f->sem_value,
2428  .semaphoreCount = nb_sems,
2429  };
2430 
2431  vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
2432  }
2433 
2435 
2436  for (int i = 0; i < nb_images; i++) {
2437  vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc);
2438  vk->FreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc);
2439  vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc);
2440  }
2441 
2442  av_free(f);
2443 }
2444 
2445 static void vulkan_frame_free_cb(void *opaque, uint8_t *data)
2446 {
2447  vulkan_frame_free(opaque, (AVVkFrame*)data);
2448 }
2449 
2451  void *alloc_pnext, size_t alloc_pnext_stride)
2452 {
2453  int img_cnt = 0, err;
2454  VkResult ret;
2455  AVHWDeviceContext *ctx = hwfc->device_ctx;
2456  VulkanDevicePriv *p = ctx->hwctx;
2457  AVVulkanDeviceContext *hwctx = &p->p;
2458  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2459  VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } };
2460 
2461  while (f->img[img_cnt]) {
2462  int use_ded_mem;
2463  VkImageMemoryRequirementsInfo2 req_desc = {
2464  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
2465  .image = f->img[img_cnt],
2466  };
2467  VkMemoryDedicatedAllocateInfo ded_alloc = {
2468  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
2469  .pNext = (void *)(((uint8_t *)alloc_pnext) + img_cnt*alloc_pnext_stride),
2470  };
2471  VkMemoryDedicatedRequirements ded_req = {
2472  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
2473  };
2474  VkMemoryRequirements2 req = {
2475  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
2476  .pNext = &ded_req,
2477  };
2478 
2479  vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req);
2480 
2481  if (f->tiling == VK_IMAGE_TILING_LINEAR)
2482  req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size,
2483  p->props.properties.limits.minMemoryMapAlignment);
2484 
2485  /* In case the implementation prefers/requires dedicated allocation */
2486  use_ded_mem = ded_req.prefersDedicatedAllocation |
2487  ded_req.requiresDedicatedAllocation;
2488  if (use_ded_mem)
2489  ded_alloc.image = f->img[img_cnt];
2490 
2491  /* Allocate memory */
2492  if ((err = alloc_mem(ctx, &req.memoryRequirements,
2493  f->tiling == VK_IMAGE_TILING_LINEAR ?
2494  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT :
2495  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
2496  use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext,
2497  &f->flags, &f->mem[img_cnt])))
2498  return err;
2499 
2500  f->size[img_cnt] = req.memoryRequirements.size;
2501  bind_info[img_cnt].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
2502  bind_info[img_cnt].image = f->img[img_cnt];
2503  bind_info[img_cnt].memory = f->mem[img_cnt];
2504 
2505  img_cnt++;
2506  }
2507 
2508  /* Bind the allocated memory to the images */
2509  ret = vk->BindImageMemory2(hwctx->act_dev, img_cnt, bind_info);
2510  if (ret != VK_SUCCESS) {
2511  av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
2512  ff_vk_ret2str(ret));
2513  return AVERROR_EXTERNAL;
2514  }
2515 
2516  return 0;
2517 }
2518 
2519 enum PrepMode {
2527 };
2528 
2529 static void switch_new_props(enum PrepMode pmode, VkImageLayout *new_layout,
2530  VkAccessFlags2 *new_access)
2531 {
2532  switch (pmode) {
2533  case PREP_MODE_GENERAL:
2534  *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2535  *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2536  break;
2537  case PREP_MODE_WRITE:
2538  *new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
2539  *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2540  break;
2542  *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2543  *new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
2544  break;
2546  *new_layout = VK_IMAGE_LAYOUT_GENERAL;
2547  *new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
2548  break;
2550  *new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DST_KHR;
2551  *new_access = VK_ACCESS_TRANSFER_WRITE_BIT;
2552  break;
2554  *new_layout = VK_IMAGE_LAYOUT_VIDEO_DECODE_DPB_KHR;
2555  *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2556  break;
2558  *new_layout = VK_IMAGE_LAYOUT_VIDEO_ENCODE_DPB_KHR;
2559  *new_access = VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT;
2560  break;
2561  }
2562 }
2563 
2565  AVVkFrame *frame, enum PrepMode pmode)
2566 {
2567  int err;
2568  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2569  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2570  VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
2571  int nb_img_bar = 0;
2572 
2573  VkImageLayout new_layout;
2574  VkAccessFlags2 new_access;
2575  switch_new_props(pmode, &new_layout, &new_access);
2576 
2577  uint32_t dst_qf = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2578  VkPipelineStageFlagBits2 src_stage = VK_PIPELINE_STAGE_2_NONE;
2579  if (pmode == PREP_MODE_EXTERNAL_EXPORT) {
2580  dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR;
2581  src_stage = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT;
2582  }
2583 
2584  /* This is dirty - but it works. The vulkan.c dependency system doesn't
2585  * free non-refcounted frames, and non-refcounted hardware frames cannot
2586  * happen anywhere outside of here. */
2587  AVBufferRef tmp_ref = {
2588  .data = (uint8_t *)hwfc,
2589  };
2590  AVFrame tmp_frame = {
2591  .data[0] = (uint8_t *)frame,
2592  .hw_frames_ctx = &tmp_ref,
2593  };
2594 
2595  VkCommandBuffer cmd_buf;
2596  FFVkExecContext *exec = ff_vk_exec_get(&p->vkctx, ectx);
2597  cmd_buf = exec->buf;
2598  ff_vk_exec_start(&p->vkctx, exec);
2599 
2600  err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, &tmp_frame,
2601  VK_PIPELINE_STAGE_2_NONE,
2602  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
2603  if (err < 0)
2604  return err;
2605 
2606  ff_vk_frame_barrier(&p->vkctx, exec, &tmp_frame, img_bar, &nb_img_bar,
2607  src_stage,
2608  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
2609  new_access, new_layout, dst_qf);
2610 
2611  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
2612  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
2613  .pImageMemoryBarriers = img_bar,
2614  .imageMemoryBarrierCount = nb_img_bar,
2615  });
2616 
2617  err = ff_vk_exec_submit(&p->vkctx, exec);
2618  if (err < 0)
2619  return err;
2620 
2621  /* We can do this because there are no real dependencies */
2622  ff_vk_exec_discard_deps(&p->vkctx, exec);
2623 
2624  return 0;
2625 }
2626 
2628  AVVkFrame *frame, enum PrepMode pmode)
2629 {
2630  VkResult ret;
2631  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2632  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2633  VkHostImageLayoutTransitionInfoEXT layout_change[AV_NUM_DATA_POINTERS];
2634  int nb_images = ff_vk_count_images(frame);
2635 
2636  VkImageLayout new_layout;
2637  VkAccessFlags2 new_access;
2638  switch_new_props(pmode, &new_layout, &new_access);
2639 
2640  int i;
2641  for (i = 0; i < p->vkctx.host_image_props.copyDstLayoutCount; i++) {
2642  if (p->vkctx.host_image_props.pCopyDstLayouts[i] == new_layout)
2643  break;
2644  }
2645  if (i == p->vkctx.host_image_props.copyDstLayoutCount)
2646  return AVERROR(ENOTSUP);
2647 
2648  for (i = 0; i < nb_images; i++) {
2649  layout_change[i] = (VkHostImageLayoutTransitionInfoEXT) {
2650  .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
2651  .image = frame->img[i],
2652  .oldLayout = frame->layout[i],
2653  .newLayout = new_layout,
2654  .subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
2655  .subresourceRange.layerCount = 1,
2656  .subresourceRange.levelCount = 1,
2657  };
2658  frame->layout[i] = new_layout;
2659  }
2660 
2661  ret = vk->TransitionImageLayoutEXT(p->vkctx.hwctx->act_dev,
2662  nb_images, layout_change);
2663  if (ret != VK_SUCCESS) {
2664  av_log(hwfc, AV_LOG_ERROR, "Unable to prepare frame: %s\n",
2665  ff_vk_ret2str(ret));
2666  return AVERROR_EXTERNAL;
2667  }
2668 
2669  return 0;
2670 }
2671 
2673  AVVkFrame *frame, enum PrepMode pmode)
2674 {
2675  int err = 0;
2676  AVVulkanFramesContext *hwfc_vk = hwfc->hwctx;
2677  if (hwfc_vk->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
2678  (pmode != PREP_MODE_EXTERNAL_EXPORT) &&
2679  (pmode != PREP_MODE_EXTERNAL_IMPORT))
2680  err = switch_layout_host(hwfc, ectx, frame, pmode);
2681 
2682  if (err != AVERROR(ENOTSUP))
2683  return err;
2684 
2685  return switch_layout(hwfc, ectx, frame, pmode);
2686 }
2687 
2688 static inline void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format,
2689  int frame_w, int frame_h, int plane)
2690 {
2692 
2693  /* Currently always true unless gray + alpha support is added */
2694  if (!plane || (plane == 3) || desc->flags & AV_PIX_FMT_FLAG_RGB ||
2695  !(desc->flags & AV_PIX_FMT_FLAG_PLANAR)) {
2696  *w = frame_w;
2697  *h = frame_h;
2698  return;
2699  }
2700 
2701  *w = AV_CEIL_RSHIFT(frame_w, desc->log2_chroma_w);
2702  *h = AV_CEIL_RSHIFT(frame_h, desc->log2_chroma_h);
2703 }
2704 
2706  VkImageTiling tiling, VkImageUsageFlagBits usage,
2707  VkImageCreateFlags flags, int nb_layers,
2708  void *create_pnext)
2709 {
2710  int err;
2711  VkResult ret;
2712  AVVulkanFramesContext *hwfc_vk = hwfc->hwctx;
2713  AVHWDeviceContext *ctx = hwfc->device_ctx;
2714  VulkanDevicePriv *p = ctx->hwctx;
2715  AVVulkanDeviceContext *hwctx = &p->p;
2716  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2717  AVVkFrame *f;
2718 
2719  VkSemaphoreTypeCreateInfo sem_type_info = {
2720  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
2721  .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
2722  .initialValue = 0,
2723  };
2724  VkSemaphoreCreateInfo sem_spawn = {
2725  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
2726  .pNext = &sem_type_info,
2727  };
2728 
2729  VkExportSemaphoreCreateInfo ext_sem_info_opaque = {
2730  .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
2731 #ifdef _WIN32
2732  .handleTypes = IsWindows8OrGreater()
2733  ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
2734  : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
2735 #else
2736  .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
2737 #endif
2738  };
2739 
2740  /* Check if exporting is supported before chaining any structs */
2741  if (p->ext_sem_props_opaque.externalSemaphoreFeatures & VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT) {
2742  if (p->vkctx.extensions & (FF_VK_EXT_EXTERNAL_WIN32_SEM | FF_VK_EXT_EXTERNAL_FD_SEM))
2743  ff_vk_link_struct(&sem_type_info, &ext_sem_info_opaque);
2744  }
2745 
2746  f = av_vk_frame_alloc();
2747  if (!f) {
2748  av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
2749  return AVERROR(ENOMEM);
2750  }
2751 
2752  // TODO: check width and height for alignment in case of multiplanar (must be mod-2 if subsampled)
2753 
2754  /* Create the images */
2755  for (int i = 0; (hwfc_vk->format[i] != VK_FORMAT_UNDEFINED); i++) {
2756  VkImageCreateInfo create_info = {
2757  .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
2758  .pNext = create_pnext,
2759  .imageType = VK_IMAGE_TYPE_2D,
2760  .format = hwfc_vk->format[i],
2761  .extent.depth = 1,
2762  .mipLevels = 1,
2763  .arrayLayers = nb_layers,
2764  .flags = flags,
2765  .tiling = tiling,
2766  .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
2767  .usage = usage,
2768  .samples = VK_SAMPLE_COUNT_1_BIT,
2769  .pQueueFamilyIndices = p->img_qfs,
2770  .queueFamilyIndexCount = p->nb_img_qfs,
2771  .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2772  VK_SHARING_MODE_EXCLUSIVE,
2773  };
2774 
2775  get_plane_wh(&create_info.extent.width, &create_info.extent.height,
2776  hwfc->sw_format, hwfc->width, hwfc->height, i);
2777 
2778  ret = vk->CreateImage(hwctx->act_dev, &create_info,
2779  hwctx->alloc, &f->img[i]);
2780  if (ret != VK_SUCCESS) {
2781  av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
2782  ff_vk_ret2str(ret));
2783  err = AVERROR(EINVAL);
2784  goto fail;
2785  }
2786 
2787  /* Create semaphore */
2788  ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
2789  hwctx->alloc, &f->sem[i]);
2790  if (ret != VK_SUCCESS) {
2791  av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
2792  ff_vk_ret2str(ret));
2793  err = AVERROR_EXTERNAL;
2794  goto fail;
2795  }
2796 
2797  f->queue_family[i] = p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0];
2798  f->layout[i] = create_info.initialLayout;
2799  f->access[i] = 0x0;
2800  f->sem_value[i] = 0;
2801  }
2802 
2803  f->flags = 0x0;
2804  f->tiling = tiling;
2805 
2806  *frame = f;
2807  return 0;
2808 
2809 fail:
2810  vulkan_frame_free(hwfc, f);
2811  return err;
2812 }
2813 
2814 /* Checks if an export flag is enabled, and if it is ORs it with *iexp */
2816  VkExternalMemoryHandleTypeFlags *comp_handle_types,
2817  VkExternalMemoryHandleTypeFlags *iexp,
2818  VkExternalMemoryHandleTypeFlagBits exp)
2819 {
2820  VkResult ret;
2821  AVVulkanFramesContext *hwctx = hwfc->hwctx;
2822  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2823  AVVulkanDeviceContext *dev_hwctx = &p->p;
2824  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2825 
2826  const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info =
2828  VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT);
2829  int has_mods = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info;
2830  int nb_mods;
2831 
2832  VkExternalImageFormatProperties eprops = {
2833  .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
2834  };
2835  VkImageFormatProperties2 props = {
2836  .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
2837  .pNext = &eprops,
2838  };
2839  VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
2840  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
2841  .pNext = NULL,
2842  .pQueueFamilyIndices = p->img_qfs,
2843  .queueFamilyIndexCount = p->nb_img_qfs,
2844  .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
2845  VK_SHARING_MODE_EXCLUSIVE,
2846  };
2847  VkPhysicalDeviceExternalImageFormatInfo enext = {
2848  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
2849  .handleType = exp,
2850  .pNext = has_mods ? &phy_dev_mod_info : NULL,
2851  };
2852  VkPhysicalDeviceImageFormatInfo2 pinfo = {
2853  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
2854  .pNext = !exp ? NULL : &enext,
2855  .format = vk_find_format_entry(hwfc->sw_format)->vkf,
2856  .type = VK_IMAGE_TYPE_2D,
2857  .tiling = hwctx->tiling,
2858  .usage = hwctx->usage,
2859  .flags = VK_IMAGE_CREATE_ALIAS_BIT,
2860  };
2861 
2862  nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1;
2863  for (int i = 0; i < nb_mods; i++) {
2864  if (has_mods)
2865  phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[i];
2866 
2867  ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
2868  &pinfo, &props);
2869 
2870  if (ret == VK_SUCCESS) {
2871  *iexp |= exp;
2872  *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
2873  }
2874  }
2875 }
2876 
2877 static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size)
2878 {
2879  int err;
2880  AVVkFrame *f;
2881  AVBufferRef *avbuf = NULL;
2882  AVHWFramesContext *hwfc = opaque;
2883  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2884  VulkanFramesPriv *fp = hwfc->hwctx;
2885  AVVulkanFramesContext *hwctx = &fp->p;
2886  VkExternalMemoryHandleTypeFlags e = 0x0;
2887  VkExportMemoryAllocateInfo eminfo[AV_NUM_DATA_POINTERS];
2888 
2889  VkExternalMemoryImageCreateInfo eiinfo = {
2890  .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
2891  .pNext = hwctx->create_pnext,
2892  };
2893 
2894 #ifdef _WIN32
2895  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY)
2896  try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater()
2897  ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
2898  : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT);
2899 #else
2900  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY)
2901  try_export_flags(hwfc, &eiinfo.handleTypes, &e,
2902  VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT);
2903 
2904  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_DMABUF_MEMORY &&
2905  hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
2906  try_export_flags(hwfc, &eiinfo.handleTypes, &e,
2907  VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2908 #endif
2909 
2910  for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) {
2911  eminfo[i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO;
2912  eminfo[i].pNext = hwctx->alloc_pnext[i];
2913  eminfo[i].handleTypes = e;
2914  }
2915 
2916  err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
2917  hwctx->nb_layers,
2918  eiinfo.handleTypes ? &eiinfo : hwctx->create_pnext);
2919  if (err)
2920  return NULL;
2921 
2922  err = alloc_bind_mem(hwfc, f, eminfo, sizeof(*eminfo));
2923  if (err)
2924  goto fail;
2925 
2926  if ( (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
2927  !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR))
2928  err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DPB);
2929  else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)
2930  err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_DECODING_DST);
2931  else if (hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR)
2932  err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_ENCODING_DPB);
2933  else if (hwctx->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
2934  err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_WRITE);
2935  else
2936  err = prepare_frame(hwfc, &fp->compute_exec, f, PREP_MODE_GENERAL);
2937  if (err)
2938  goto fail;
2939 
2940  avbuf = av_buffer_create((uint8_t *)f, sizeof(AVVkFrame),
2941  vulkan_frame_free_cb, hwfc, 0);
2942  if (!avbuf)
2943  goto fail;
2944 
2945  return avbuf;
2946 
2947 fail:
2948  vulkan_frame_free(hwfc, f);
2949  return NULL;
2950 }
2951 
2953 {
2955 }
2956 
2958 {
2960 }
2961 
2963 {
2964  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2965  VulkanFramesPriv *fp = hwfc->hwctx;
2966 
2967  if (fp->modifier_info) {
2968  if (fp->modifier_info->pDrmFormatModifiers)
2969  av_freep(&fp->modifier_info->pDrmFormatModifiers);
2970  av_freep(&fp->modifier_info);
2971  }
2972 
2973  ff_vk_exec_pool_free(&p->vkctx, &fp->compute_exec);
2974  ff_vk_exec_pool_free(&p->vkctx, &fp->upload_exec);
2975  ff_vk_exec_pool_free(&p->vkctx, &fp->download_exec);
2976 
2977  av_buffer_pool_uninit(&fp->tmp);
2978 }
2979 
2981 {
2982  int err;
2983  AVVkFrame *f;
2984  VulkanFramesPriv *fp = hwfc->hwctx;
2985  AVVulkanFramesContext *hwctx = &fp->p;
2986  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
2987  AVVulkanDeviceContext *dev_hwctx = &p->p;
2988  VkImageUsageFlags supported_usage;
2989  FFVulkanFunctions *vk = &p->vkctx.vkfn;
2990  const struct FFVkFormatEntry *fmt;
2991  int disable_multiplane = p->disable_multiplane ||
2993  int is_lone_dpb = ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_DPB_BIT_KHR) ||
2994  ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DPB_BIT_KHR) &&
2995  !(hwctx->usage & VK_IMAGE_USAGE_VIDEO_DECODE_DST_BIT_KHR)));
2996 
2997  /* Defaults */
2998  if (!hwctx->nb_layers)
2999  hwctx->nb_layers = 1;
3000 
3001  /* VK_IMAGE_TILING_OPTIMAL == 0, can't check for it really */
3002  if (p->use_linear_images &&
3003  (hwctx->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT))
3004  hwctx->tiling = VK_IMAGE_TILING_LINEAR;
3005 
3006 
3007  fmt = vk_find_format_entry(hwfc->sw_format);
3008  if (!fmt) {
3009  av_log(hwfc, AV_LOG_ERROR, "Unsupported pixel format: %s!\n",
3011  return AVERROR(EINVAL);
3012  }
3013 
3014  if (hwctx->format[0] != VK_FORMAT_UNDEFINED) {
3015  if (hwctx->format[0] != fmt->vkf) {
3016  for (int i = 0; i < fmt->nb_images_fallback; i++) {
3017  if (hwctx->format[i] != fmt->fallback[i]) {
3018  av_log(hwfc, AV_LOG_ERROR, "Incompatible Vulkan format given "
3019  "for the current sw_format %s!\n",
3021  return AVERROR(EINVAL);
3022  }
3023  }
3024  }
3025 
3026  /* Check if the sw_format itself is supported */
3027  err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
3028  hwctx->tiling, NULL,
3029  NULL, NULL, &supported_usage, 0,
3030  !hwctx->usage ||
3031  (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
3032  if (err < 0) {
3033  av_log(hwfc, AV_LOG_ERROR, "Unsupported sw format: %s!\n",
3035  return AVERROR(EINVAL);
3036  }
3037  } else {
3038  err = vkfmt_from_pixfmt2(hwfc->device_ctx, hwfc->sw_format,
3039  hwctx->tiling, hwctx->format, NULL,
3040  NULL, &supported_usage,
3041  disable_multiplane,
3042  !hwctx->usage ||
3043  (hwctx->usage & VK_IMAGE_USAGE_STORAGE_BIT));
3044  if (err < 0)
3045  return err;
3046  }
3047 
3048  /* Lone DPB images do not need additional flags. */
3049  if (!is_lone_dpb) {
3050  /* Image usage flags */
3051  hwctx->usage |= supported_usage & (VK_IMAGE_USAGE_TRANSFER_DST_BIT |
3052  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
3053  VK_IMAGE_USAGE_STORAGE_BIT |
3054  VK_IMAGE_USAGE_SAMPLED_BIT);
3055 
3056  if (p->vkctx.extensions & FF_VK_EXT_HOST_IMAGE_COPY &&
3057  !(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY) &&
3058  !(p->dprops.driverID == VK_DRIVER_ID_MOLTENVK))
3059  hwctx->usage |= supported_usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT;
3060 
3061  /* Enables encoding of images, if supported by format and extensions */
3062  if ((supported_usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3063  (p->vkctx.extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE) &&
3064  (p->vkctx.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1))
3065  hwctx->usage |= VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR;
3066 
3067  /* Image creation flags.
3068  * Only fill them in automatically if the image is not going to be used as
3069  * a DPB-only image, and we have SAMPLED/STORAGE bits set. */
3070  if (!hwctx->img_flags) {
3071  int sampleable = hwctx->usage & (VK_IMAGE_USAGE_SAMPLED_BIT |
3072  VK_IMAGE_USAGE_STORAGE_BIT);
3073  hwctx->img_flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
3074  if (sampleable) {
3075  hwctx->img_flags |= VK_IMAGE_CREATE_ALIAS_BIT;
3076  if ((fmt->vk_planes > 1) && (hwctx->format[0] == fmt->vkf))
3077  hwctx->img_flags |= VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
3078  }
3079  }
3080  }
3081 
3082  /* If the image has an ENCODE_SRC usage, and the maintenance1
3083  * extension is supported, check if it has a profile list.
3084  * If there's no profile list, or it has no encode operations,
3085  * then allow creating the image with no specific profile. */
3086  if ((hwctx->usage & VK_IMAGE_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) &&
3087  (p->vkctx.extensions & FF_VK_EXT_VIDEO_ENCODE_QUEUE) &&
3088  (p->vkctx.extensions & FF_VK_EXT_VIDEO_MAINTENANCE_1)) {
3089  const VkVideoProfileListInfoKHR *pl;
3090  pl = ff_vk_find_struct(hwctx->create_pnext, VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR);
3091  if (!pl) {
3092  hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3093  } else {
3094  uint32_t i;
3095  for (i = 0; i < pl->profileCount; i++) {
3096  /* Video ops start at exactly 0x00010000 */
3097  if (pl->pProfiles[i].videoCodecOperation & 0xFFFF0000)
3098  break;
3099  }
3100  if (i == pl->profileCount)
3101  hwctx->img_flags |= VK_IMAGE_CREATE_VIDEO_PROFILE_INDEPENDENT_BIT_KHR;
3102  }
3103  }
3104 
3105  if (!hwctx->lock_frame)
3106  hwctx->lock_frame = lock_frame;
3107 
3108  if (!hwctx->unlock_frame)
3109  hwctx->unlock_frame = unlock_frame;
3110 
3111  err = ff_vk_exec_pool_init(&p->vkctx, p->compute_qf, &fp->compute_exec,
3112  p->compute_qf->num, 0, 0, 0, NULL);
3113  if (err)
3114  return err;
3115 
3116  err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->upload_exec,
3117  p->transfer_qf->num*2, 0, 0, 0, NULL);
3118  if (err)
3119  return err;
3120 
3121  err = ff_vk_exec_pool_init(&p->vkctx, p->transfer_qf, &fp->download_exec,
3122  p->transfer_qf->num, 0, 0, 0, NULL);
3123  if (err)
3124  return err;
3125 
3126  /* Test to see if allocation will fail */
3127  err = create_frame(hwfc, &f, hwctx->tiling, hwctx->usage, hwctx->img_flags,
3128  hwctx->nb_layers, hwctx->create_pnext);
3129  if (err)
3130  return err;
3131 
3132  /* Collect `VkDrmFormatModifierPropertiesEXT` for each plane. Required for DRM export. */
3133  if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS && hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
3134  VkImageDrmFormatModifierPropertiesEXT drm_mod = {
3135  .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
3136  };
3137  err = vk->GetImageDrmFormatModifierPropertiesEXT(dev_hwctx->act_dev, f->img[0],
3138  &drm_mod);
3139  if (err != VK_SUCCESS) {
3140  av_log(hwfc, AV_LOG_ERROR, "Failed to get image DRM format modifier properties");
3141  vulkan_frame_free(hwfc, f);
3142  return AVERROR_EXTERNAL;
3143  }
3144  for (int i = 0; i < fmt->vk_planes; ++i) {
3145  VkDrmFormatModifierPropertiesListEXT modp;
3146  VkFormatProperties2 fmtp;
3147  VkDrmFormatModifierPropertiesEXT *mod_props = NULL;
3148 
3149  modp = (VkDrmFormatModifierPropertiesListEXT) {
3150  .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
3151  };
3152  fmtp = (VkFormatProperties2) {
3153  .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
3154  .pNext = &modp,
3155  };
3156 
3157  /* query drmFormatModifierCount by keeping pDrmFormatModifierProperties NULL */
3158  vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
3159 
3160  modp.pDrmFormatModifierProperties =
3161  av_calloc(modp.drmFormatModifierCount, sizeof(*modp.pDrmFormatModifierProperties));
3162  if (!modp.pDrmFormatModifierProperties) {
3163  vulkan_frame_free(hwfc, f);
3164  return AVERROR(ENOMEM);
3165  }
3166  vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt->fallback[i], &fmtp);
3167 
3168  for (uint32_t i = 0; i < modp.drmFormatModifierCount; ++i) {
3169  VkDrmFormatModifierPropertiesEXT *m = &modp.pDrmFormatModifierProperties[i];
3170  if (m->drmFormatModifier == drm_mod.drmFormatModifier) {
3171  mod_props = m;
3172  break;
3173  }
3174  }
3175 
3176  if (mod_props == NULL) {
3177  av_log(hwfc, AV_LOG_ERROR, "No DRM format modifier properties found for modifier 0x%016"PRIx64"\n",
3178  drm_mod.drmFormatModifier);
3179  av_free(modp.pDrmFormatModifierProperties);
3180  vulkan_frame_free(hwfc, f);
3181  return AVERROR_EXTERNAL;
3182  }
3183 
3184  fp->drm_format_modifier_properties[i] = *mod_props;
3185  av_free(modp.pDrmFormatModifierProperties);
3186  }
3187  }
3188 
3189  vulkan_frame_free(hwfc, f);
3190 
3191  /* If user did not specify a pool, hwfc->pool will be set to the internal one
3192  * in hwcontext.c just after this gets called */
3193  if (!hwfc->pool) {
3195  hwfc, vulkan_pool_alloc,
3196  NULL);
3197  if (!ffhwframesctx(hwfc)->pool_internal)
3198  return AVERROR(ENOMEM);
3199  }
3200 
3201  return 0;
3202 }
3203 
3205 {
3206  frame->buf[0] = av_buffer_pool_get(hwfc->pool);
3207  if (!frame->buf[0])
3208  return AVERROR(ENOMEM);
3209 
3210  frame->data[0] = frame->buf[0]->data;
3211  frame->format = AV_PIX_FMT_VULKAN;
3212  frame->width = hwfc->width;
3213  frame->height = hwfc->height;
3214 
3215  return 0;
3216 }
3217 
3219  enum AVHWFrameTransferDirection dir,
3220  enum AVPixelFormat **formats)
3221 {
3222  enum AVPixelFormat *fmts;
3223  int n = 2;
3224 
3225 #if CONFIG_CUDA
3226  n++;
3227 #endif
3228  fmts = av_malloc_array(n, sizeof(*fmts));
3229  if (!fmts)
3230  return AVERROR(ENOMEM);
3231 
3232  n = 0;
3233  fmts[n++] = hwfc->sw_format;
3234 #if CONFIG_CUDA
3235  fmts[n++] = AV_PIX_FMT_CUDA;
3236 #endif
3237  fmts[n++] = AV_PIX_FMT_NONE;
3238 
3239  *formats = fmts;
3240  return 0;
3241 }
3242 
3243 #if CONFIG_LIBDRM
3244 static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
3245 {
3246  vulkan_frame_free(hwfc, hwmap->priv);
3247 }
3248 
3249 static const struct {
3250  uint32_t drm_fourcc;
3251  VkFormat vk_format;
3252 } vulkan_drm_format_map[] = {
3253  { DRM_FORMAT_R8, VK_FORMAT_R8_UNORM },
3254  { DRM_FORMAT_R16, VK_FORMAT_R16_UNORM },
3255  { DRM_FORMAT_GR88, VK_FORMAT_R8G8_UNORM },
3256  { DRM_FORMAT_RG88, VK_FORMAT_R8G8_UNORM },
3257  { DRM_FORMAT_GR1616, VK_FORMAT_R16G16_UNORM },
3258  { DRM_FORMAT_RG1616, VK_FORMAT_R16G16_UNORM },
3259  { DRM_FORMAT_ARGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3260  { DRM_FORMAT_XRGB8888, VK_FORMAT_B8G8R8A8_UNORM },
3261  { DRM_FORMAT_ABGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3262  { DRM_FORMAT_XBGR8888, VK_FORMAT_R8G8B8A8_UNORM },
3263  { DRM_FORMAT_ARGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3264  { DRM_FORMAT_ABGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3265  { DRM_FORMAT_XRGB2101010, VK_FORMAT_A2B10G10R10_UNORM_PACK32 },
3266  { DRM_FORMAT_XBGR2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 },
3267 
3268  // All these DRM_FORMATs were added in the same libdrm commit.
3269 #ifdef DRM_FORMAT_XYUV8888
3270  { DRM_FORMAT_XYUV8888, VK_FORMAT_R8G8B8A8_UNORM },
3271  { DRM_FORMAT_XVYU2101010, VK_FORMAT_A2R10G10B10_UNORM_PACK32 } ,
3272  { DRM_FORMAT_XVYU12_16161616, VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16 } ,
3273  { DRM_FORMAT_XVYU16161616, VK_FORMAT_R16G16B16A16_UNORM } ,
3274 #endif
3275 };
3276 
3277 static inline VkFormat drm_to_vulkan_fmt(uint32_t drm_fourcc)
3278 {
3279  for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
3280  if (vulkan_drm_format_map[i].drm_fourcc == drm_fourcc)
3281  return vulkan_drm_format_map[i].vk_format;
3282  return VK_FORMAT_UNDEFINED;
3283 }
3284 
3285 static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **frame,
3286  const AVFrame *src, int flags)
3287 {
3288  int err = 0;
3289  VkResult ret;
3290  AVVkFrame *f;
3291  int bind_counts = 0;
3292  AVHWDeviceContext *ctx = hwfc->device_ctx;
3293  VulkanDevicePriv *p = ctx->hwctx;
3294  AVVulkanDeviceContext *hwctx = &p->p;
3295  FFVulkanFunctions *vk = &p->vkctx.vkfn;
3296  const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
3297  VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES];
3298  VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES];
3299 
3300  for (int i = 0; i < desc->nb_layers; i++) {
3301  if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) {
3302  av_log(ctx, AV_LOG_ERROR, "Unsupported DMABUF layer format %#08x!\n",
3303  desc->layers[i].format);
3304  return AVERROR(EINVAL);
3305  }
3306  }
3307 
3308  if (!(f = av_vk_frame_alloc())) {
3309  av_log(ctx, AV_LOG_ERROR, "Unable to allocate memory for AVVkFrame!\n");
3310  err = AVERROR(ENOMEM);
3311  goto fail;
3312  }
3313 
3314  f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
3315 
3316  for (int i = 0; i < desc->nb_layers; i++) {
3317  const int planes = desc->layers[i].nb_planes;
3318 
3319  /* Semaphore */
3320  VkSemaphoreTypeCreateInfo sem_type_info = {
3321  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3322  .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
3323  .initialValue = 0,
3324  };
3325  VkSemaphoreCreateInfo sem_spawn = {
3326  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3327  .pNext = &sem_type_info,
3328  };
3329 
3330  /* Image creation */
3331  VkSubresourceLayout ext_img_layouts[AV_DRM_MAX_PLANES];
3332  VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = {
3333  .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT,
3334  .drmFormatModifier = desc->objects[0].format_modifier,
3335  .drmFormatModifierPlaneCount = planes,
3336  .pPlaneLayouts = (const VkSubresourceLayout *)&ext_img_layouts,
3337  };
3338  VkExternalMemoryImageCreateInfo ext_img_spec = {
3339  .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
3340  .pNext = &ext_img_mod_spec,
3341  .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3342  };
3343  VkImageCreateInfo create_info = {
3344  .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
3345  .pNext = &ext_img_spec,
3346  .imageType = VK_IMAGE_TYPE_2D,
3347  .format = drm_to_vulkan_fmt(desc->layers[i].format),
3348  .extent.depth = 1,
3349  .mipLevels = 1,
3350  .arrayLayers = 1,
3351  .flags = 0x0,
3352  .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
3353  .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */
3354  .usage = 0x0, /* filled in below */
3355  .samples = VK_SAMPLE_COUNT_1_BIT,
3356  .pQueueFamilyIndices = p->img_qfs,
3357  .queueFamilyIndexCount = p->nb_img_qfs,
3358  .sharingMode = p->nb_img_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
3359  VK_SHARING_MODE_EXCLUSIVE,
3360  };
3361 
3362  /* Image format verification */
3363  VkExternalImageFormatProperties ext_props = {
3364  .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
3365  };
3366  VkImageFormatProperties2 props_ret = {
3367  .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
3368  .pNext = &ext_props,
3369  };
3370  VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = {
3371  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
3372  .drmFormatModifier = ext_img_mod_spec.drmFormatModifier,
3373  .pQueueFamilyIndices = create_info.pQueueFamilyIndices,
3374  .queueFamilyIndexCount = create_info.queueFamilyIndexCount,
3375  .sharingMode = create_info.sharingMode,
3376  };
3377  VkPhysicalDeviceExternalImageFormatInfo props_ext = {
3378  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
3379  .pNext = &props_drm_mod,
3380  .handleType = ext_img_spec.handleTypes,
3381  };
3382  VkPhysicalDeviceImageFormatInfo2 fmt_props;
3383 
3384  if (flags & AV_HWFRAME_MAP_READ)
3385  create_info.usage |= VK_IMAGE_USAGE_SAMPLED_BIT |
3386  VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
3388  create_info.usage |= VK_IMAGE_USAGE_STORAGE_BIT |
3389  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
3390 
3391  fmt_props = (VkPhysicalDeviceImageFormatInfo2) {
3392  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
3393  .pNext = &props_ext,
3394  .format = create_info.format,
3395  .type = create_info.imageType,
3396  .tiling = create_info.tiling,
3397  .usage = create_info.usage,
3398  .flags = create_info.flags,
3399  };
3400 
3401  /* Check if importing is possible for this combination of parameters */
3402  ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev,
3403  &fmt_props, &props_ret);
3404  if (ret != VK_SUCCESS) {
3405  av_log(ctx, AV_LOG_ERROR, "Cannot map DRM frame to Vulkan: %s\n",
3406  ff_vk_ret2str(ret));
3407  err = AVERROR_EXTERNAL;
3408  goto fail;
3409  }
3410 
3411  /* Set the image width/height */
3412  get_plane_wh(&create_info.extent.width, &create_info.extent.height,
3413  hwfc->sw_format, src->width, src->height, i);
3414 
3415  /* Set the subresource layout based on the layer properties */
3416  for (int j = 0; j < planes; j++) {
3417  ext_img_layouts[j].offset = desc->layers[i].planes[j].offset;
3418  ext_img_layouts[j].rowPitch = desc->layers[i].planes[j].pitch;
3419  ext_img_layouts[j].size = 0; /* The specs say so for all 3 */
3420  ext_img_layouts[j].arrayPitch = 0;
3421  ext_img_layouts[j].depthPitch = 0;
3422  }
3423 
3424  /* Create image */
3425  ret = vk->CreateImage(hwctx->act_dev, &create_info,
3426  hwctx->alloc, &f->img[i]);
3427  if (ret != VK_SUCCESS) {
3428  av_log(ctx, AV_LOG_ERROR, "Image creation failure: %s\n",
3429  ff_vk_ret2str(ret));
3430  err = AVERROR(EINVAL);
3431  goto fail;
3432  }
3433 
3434  ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
3435  hwctx->alloc, &f->sem[i]);
3436  if (ret != VK_SUCCESS) {
3437  av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
3438  ff_vk_ret2str(ret));
3439  err = AVERROR_EXTERNAL;
3440  goto fail;
3441  }
3442 
3443  f->queue_family[i] = VK_QUEUE_FAMILY_EXTERNAL;
3444  f->layout[i] = create_info.initialLayout;
3445  f->access[i] = 0x0;
3446  f->sem_value[i] = 0;
3447  }
3448 
3449  for (int i = 0; i < desc->nb_layers; i++) {
3450  /* Memory requirements */
3451  VkImageMemoryRequirementsInfo2 req_desc = {
3452  .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
3453  .image = f->img[i],
3454  };
3455  VkMemoryDedicatedRequirements ded_req = {
3456  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
3457  };
3458  VkMemoryRequirements2 req2 = {
3459  .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
3460  .pNext = &ded_req,
3461  };
3462 
3463  /* Allocation/importing */
3464  VkMemoryFdPropertiesKHR fdmp = {
3465  .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR,
3466  };
3467  /* This assumes that a layer will never be constructed from multiple
3468  * objects. If that was to happen in the real world, this code would
3469  * need to import each plane separately.
3470  */
3471  VkImportMemoryFdInfoKHR idesc = {
3472  .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
3473  .fd = dup(desc->objects[desc->layers[i].planes[0].object_index].fd),
3474  .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3475  };
3476  VkMemoryDedicatedAllocateInfo ded_alloc = {
3477  .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
3478  .pNext = &idesc,
3479  .image = req_desc.image,
3480  };
3481 
3482  /* Get object properties */
3483  ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev,
3484  VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
3485  idesc.fd, &fdmp);
3486  if (ret != VK_SUCCESS) {
3487  av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n",
3488  ff_vk_ret2str(ret));
3489  err = AVERROR_EXTERNAL;
3490  close(idesc.fd);
3491  goto fail;
3492  }
3493 
3494  vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2);
3495 
3496  /* Only a single bit must be set, not a range, and it must match */
3497  req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits;
3498 
3499  err = alloc_mem(ctx, &req2.memoryRequirements,
3500  VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
3501  (ded_req.prefersDedicatedAllocation ||
3502  ded_req.requiresDedicatedAllocation) ?
3503  &ded_alloc : ded_alloc.pNext,
3504  &f->flags, &f->mem[i]);
3505  if (err) {
3506  close(idesc.fd);
3507  return err;
3508  }
3509 
3510  f->size[i] = req2.memoryRequirements.size;
3511  }
3512 
3513  for (int i = 0; i < desc->nb_layers; i++) {
3514  const int planes = desc->layers[i].nb_planes;
3515  for (int j = 0; j < planes; j++) {
3516  VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT :
3517  j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
3518  VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
3519 
3520  plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO;
3521  plane_info[bind_counts].pNext = NULL;
3522  plane_info[bind_counts].planeAspect = aspect;
3523 
3524  bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO;
3525  bind_info[bind_counts].pNext = planes > 1 ? &plane_info[bind_counts] : NULL;
3526  bind_info[bind_counts].image = f->img[i];
3527  bind_info[bind_counts].memory = f->mem[i];
3528 
3529  /* Offset is already signalled via pPlaneLayouts above */
3530  bind_info[bind_counts].memoryOffset = 0;
3531 
3532  bind_counts++;
3533  }
3534  }
3535 
3536  /* Bind the allocated memory to the images */
3537  ret = vk->BindImageMemory2(hwctx->act_dev, bind_counts, bind_info);
3538  if (ret != VK_SUCCESS) {
3539  av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n",
3540  ff_vk_ret2str(ret));
3541  err = AVERROR_EXTERNAL;
3542  goto fail;
3543  }
3544 
3545  *frame = f;
3546 
3547  return 0;
3548 
3549 fail:
3550  vulkan_frame_free(hwfc, f);
3551 
3552  return err;
3553 }
3554 
3555 static int vulkan_map_from_drm_frame_sync(AVHWFramesContext *hwfc, AVFrame *dst,
3556  const AVDRMFrameDescriptor *desc, int flags)
3557 {
3558  int err;
3559  VkResult ret;
3560  AVHWDeviceContext *ctx = hwfc->device_ctx;
3561  VulkanDevicePriv *p = ctx->hwctx;
3562  VulkanFramesPriv *fp = hwfc->hwctx;
3563  AVVulkanDeviceContext *hwctx = &p->p;
3564  FFVulkanFunctions *vk = &p->vkctx.vkfn;
3565 
3566 #ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE
3567  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM) {
3568  VkCommandBuffer cmd_buf;
3569  FFVkExecContext *exec;
3570  VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
3571  VkSemaphore drm_sync_sem[AV_DRM_MAX_PLANES] = { 0 };
3572  int nb_img_bar = 0;
3573 
3574  for (int i = 0; i < desc->nb_objects; i++) {
3575  VkSemaphoreTypeCreateInfo sem_type_info = {
3576  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
3577  .semaphoreType = VK_SEMAPHORE_TYPE_BINARY,
3578  };
3579  VkSemaphoreCreateInfo sem_spawn = {
3580  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
3581  .pNext = &sem_type_info,
3582  };
3583  VkImportSemaphoreFdInfoKHR import_info;
3584  struct dma_buf_export_sync_file implicit_fd_info = {
3585  .flags = DMA_BUF_SYNC_READ,
3586  .fd = -1,
3587  };
3588 
3589  if (ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE,
3590  &implicit_fd_info)) {
3591  err = AVERROR(errno);
3592  av_log(hwctx, AV_LOG_ERROR, "Failed to retrieve implicit DRM sync file: %s\n",
3593  av_err2str(err));
3594  for (; i >= 0; i--)
3595  vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
3596  return err;
3597  }
3598 
3599  ret = vk->CreateSemaphore(hwctx->act_dev, &sem_spawn,
3600  hwctx->alloc, &drm_sync_sem[i]);
3601  if (ret != VK_SUCCESS) {
3602  av_log(hwctx, AV_LOG_ERROR, "Failed to create semaphore: %s\n",
3603  ff_vk_ret2str(ret));
3604  err = AVERROR_EXTERNAL;
3605  for (; i >= 0; i--)
3606  vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
3607  return err;
3608  }
3609 
3610  import_info = (VkImportSemaphoreFdInfoKHR) {
3611  .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
3612  .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
3613  .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
3614  .semaphore = drm_sync_sem[i],
3615  .fd = implicit_fd_info.fd,
3616  };
3617 
3618  ret = vk->ImportSemaphoreFdKHR(hwctx->act_dev, &import_info);
3619  if (ret != VK_SUCCESS) {
3620  av_log(hwctx, AV_LOG_ERROR, "Failed to import semaphore: %s\n",
3621  ff_vk_ret2str(ret));
3622  err = AVERROR_EXTERNAL;
3623  for (; i >= 0; i--)
3624  vk->DestroySemaphore(hwctx->act_dev, drm_sync_sem[i], hwctx->alloc);
3625  return err;
3626  }
3627  }
3628 
3629  exec = ff_vk_exec_get(&p->vkctx, &fp->compute_exec);
3630  cmd_buf = exec->buf;
3631 
3632  ff_vk_exec_start(&p->vkctx, exec);
3633 
3634  /* Ownership of semaphores is passed */
3635  err = ff_vk_exec_add_dep_bool_sem(&p->vkctx, exec,
3636  drm_sync_sem, desc->nb_objects,
3637  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT, 1);
3638  if (err < 0)
3639  return err;
3640 
3641  err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, dst,
3642  VK_PIPELINE_STAGE_2_NONE,
3643  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT);
3644  if (err < 0)
3645  return err;
3646 
3647  ff_vk_frame_barrier(&p->vkctx, exec, dst, img_bar, &nb_img_bar,
3648  VK_PIPELINE_STAGE_2_NONE,
3649  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
3650  ((flags & AV_HWFRAME_MAP_READ) ?
3651  VK_ACCESS_2_SHADER_SAMPLED_READ_BIT : 0x0) |
3653  VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT : 0x0),
3654  VK_IMAGE_LAYOUT_GENERAL,
3655  p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
3656 
3657  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
3658  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
3659  .pImageMemoryBarriers = img_bar,
3660  .imageMemoryBarrierCount = nb_img_bar,
3661  });
3662 
3663  err = ff_vk_exec_submit(&p->vkctx, exec);
3664  if (err < 0)
3665  return err;
3666  } else
3667 #endif
3668  {
3669  AVVkFrame *f = (AVVkFrame *)dst->data[0];
3670  av_log(hwctx, AV_LOG_WARNING, "No support for synchronization when importing DMA-BUFs, "
3671  "image may be corrupted.\n");
3673  if (err)
3674  return err;
3675  }
3676 
3677  return 0;
3678 }
3679 
3680 static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst,
3681  const AVFrame *src, int flags)
3682 {
3683  int err = 0;
3684  AVVkFrame *f;
3685  const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0];
3686 
3687  if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src, flags)))
3688  return err;
3689 
3690  /* The unmapping function will free this */
3691  dst->data[0] = (uint8_t *)f;
3692  dst->width = src->width;
3693  dst->height = src->height;
3694 
3695  err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
3696  &vulkan_unmap_from_drm, f);
3697  if (err < 0)
3698  goto fail;
3699 
3700  err = vulkan_map_from_drm_frame_sync(hwfc, dst, desc, flags);
3701  if (err < 0)
3702  return err;
3703 
3704  av_log(hwfc, AV_LOG_DEBUG, "Mapped DRM object to Vulkan!\n");
3705 
3706  return 0;
3707 
3708 fail:
3710  dst->data[0] = NULL;
3711  return err;
3712 }
3713 
3714 #if CONFIG_VAAPI
3715 static int vulkan_map_from_vaapi(AVHWFramesContext *dst_fc,
3716  AVFrame *dst, const AVFrame *src,
3717  int flags)
3718 {
3719  int err;
3720  AVFrame *tmp = av_frame_alloc();
3721  AVHWFramesContext *vaapi_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
3722  AVVAAPIDeviceContext *vaapi_ctx = vaapi_fc->device_ctx->hwctx;
3723  VASurfaceID surface_id = (VASurfaceID)(uintptr_t)src->data[3];
3724 
3725  if (!tmp)
3726  return AVERROR(ENOMEM);
3727 
3728  /* We have to sync since like the previous comment said, no semaphores */
3729  vaSyncSurface(vaapi_ctx->display, surface_id);
3730 
3731  tmp->format = AV_PIX_FMT_DRM_PRIME;
3732 
3733  err = av_hwframe_map(tmp, src, flags);
3734  if (err < 0)
3735  goto fail;
3736 
3737  err = vulkan_map_from_drm(dst_fc, dst, tmp, flags);
3738  if (err < 0)
3739  goto fail;
3740 
3741  err = ff_hwframe_map_replace(dst, src);
3742 
3743 fail:
3744  av_frame_free(&tmp);
3745  return err;
3746 }
3747 #endif
3748 #endif
3749 
3750 #if CONFIG_CUDA
3751 static int export_mem_to_cuda(AVHWDeviceContext *ctx,
3752  AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
3753  AVVkFrameInternal *dst_int, int idx,
3754  VkDeviceMemory mem, size_t size)
3755 {
3756  VkResult ret;
3757  VulkanDevicePriv *p = ctx->hwctx;
3758  AVVulkanDeviceContext *hwctx = &p->p;
3759  FFVulkanFunctions *vk = &p->vkctx.vkfn;
3760 
3761 #ifdef _WIN32
3762  CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
3763  .type = IsWindows8OrGreater()
3764  ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32
3765  : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT,
3766  .size = size,
3767  };
3768  VkMemoryGetWin32HandleInfoKHR export_info = {
3769  .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR,
3770  .memory = mem,
3771  .handleType = IsWindows8OrGreater()
3772  ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT
3773  : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
3774  };
3775 
3776  ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info,
3777  &ext_desc.handle.win32.handle);
3778  if (ret != VK_SUCCESS) {
3779  av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n",
3780  ff_vk_ret2str(ret));
3781  return AVERROR_EXTERNAL;
3782  }
3783  dst_int->ext_mem_handle[idx] = ext_desc.handle.win32.handle;
3784 #else
3785  CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
3786  .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
3787  .size = size,
3788  };
3789  VkMemoryGetFdInfoKHR export_info = {
3790  .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
3791  .memory = mem,
3792  .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR,
3793  };
3794 
3795  ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
3796  &ext_desc.handle.fd);
3797  if (ret != VK_SUCCESS) {
3798  av_log(ctx, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n",
3799  ff_vk_ret2str(ret));
3800  return AVERROR_EXTERNAL;
3801  }
3802 #endif
3803 
3804  ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[idx], &ext_desc));
3805  if (ret < 0) {
3806 #ifndef _WIN32
3807  close(ext_desc.handle.fd);
3808 #endif
3809  return AVERROR_EXTERNAL;
3810  }
3811 
3812  return 0;
3813 }
3814 
3815 static int export_sem_to_cuda(AVHWDeviceContext *ctx,
3816  AVHWDeviceContext *cuda_cu, CudaFunctions *cu,
3817  AVVkFrameInternal *dst_int, int idx,
3818  VkSemaphore sem)
3819 {
3820  VkResult ret;
3821  VulkanDevicePriv *p = ctx->hwctx;
3822  AVVulkanDeviceContext *hwctx = &p->p;
3823  FFVulkanFunctions *vk = &p->vkctx.vkfn;
3824 
3825 #ifdef _WIN32
3826  VkSemaphoreGetWin32HandleInfoKHR sem_export = {
3827  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR,
3828  .semaphore = sem,
3829  .handleType = IsWindows8OrGreater()
3830  ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT
3831  : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT,
3832  };
3833  CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
3834  .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */,
3835  };
3836 #else
3837  VkSemaphoreGetFdInfoKHR sem_export = {
3838  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
3839  .semaphore = sem,
3840  .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
3841  };
3842  CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = {
3843  .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */,
3844  };
3845 #endif
3846 
3847 #ifdef _WIN32
3848  ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export,
3849  &ext_sem_desc.handle.win32.handle);
3850 #else
3851  ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export,
3852  &ext_sem_desc.handle.fd);
3853 #endif
3854  if (ret != VK_SUCCESS) {
3855  av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n",
3856  ff_vk_ret2str(ret));
3857  return AVERROR_EXTERNAL;
3858  }
3859 #ifdef _WIN32
3860  dst_int->ext_sem_handle[idx] = ext_sem_desc.handle.win32.handle;
3861 #endif
3862 
3863  ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[idx],
3864  &ext_sem_desc));
3865  if (ret < 0) {
3866 #ifndef _WIN32
3867  close(ext_sem_desc.handle.fd);
3868 #endif
3869  return AVERROR_EXTERNAL;
3870  }
3871 
3872  return 0;
3873 }
3874 
3875 static int vulkan_export_to_cuda(AVHWFramesContext *hwfc,
3876  AVBufferRef *cuda_hwfc,
3877  const AVFrame *frame)
3878 {
3879  int err;
3880  VkResult ret;
3881  AVVkFrame *dst_f;
3882  AVVkFrameInternal *dst_int;
3883  AVHWDeviceContext *ctx = hwfc->device_ctx;
3884  const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
3886  VulkanDevicePriv *p = ctx->hwctx;
3887  AVVulkanDeviceContext *hwctx = &p->p;
3888  FFVulkanFunctions *vk = &p->vkctx.vkfn;
3889  int nb_images;
3890 
3891  AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data;
3892  AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
3893  AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
3894  AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
3895  CudaFunctions *cu = cu_internal->cuda_dl;
3896  CUarray_format cufmt = desc->comp[0].depth > 8 ? CU_AD_FORMAT_UNSIGNED_INT16 :
3897  CU_AD_FORMAT_UNSIGNED_INT8;
3898 
3899  dst_f = (AVVkFrame *)frame->data[0];
3900  dst_int = dst_f->internal;
3901 
3902  if (!dst_int->cuda_fc_ref) {
3903  size_t offsets[3] = { 0 };
3904 
3905  dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc);
3906  if (!dst_int->cuda_fc_ref)
3907  return AVERROR(ENOMEM);
3908 
3909  nb_images = ff_vk_count_images(dst_f);
3910  for (int i = 0; i < nb_images; i++) {
3911  err = export_mem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
3912  dst_f->mem[i], dst_f->size[i]);
3913  if (err < 0)
3914  goto fail;
3915 
3916  err = export_sem_to_cuda(ctx, cuda_cu, cu, dst_int, i,
3917  dst_f->sem[i]);
3918  if (err < 0)
3919  goto fail;
3920  }
3921 
3922  if (nb_images != planes) {
3923  for (int i = 0; i < planes; i++) {
3924  VkImageSubresource subres = {
3925  .aspectMask = i == 2 ? VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT :
3926  i == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT :
3927  VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT
3928  };
3929  VkSubresourceLayout layout = { 0 };
3930  vk->GetImageSubresourceLayout(hwctx->act_dev, dst_f->img[FFMIN(i, nb_images - 1)],
3931  &subres, &layout);
3932  offsets[i] = layout.offset;
3933  }
3934  }
3935 
3936  for (int i = 0; i < planes; i++) {
3937  CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
3938  .offset = offsets[i],
3939  .arrayDesc = {
3940  .Depth = 0,
3941  .Format = cufmt,
3942  .NumChannels = 1 + ((planes == 2) && i),
3943  .Flags = 0,
3944  },
3945  .numLevels = 1,
3946  };
3947  int p_w, p_h;
3948 
3949  get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
3950  tex_desc.arrayDesc.Width = p_w;
3951  tex_desc.arrayDesc.Height = p_h;
3952 
3953  ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i],
3954  dst_int->ext_mem[FFMIN(i, nb_images - 1)],
3955  &tex_desc));
3956  if (ret < 0) {
3957  err = AVERROR_EXTERNAL;
3958  goto fail;
3959  }
3960 
3961  ret = CHECK_CU(cu->cuMipmappedArrayGetLevel(&dst_int->cu_array[i],
3962  dst_int->cu_mma[i], 0));
3963  if (ret < 0) {
3964  err = AVERROR_EXTERNAL;
3965  goto fail;
3966  }
3967 
3968  }
3969  }
3970 
3971  return 0;
3972 
3973 fail:
3974  vulkan_free_internal(dst_f);
3975  return err;
3976 }
3977 
3978 static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc,
3979  AVFrame *dst, const AVFrame *src)
3980 {
3981  int err;
3982  CUcontext dummy;
3983  AVVkFrame *dst_f;
3984  AVVkFrameInternal *dst_int;
3985  VulkanFramesPriv *fp = hwfc->hwctx;
3986  const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
3988 
3989  AVHWFramesContext *cuda_fc = (AVHWFramesContext*)src->hw_frames_ctx->data;
3990  AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
3991  AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
3992  AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
3993  CudaFunctions *cu = cu_internal->cuda_dl;
3994  CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
3995  CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
3996 
3997  dst_f = (AVVkFrame *)dst->data[0];
3998 
3999  err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
4000  if (err < 0)
4001  return err;
4002 
4003  err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
4004  if (err < 0)
4005  return err;
4006 
4007  err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst);
4008  if (err < 0) {
4009  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4010  return err;
4011  }
4012 
4013  dst_int = dst_f->internal;
4014 
4015  for (int i = 0; i < planes; i++) {
4016  s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
4017  s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
4018  }
4019 
4020  err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
4021  planes, cuda_dev->stream));
4022  if (err < 0)
4023  goto fail;
4024 
4025  for (int i = 0; i < planes; i++) {
4026  CUDA_MEMCPY2D cpy = {
4027  .srcMemoryType = CU_MEMORYTYPE_DEVICE,
4028  .srcDevice = (CUdeviceptr)src->data[i],
4029  .srcPitch = src->linesize[i],
4030  .srcY = 0,
4031 
4032  .dstMemoryType = CU_MEMORYTYPE_ARRAY,
4033  .dstArray = dst_int->cu_array[i],
4034  };
4035 
4036  int p_w, p_h;
4037  get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i);
4038 
4039  cpy.WidthInBytes = p_w * desc->comp[i].step;
4040  cpy.Height = p_h;
4041 
4042  err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
4043  if (err < 0)
4044  goto fail;
4045  }
4046 
4047  err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
4048  planes, cuda_dev->stream));
4049  if (err < 0)
4050  goto fail;
4051 
4052  for (int i = 0; i < planes; i++)
4053  dst_f->sem_value[i]++;
4054 
4055  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4056 
4057  av_log(hwfc, AV_LOG_VERBOSE, "Transferred CUDA image to Vulkan!\n");
4058 
4059  return err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
4060 
4061 fail:
4062  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4063  vulkan_free_internal(dst_f);
4064  av_buffer_unref(&dst->buf[0]);
4065  return err;
4066 }
4067 #endif
4068 
4070  const AVFrame *src, int flags)
4071 {
4073 
4074  switch (src->format) {
4075 #if CONFIG_LIBDRM
4076 #if CONFIG_VAAPI
4077  case AV_PIX_FMT_VAAPI:
4078  if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
4079  return vulkan_map_from_vaapi(hwfc, dst, src, flags);
4080  else
4081  return AVERROR(ENOSYS);
4082 #endif
4083  case AV_PIX_FMT_DRM_PRIME:
4084  if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
4085  return vulkan_map_from_drm(hwfc, dst, src, flags);
4086  else
4087  return AVERROR(ENOSYS);
4088 #endif
4089  default:
4090  return AVERROR(ENOSYS);
4091  }
4092 }
4093 
4094 #if CONFIG_LIBDRM
4095 typedef struct VulkanDRMMapping {
4096  AVDRMFrameDescriptor drm_desc;
4097  AVVkFrame *source;
4098 } VulkanDRMMapping;
4099 
4100 static void vulkan_unmap_to_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
4101 {
4102  AVDRMFrameDescriptor *drm_desc = hwmap->priv;
4103 
4104  /* on unmap from DRM, make sure to import sync objects so that we are sync'd with any work that was
4105  * done on the buffer while exported. We don't know if who used the dmabuf did reads or writes, so protect against both */
4106  vulkan_map_from_drm_frame_sync(hwfc, hwmap->source, drm_desc, AV_HWFRAME_MAP_READ | AV_HWFRAME_MAP_WRITE);
4107 
4108  for (int i = 0; i < drm_desc->nb_objects; i++)
4109  close(drm_desc->objects[i].fd);
4110 
4111  av_free(drm_desc);
4112 }
4113 
4114 static inline uint32_t vulkan_fmt_to_drm(VkFormat vkfmt)
4115 {
4116  for (int i = 0; i < FF_ARRAY_ELEMS(vulkan_drm_format_map); i++)
4117  if (vulkan_drm_format_map[i].vk_format == vkfmt)
4118  return vulkan_drm_format_map[i].drm_fourcc;
4119  return DRM_FORMAT_INVALID;
4120 }
4121 
4122 #define MAX_MEMORY_PLANES 4
4123 static VkImageAspectFlags plane_index_to_aspect(int plane) {
4124  if (plane == 0) return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4125  if (plane == 1) return VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT;
4126  if (plane == 2) return VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT;
4127  if (plane == 3) return VK_IMAGE_ASPECT_MEMORY_PLANE_3_BIT_EXT;
4128 
4129  av_assert2 (0 && "Invalid plane index");
4130  return VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT;
4131 }
4132 
4133 static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
4134  const AVFrame *src, int flags)
4135 {
4136  int err = 0;
4137  VkResult ret;
4138  AVVkFrame *f = (AVVkFrame *)src->data[0];
4139  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4140  AVVulkanDeviceContext *hwctx = &p->p;
4141  FFVulkanFunctions *vk = &p->vkctx.vkfn;
4142  VulkanFramesPriv *fp = hwfc->hwctx;
4143  const int nb_images = ff_vk_count_images(f);
4144  VkImageDrmFormatModifierPropertiesEXT drm_mod = {
4145  .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
4146  };
4147  VkSemaphoreWaitInfo wait_info = {
4148  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4149  .flags = 0x0,
4150  .semaphoreCount = nb_images,
4151  };
4152 
4153  AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc));
4154  if (!drm_desc)
4155  return AVERROR(ENOMEM);
4156 
4158  if (err < 0)
4159  goto end;
4160 
4161  /* Wait for the operation to finish so we can cleanly export it. */
4162  wait_info.pSemaphores = f->sem;
4163  wait_info.pValues = f->sem_value;
4164 
4165  vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX);
4166 
4167  err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc);
4168  if (err < 0)
4169  goto end;
4170 
4171  ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0],
4172  &drm_mod);
4173  if (ret != VK_SUCCESS) {
4174  av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n");
4175  err = AVERROR_EXTERNAL;
4176  goto end;
4177  }
4178 
4179  for (int i = 0; (i < nb_images) && (f->mem[i]); i++) {
4180  VkMemoryGetFdInfoKHR export_info = {
4181  .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
4182  .memory = f->mem[i],
4183  .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
4184  };
4185 
4186  ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info,
4187  &drm_desc->objects[i].fd);
4188  if (ret != VK_SUCCESS) {
4189  av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n");
4190  err = AVERROR_EXTERNAL;
4191  goto end;
4192  }
4193 
4194  drm_desc->nb_objects++;
4195  drm_desc->objects[i].size = f->size[i];
4196  drm_desc->objects[i].format_modifier = drm_mod.drmFormatModifier;
4197  }
4198 
4199  drm_desc->nb_layers = nb_images;
4200  for (int i = 0; i < drm_desc->nb_layers; i++) {
4201  VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i];
4202 
4203  drm_desc->layers[i].format = vulkan_fmt_to_drm(plane_vkfmt);
4204  drm_desc->layers[i].nb_planes = fp->drm_format_modifier_properties[i].drmFormatModifierPlaneCount;
4205 
4206  if (drm_desc->layers[i].nb_planes > MAX_MEMORY_PLANES) {
4207  av_log(hwfc, AV_LOG_ERROR, "Too many memory planes for DRM format!\n");
4208  err = AVERROR_EXTERNAL;
4209  goto end;
4210  }
4211 
4212  for (int j = 0; j < drm_desc->layers[i].nb_planes; j++) {
4213  VkSubresourceLayout layout;
4214  VkImageSubresource sub = {
4215  .aspectMask = plane_index_to_aspect(j),
4216  };
4217 
4218  drm_desc->layers[i].planes[j].object_index = FFMIN(i, drm_desc->nb_objects - 1);
4219 
4220  vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout);
4221  drm_desc->layers[i].planes[j].offset = layout.offset;
4222  drm_desc->layers[i].planes[j].pitch = layout.rowPitch;
4223  }
4224 
4225  if (drm_desc->layers[i].format == DRM_FORMAT_INVALID) {
4226  av_log(hwfc, AV_LOG_ERROR, "Cannot map to DRM layer, unsupported!\n");
4227  err = AVERROR_PATCHWELCOME;
4228  goto end;
4229  }
4230 
4231 
4232  if (f->tiling == VK_IMAGE_TILING_OPTIMAL)
4233  continue;
4234 
4235  }
4236 
4237  dst->width = src->width;
4238  dst->height = src->height;
4239  dst->data[0] = (uint8_t *)drm_desc;
4240 
4241  av_log(hwfc, AV_LOG_VERBOSE, "Mapped AVVkFrame to a DRM object!\n");
4242 
4243  return 0;
4244 
4245 end:
4246  av_free(drm_desc);
4247  return err;
4248 }
4249 
4250 #if CONFIG_VAAPI
4251 static int vulkan_map_to_vaapi(AVHWFramesContext *hwfc, AVFrame *dst,
4252  const AVFrame *src, int flags)
4253 {
4254  int err;
4255  AVFrame *tmp = av_frame_alloc();
4256  if (!tmp)
4257  return AVERROR(ENOMEM);
4258 
4259  tmp->format = AV_PIX_FMT_DRM_PRIME;
4260 
4261  err = vulkan_map_to_drm(hwfc, tmp, src, flags);
4262  if (err < 0)
4263  goto fail;
4264 
4265  err = av_hwframe_map(dst, tmp, flags);
4266  if (err < 0)
4267  goto fail;
4268 
4269  err = ff_hwframe_map_replace(dst, src);
4270 
4271 fail:
4272  av_frame_free(&tmp);
4273  return err;
4274 }
4275 #endif
4276 #endif
4277 
4279  const AVFrame *src, int flags)
4280 {
4282 
4283  switch (dst->format) {
4284 #if CONFIG_LIBDRM
4285  case AV_PIX_FMT_DRM_PRIME:
4286  if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
4287  return vulkan_map_to_drm(hwfc, dst, src, flags);
4288  else
4289  return AVERROR(ENOSYS);
4290 #if CONFIG_VAAPI
4291  case AV_PIX_FMT_VAAPI:
4292  if (p->vkctx.extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS)
4293  return vulkan_map_to_vaapi(hwfc, dst, src, flags);
4294  else
4295  return AVERROR(ENOSYS);
4296 #endif
4297 #endif
4298  default:
4299  break;
4300  }
4301  return AVERROR(ENOSYS);
4302 }
4303 
4305  AVFrame *swf, VkBufferImageCopy *region,
4306  int planes, int upload)
4307 {
4308  int err;
4309  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4310  FFVkBuffer *vkbuf = (FFVkBuffer *)buf->data;
4311 
4312  if (upload) {
4313  for (int i = 0; i < planes; i++)
4314  av_image_copy_plane(vkbuf->mapped_mem + region[i].bufferOffset,
4315  region[i].bufferRowLength,
4316  swf->data[i],
4317  swf->linesize[i],
4318  swf->linesize[i],
4319  region[i].imageExtent.height);
4320 
4321  err = ff_vk_flush_buffer(&p->vkctx, vkbuf, 0, VK_WHOLE_SIZE, 1);
4322  if (err != VK_SUCCESS) {
4323  av_log(hwfc, AV_LOG_ERROR, "Failed to flush buffer data: %s\n",
4324  av_err2str(err));
4325  return AVERROR_EXTERNAL;
4326  }
4327  } else {
4328  err = ff_vk_flush_buffer(&p->vkctx, vkbuf, 0, VK_WHOLE_SIZE, 0);
4329  if (err != VK_SUCCESS) {
4330  av_log(hwfc, AV_LOG_ERROR, "Failed to invalidate buffer data: %s\n",
4331  av_err2str(err));
4332  return AVERROR_EXTERNAL;
4333  }
4334 
4335  for (int i = 0; i < planes; i++)
4336  av_image_copy_plane(swf->data[i],
4337  swf->linesize[i],
4338  vkbuf->mapped_mem + region[i].bufferOffset,
4339  region[i].bufferRowLength,
4340  swf->linesize[i],
4341  region[i].imageExtent.height);
4342  }
4343 
4344  return 0;
4345 }
4346 
4348  AVFrame *swf, VkBufferImageCopy *region, int upload)
4349 {
4350  int err;
4351  uint32_t p_w, p_h;
4352  VulkanFramesPriv *fp = hwfc->hwctx;
4353  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4354  const int planes = av_pix_fmt_count_planes(swf->format);
4355  VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4356  VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4357 
4358  size_t buf_offset = 0;
4359  for (int i = 0; i < planes; i++) {
4360  get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4361 
4362  region[i] = (VkBufferImageCopy) {
4363  .bufferOffset = buf_offset,
4364  .bufferRowLength = FFALIGN(swf->linesize[i],
4365  p->props.properties.limits.optimalBufferCopyRowPitchAlignment),
4366  .bufferImageHeight = p_h,
4367  .imageSubresource.layerCount = 1,
4368  .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4369  /* Rest of the fields adjusted/filled in later */
4370  };
4371 
4372  buf_offset += FFALIGN(p_h*region[i].bufferRowLength,
4373  p->props.properties.limits.optimalBufferCopyOffsetAlignment);
4374  }
4375 
4376  err = ff_vk_get_pooled_buffer(&p->vkctx, &fp->tmp, dst, buf_usage,
4377  NULL, buf_offset,
4378  VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
4379  p->vkctx.host_cached_flag);
4380  if (err < 0)
4381  return err;
4382 
4383  return 0;
4384 }
4385 
4386 static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs,
4387  AVFrame *swf, VkBufferImageCopy *region, int upload)
4388 {
4389  int err;
4390  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4391 
4392  int nb_src_bufs;
4393  const int planes = av_pix_fmt_count_planes(swf->format);
4394  VkBufferUsageFlags buf_usage = upload ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT :
4395  VK_BUFFER_USAGE_TRANSFER_DST_BIT;
4396 
4397  /* We can't host map images with negative strides */
4398  for (int i = 0; i < planes; i++)
4399  if (swf->linesize[i] < 0)
4400  return AVERROR(EINVAL);
4401 
4402  /* Count the number of buffers in the software frame */
4403  nb_src_bufs = 0;
4404  while (swf->buf[nb_src_bufs])
4405  nb_src_bufs++;
4406 
4407  /* Single buffer contains all planes */
4408  if (nb_src_bufs == 1) {
4409  err = ff_vk_host_map_buffer(&p->vkctx, &dst[0],
4410  swf->data[0], swf->buf[0],
4411  buf_usage);
4412  if (err < 0)
4413  return err;
4414  (*nb_bufs)++;
4415 
4416  for (int i = 0; i < planes; i++)
4417  region[i].bufferOffset = ((FFVkBuffer *)dst[0]->data)->virtual_offset +
4418  swf->data[i] - swf->data[0];
4419  } else if (nb_src_bufs == planes) { /* One buffer per plane */
4420  for (int i = 0; i < planes; i++) {
4421  err = ff_vk_host_map_buffer(&p->vkctx, &dst[i],
4422  swf->data[i], swf->buf[i],
4423  buf_usage);
4424  if (err < 0)
4425  goto fail;
4426  (*nb_bufs)++;
4427 
4428  region[i].bufferOffset = ((FFVkBuffer *)dst[i]->data)->virtual_offset;
4429  }
4430  } else {
4431  /* Weird layout (3 planes, 2 buffers), patch welcome, fallback to copy */
4432  return AVERROR_PATCHWELCOME;
4433  }
4434 
4435  return 0;
4436 
4437 fail:
4438  for (int i = 0; i < (*nb_bufs); i++)
4439  av_buffer_unref(&dst[i]);
4440  return err;
4441 }
4442 
4444  AVFrame *swf, int upload)
4445 {
4446  VulkanFramesPriv *fp = hwfc->hwctx;
4447  AVVulkanFramesContext *hwfc_vk = &fp->p;
4448  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4449  AVVulkanDeviceContext *hwctx = &p->p;
4450  FFVulkanFunctions *vk = &p->vkctx.vkfn;
4451 
4452  AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0];
4454  const int planes = av_pix_fmt_count_planes(swf->format);
4455  const int nb_images = ff_vk_count_images(hwf_vk);
4456 
4457  VkSemaphoreWaitInfo sem_wait;
4458  VkHostImageLayoutTransitionInfoEXT layout_ch_info[AV_NUM_DATA_POINTERS];
4459  int nb_layout_ch = 0;
4460 
4461  hwfc_vk->lock_frame(hwfc, hwf_vk);
4462 
4463  for (int i = 0; i < nb_images; i++) {
4464  int compat = 0;
4465  for (int j = 0; j < p->vkctx.host_image_props.copySrcLayoutCount; j++) {
4466  if (hwf_vk->layout[i] == p->vkctx.host_image_props.pCopySrcLayouts[j]) {
4467  compat = 1;
4468  break;
4469  }
4470  }
4471  if (compat)
4472  continue;
4473 
4474  layout_ch_info[nb_layout_ch] = (VkHostImageLayoutTransitionInfoEXT) {
4475  .sType = VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
4476  .image = hwf_vk->img[i],
4477  .oldLayout = hwf_vk->layout[i],
4478  .newLayout = VK_IMAGE_LAYOUT_GENERAL,
4479  .subresourceRange = {
4480  .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
4481  .levelCount = 1,
4482  .layerCount = 1,
4483  },
4484  };
4485 
4486  hwf_vk->layout[i] = layout_ch_info[nb_layout_ch].newLayout;
4487  nb_layout_ch++;
4488  }
4489 
4490  sem_wait = (VkSemaphoreWaitInfo) {
4491  .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
4492  .pSemaphores = hwf_vk->sem,
4493  .pValues = hwf_vk->sem_value,
4494  .semaphoreCount = nb_images,
4495  };
4496 
4497  vk->WaitSemaphores(hwctx->act_dev, &sem_wait, UINT64_MAX);
4498 
4499  if (nb_layout_ch)
4500  vk->TransitionImageLayoutEXT(hwctx->act_dev,
4501  nb_layout_ch, layout_ch_info);
4502 
4503  if (upload) {
4504  VkMemoryToImageCopyEXT region_info = {
4505  .sType = VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
4506  .imageSubresource = {
4507  .layerCount = 1,
4508  },
4509  };
4510  VkCopyMemoryToImageInfoEXT copy_info = {
4511  .sType = VK_STRUCTURE_TYPE_COPY_MEMORY_TO_IMAGE_INFO_EXT,
4512  .regionCount = 1,
4513  .pRegions = &region_info,
4514  };
4515  for (int i = 0; i < planes; i++) {
4516  int img_idx = FFMIN(i, (nb_images - 1));
4517  uint32_t p_w, p_h;
4518  get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4519 
4520  region_info.pHostPointer = swf->data[i];
4521  region_info.memoryRowLength = swf->linesize[i] / desc->comp[i].step;
4522  region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
4523  region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4524  copy_info.dstImage = hwf_vk->img[img_idx];
4525  copy_info.dstImageLayout = hwf_vk->layout[img_idx];
4526 
4527  vk->CopyMemoryToImageEXT(hwctx->act_dev, &copy_info);
4528  }
4529  } else {
4530  VkImageToMemoryCopyEXT region_info = {
4531  .sType = VK_STRUCTURE_TYPE_IMAGE_TO_MEMORY_COPY_EXT,
4532  .imageSubresource = {
4533  .layerCount = 1,
4534  },
4535  };
4536  VkCopyImageToMemoryInfoEXT copy_info = {
4537  .sType = VK_STRUCTURE_TYPE_COPY_IMAGE_TO_MEMORY_INFO_EXT,
4538  .regionCount = 1,
4539  .pRegions = &region_info,
4540  };
4541  for (int i = 0; i < planes; i++) {
4542  int img_idx = FFMIN(i, (nb_images - 1));
4543  uint32_t p_w, p_h;
4544  get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4545 
4546  region_info.pHostPointer = swf->data[i];
4547  region_info.memoryRowLength = swf->linesize[i] / desc->comp[i].step;
4548  region_info.imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
4549  region_info.imageExtent = (VkExtent3D){ p_w, p_h, 1 };
4550  copy_info.srcImage = hwf_vk->img[img_idx];
4551  copy_info.srcImageLayout = hwf_vk->layout[img_idx];
4552 
4553  vk->CopyImageToMemoryEXT(hwctx->act_dev, &copy_info);
4554  }
4555  }
4556 
4557  hwfc_vk->unlock_frame(hwfc, hwf_vk);
4558 
4559  return 0;
4560 }
4561 
4563  AVFrame *swf, AVFrame *hwf,
4564  int upload)
4565 {
4566  int err;
4567  VulkanFramesPriv *fp = hwfc->hwctx;
4568  AVVulkanFramesContext *hwctx = &fp->p;
4569  VulkanDevicePriv *p = hwfc->device_ctx->hwctx;
4570  FFVulkanFunctions *vk = &p->vkctx.vkfn;
4571 
4572  int host_mapped = 0;
4573 
4574  AVVkFrame *hwf_vk = (AVVkFrame *)hwf->data[0];
4575  VkBufferImageCopy region[AV_NUM_DATA_POINTERS]; // always one per plane
4576 
4577  const int planes = av_pix_fmt_count_planes(swf->format);
4579  const int nb_images = ff_vk_count_images(hwf_vk);
4580 
4581  VkImageMemoryBarrier2 img_bar[AV_NUM_DATA_POINTERS];
4582  int nb_img_bar = 0;
4583 
4585  int nb_bufs = 0;
4586 
4587  VkCommandBuffer cmd_buf;
4588  FFVkExecContext *exec;
4589 
4590  /* Sanity checking */
4591  if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) {
4592  av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n");
4593  return AVERROR(EINVAL);
4594  }
4595 
4596  if (swf->width > hwfc->width || swf->height > hwfc->height)
4597  return AVERROR(EINVAL);
4598 
4599  if (hwctx->usage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT &&
4600  !(p->dprops.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY))
4601  return vulkan_transfer_host(hwfc, hwf, swf, upload);
4602 
4603  for (int i = 0; i < av_pix_fmt_count_planes(swf->format); i++) {
4604  uint32_t p_w, p_h;
4605  get_plane_wh(&p_w, &p_h, swf->format, swf->width, swf->height, i);
4606 
4607  /* Buffer region for this plane */
4608  region[i] = (VkBufferImageCopy) {
4609  .bufferOffset = 0,
4610  .bufferRowLength = swf->linesize[i],
4611  .bufferImageHeight = p_h,
4612  .imageSubresource.layerCount = 1,
4613  .imageExtent = (VkExtent3D){ p_w, p_h, 1 },
4614  /* Rest of the fields adjusted/filled in later */
4615  };
4616  }
4617 
4618  /* Setup buffers first */
4619  if (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY && !p->avoid_host_import) {
4620  err = host_map_frame(hwfc, bufs, &nb_bufs, swf, region, upload);
4621  if (err >= 0)
4622  host_mapped = 1;
4623  }
4624 
4625  if (!host_mapped) {
4626  err = get_plane_buf(hwfc, &bufs[0], swf, region, upload);
4627  if (err < 0)
4628  goto end;
4629  nb_bufs = 1;
4630 
4631  if (upload) {
4632  err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 1);
4633  if (err < 0)
4634  goto end;
4635  }
4636  }
4637 
4638  exec = ff_vk_exec_get(&p->vkctx, &fp->upload_exec);
4639  cmd_buf = exec->buf;
4640 
4641  ff_vk_exec_start(&p->vkctx, exec);
4642 
4643  /* Prep destination Vulkan frame */
4644  err = ff_vk_exec_add_dep_frame(&p->vkctx, exec, hwf,
4645  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
4646  VK_PIPELINE_STAGE_2_TRANSFER_BIT);
4647  if (err < 0)
4648  goto end;
4649 
4650  /* No need to declare buf deps for synchronous transfers (downloads) */
4651  if (upload) {
4652  /* Add the software frame backing the buffers if we're host mapping */
4653  if (host_mapped) {
4654  err = ff_vk_exec_add_dep_sw_frame(&p->vkctx, exec, swf);
4655  if (err < 0) {
4656  ff_vk_exec_discard_deps(&p->vkctx, exec);
4657  goto end;
4658  }
4659  }
4660 
4661  /* Add the buffers as a dependency */
4662  err = ff_vk_exec_add_dep_buf(&p->vkctx, exec, bufs, nb_bufs, 1);
4663  if (err < 0) {
4664  ff_vk_exec_discard_deps(&p->vkctx, exec);
4665  goto end;
4666  }
4667  }
4668 
4669  ff_vk_frame_barrier(&p->vkctx, exec, hwf, img_bar, &nb_img_bar,
4670  VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
4671  VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR,
4672  upload ? VK_ACCESS_TRANSFER_WRITE_BIT :
4673  VK_ACCESS_TRANSFER_READ_BIT,
4674  upload ? VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL :
4675  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
4676  p->nb_img_qfs > 1 ? VK_QUEUE_FAMILY_IGNORED : p->img_qfs[0]);
4677 
4678  vk->CmdPipelineBarrier2(cmd_buf, &(VkDependencyInfo) {
4679  .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
4680  .pImageMemoryBarriers = img_bar,
4681  .imageMemoryBarrierCount = nb_img_bar,
4682  });
4683 
4684  for (int i = 0; i < planes; i++) {
4685  int buf_idx = FFMIN(i, (nb_bufs - 1));
4686  int img_idx = FFMIN(i, (nb_images - 1));
4687  FFVkBuffer *vkbuf = (FFVkBuffer *)bufs[buf_idx]->data;
4688 
4689  uint32_t orig_stride = region[i].bufferRowLength;
4690  region[i].bufferRowLength /= desc->comp[i].step;
4691  region[i].imageSubresource.aspectMask = ff_vk_aspect_flag(hwf, i);
4692 
4693  if (upload)
4694  vk->CmdCopyBufferToImage(cmd_buf, vkbuf->buf,
4695  hwf_vk->img[img_idx],
4696  img_bar[img_idx].newLayout,
4697  1, &region[i]);
4698  else
4699  vk->CmdCopyImageToBuffer(cmd_buf, hwf_vk->img[img_idx],
4700  img_bar[img_idx].newLayout,
4701  vkbuf->buf,
4702  1, &region[i]);
4703 
4704  region[i].bufferRowLength = orig_stride;
4705  }
4706 
4707  err = ff_vk_exec_submit(&p->vkctx, exec);
4708  if (err < 0) {
4709  ff_vk_exec_discard_deps(&p->vkctx, exec);
4710  } else if (!upload) {
4711  ff_vk_exec_wait(&p->vkctx, exec);
4712  if (!host_mapped)
4713  err = copy_buffer_data(hwfc, bufs[0], swf, region, planes, 0);
4714  }
4715 
4716 end:
4717  for (int i = 0; i < nb_bufs; i++)
4718  av_buffer_unref(&bufs[i]);
4719 
4720  return err;
4721 }
4722 
4724  const AVFrame *src)
4725 {
4727 
4728  switch (src->format) {
4729 #if CONFIG_CUDA
4730  case AV_PIX_FMT_CUDA:
4731 #ifdef _WIN32
4732  if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
4733  (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
4734 #else
4735  if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
4736  (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
4737 #endif
4738  return vulkan_transfer_data_from_cuda(hwfc, dst, src);
4739 #endif
4740  default:
4741  if (src->hw_frames_ctx)
4742  return AVERROR(ENOSYS);
4743  else
4744  return vulkan_transfer_frame(hwfc, (AVFrame *)src, dst, 1);
4745  }
4746 }
4747 
4748 #if CONFIG_CUDA
4749 static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst,
4750  const AVFrame *src)
4751 {
4752  int err;
4753  CUcontext dummy;
4754  AVVkFrame *dst_f;
4755  AVVkFrameInternal *dst_int;
4756  VulkanFramesPriv *fp = hwfc->hwctx;
4757  const int planes = av_pix_fmt_count_planes(hwfc->sw_format);
4759  int nb_images;
4760 
4761  AVHWFramesContext *cuda_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data;
4762  AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx;
4763  AVCUDADeviceContext *cuda_dev = cuda_cu->hwctx;
4764  AVCUDADeviceContextInternal *cu_internal = cuda_dev->internal;
4765  CudaFunctions *cu = cu_internal->cuda_dl;
4766  CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 };
4767  CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 };
4768 
4769  dst_f = (AVVkFrame *)src->data[0];
4770  nb_images = ff_vk_count_images(dst_f);
4771 
4772  err = prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_EXPORT);
4773  if (err < 0)
4774  return err;
4775 
4776  err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx));
4777  if (err < 0)
4778  return err;
4779 
4780  err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src);
4781  if (err < 0) {
4782  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4783  return err;
4784  }
4785 
4786  dst_int = dst_f->internal;
4787 
4788  for (int i = 0; i < planes; i++) {
4789  s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0;
4790  s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1;
4791  }
4792 
4793  err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par,
4794  nb_images, cuda_dev->stream));
4795  if (err < 0)
4796  goto fail;
4797 
4798  for (int i = 0; i < planes; i++) {
4799  CUDA_MEMCPY2D cpy = {
4800  .dstMemoryType = CU_MEMORYTYPE_DEVICE,
4801  .dstDevice = (CUdeviceptr)dst->data[i],
4802  .dstPitch = dst->linesize[i],
4803  .dstY = 0,
4804 
4805  .srcMemoryType = CU_MEMORYTYPE_ARRAY,
4806  .srcArray = dst_int->cu_array[i],
4807  };
4808 
4809  int w, h;
4810  get_plane_wh(&w, &h, hwfc->sw_format, hwfc->width, hwfc->height, i);
4811 
4812  cpy.WidthInBytes = w * desc->comp[i].step;
4813  cpy.Height = h;
4814 
4815  err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream));
4816  if (err < 0)
4817  goto fail;
4818  }
4819 
4820  err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par,
4821  nb_images, cuda_dev->stream));
4822  if (err < 0)
4823  goto fail;
4824 
4825  for (int i = 0; i < planes; i++)
4826  dst_f->sem_value[i]++;
4827 
4828  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4829 
4830  av_log(hwfc, AV_LOG_VERBOSE, "Transferred Vulkan image to CUDA!\n");
4831 
4832  return prepare_frame(hwfc, &fp->upload_exec, dst_f, PREP_MODE_EXTERNAL_IMPORT);
4833 
4834 fail:
4835  CHECK_CU(cu->cuCtxPopCurrent(&dummy));
4836  vulkan_free_internal(dst_f);
4837  av_buffer_unref(&dst->buf[0]);
4838  return err;
4839 }
4840 #endif
4841 
4843  const AVFrame *src)
4844 {
4846 
4847  switch (dst->format) {
4848 #if CONFIG_CUDA
4849  case AV_PIX_FMT_CUDA:
4850 #ifdef _WIN32
4851  if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) &&
4852  (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM))
4853 #else
4854  if ((p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) &&
4855  (p->vkctx.extensions & FF_VK_EXT_EXTERNAL_FD_SEM))
4856 #endif
4857  return vulkan_transfer_data_to_cuda(hwfc, dst, src);
4858 #endif
4859  default:
4860  if (dst->hw_frames_ctx)
4861  return AVERROR(ENOSYS);
4862  else
4863  return vulkan_transfer_frame(hwfc, dst, (AVFrame *)src, 0);
4864  }
4865 }
4866 
4868  AVHWFramesContext *src_fc, int flags)
4869 {
4870  return vulkan_frames_init(dst_fc);
4871 }
4872 
4874 {
4875  int err;
4876  AVVkFrame *f = av_mallocz(sizeof(AVVkFrame));
4877  if (!f)
4878  return NULL;
4879 
4880  f->internal = av_mallocz(sizeof(*f->internal));
4881  if (!f->internal) {
4882  av_free(f);
4883  return NULL;
4884  }
4885 
4886  err = pthread_mutex_init(&f->internal->update_mutex, NULL);
4887  if (err != 0) {
4888  av_free(f->internal);
4889  av_free(f);
4890  return NULL;
4891  }
4892 
4893  return f;
4894 }
4895 
4898  .name = "Vulkan",
4899 
4900  .device_hwctx_size = sizeof(VulkanDevicePriv),
4901  .frames_hwctx_size = sizeof(VulkanFramesPriv),
4902 
4903  .device_init = &vulkan_device_init,
4904  .device_uninit = &vulkan_device_uninit,
4905  .device_create = &vulkan_device_create,
4906  .device_derive = &vulkan_device_derive,
4907 
4908  .frames_get_constraints = &vulkan_frames_get_constraints,
4909  .frames_init = vulkan_frames_init,
4910  .frames_get_buffer = vulkan_get_buffer,
4911  .frames_uninit = vulkan_frames_uninit,
4912 
4913  .transfer_get_formats = vulkan_transfer_get_formats,
4914  .transfer_data_to = vulkan_transfer_data_to,
4915  .transfer_data_from = vulkan_transfer_data_from,
4916 
4917  .map_to = vulkan_map_to,
4918  .map_from = vulkan_map_from,
4919  .frames_derive_to = &vulkan_frames_derive_to,
4920 
4921  .pix_fmts = (const enum AVPixelFormat []) {
4924  },
4925 };
flags
const SwsFlags flags[]
Definition: swscale.c:71
vulkan_loader.h
formats
formats
Definition: signature.h:47
AV_PIX_FMT_YUVA422P16
#define AV_PIX_FMT_YUVA422P16
Definition: pixfmt.h:596
load_libvulkan
static int load_libvulkan(AVHWDeviceContext *ctx)
Definition: hwcontext_vulkan.c:632
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
FFHWFramesContext::pool_internal
AVBufferPool * pool_internal
Definition: hwcontext_internal.h:101
vulkan_device_init
static int vulkan_device_init(AVHWDeviceContext *ctx)
Definition: hwcontext_vulkan.c:1909
AV_PIX_FMT_GBRAP16
#define AV_PIX_FMT_GBRAP16
Definition: pixfmt.h:565
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:73
ff_vk_load_props
int ff_vk_load_props(FFVulkanContext *s)
Loads props/mprops/driver_props.
Definition: vulkan.c:147
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVVulkanDeviceContext::phys_dev
VkPhysicalDevice phys_dev
Physical device.
Definition: hwcontext_vulkan.h:79
AV_PIX_FMT_CUDA
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
Definition: pixfmt.h:260
VulkanDeviceFeatures::vulkan_1_2
VkPhysicalDeviceVulkan12Features vulkan_1_2
Definition: hwcontext_vulkan.c:79
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
VulkanDevicePriv::libvulkan
void * libvulkan
Definition: hwcontext_vulkan.c:129
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
VulkanOptExtension::name
const char * name
Definition: hwcontext_vulkan.c:671
FFVkFormatEntry::nb_images
int nb_images
Definition: hwcontext_vulkan.c:401
host_map_frame
static int host_map_frame(AVHWFramesContext *hwfc, AVBufferRef **dst, int *nb_bufs, AVFrame *swf, VkBufferImageCopy *region, int upload)
Definition: hwcontext_vulkan.c:4386
AVCUDADeviceContextInternal
Definition: hwcontext_cuda_internal.h:31
AV_PIX_FMT_GRAY32
#define AV_PIX_FMT_GRAY32
Definition: pixfmt.h:523
AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE
@ AV_VK_FRAME_FLAG_DISABLE_MULTIPLANE
Definition: hwcontext_vulkan.h:214
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
hwcontext_cuda_internal.h
HWMapDescriptor::source
AVFrame * source
A reference to the original source of the mapping.
Definition: hwcontext_internal.h:124
FFVulkanExtensions
uint64_t FFVulkanExtensions
Definition: vulkan_functions.h:29
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
SET_OLD_QF
#define SET_OLD_QF(field, nb_field, type)
vulkan_transfer_data_to
static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_vulkan.c:4723
FF_VK_EXT_EXTERNAL_WIN32_MEMORY
#define FF_VK_EXT_EXTERNAL_WIN32_MEMORY
Definition: vulkan_functions.h:39
FF_VK_EXT_VIDEO_QUEUE
#define FF_VK_EXT_VIDEO_QUEUE
Definition: vulkan_functions.h:58
thread.h
vk_dbg_callback
static VKAPI_ATTR VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *data, void *priv)
Definition: hwcontext_vulkan.c:770
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3456
CHECK_QUEUE
#define CHECK_QUEUE(type, required, fidx, ctx_qf, qc)
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
ff_vk_exec_pool_init
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.
Definition: vulkan.c:357
FF_VK_EXT_PORTABILITY_SUBSET
#define FF_VK_EXT_PORTABILITY_SUBSET
Definition: vulkan_functions.h:73
AV_HWFRAME_MAP_WRITE
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition: hwcontext.h:519
vulkan_frames_get_constraints
static int vulkan_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_vulkan.c:2271
FF_VK_EXT_VIDEO_MAINTENANCE_2
#define FF_VK_EXT_VIDEO_MAINTENANCE_2
Definition: vulkan_functions.h:60
AVVkFrameInternal::update_mutex
pthread_mutex_t update_mutex
Definition: hwcontext_vulkan.c:196
av_unused
#define av_unused
Definition: attributes.h:156
vulkan_frames_derive_to
static int vulkan_frames_derive_to(AVHWFramesContext *dst_fc, AVHWFramesContext *src_fc, int flags)
Definition: hwcontext_vulkan.c:4867
VulkanDeviceFeatures::explicit_mem_layout
VkPhysicalDeviceWorkgroupMemoryExplicitLayoutFeaturesKHR explicit_mem_layout
Definition: hwcontext_vulkan.c:84
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
PICK_QF
#define PICK_QF(type, vid_op)
FF_VK_EXT_VIDEO_DECODE_H265
#define FF_VK_EXT_VIDEO_DECODE_H265
Definition: vulkan_functions.h:64
mode
Definition: swscale.c:59
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:427
pixdesc.h
AVVulkanDeviceContext::get_proc_addr
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
Definition: hwcontext_vulkan.h:69
optional_device_exts
static const VulkanOptExtension optional_device_exts[]
Definition: hwcontext_vulkan.c:682
AVFrame::width
int width
Definition: frame.h:499
AV_PIX_FMT_YUVA420P16
#define AV_PIX_FMT_YUVA420P16
Definition: pixfmt.h:595
AV_PIX_FMT_Y216
#define AV_PIX_FMT_Y216
Definition: pixfmt.h:608
create_frame
static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkImageTiling tiling, VkImageUsageFlagBits usage, VkImageCreateFlags flags, int nb_layers, void *create_pnext)
Definition: hwcontext_vulkan.c:2705
AVDRMFrameDescriptor::nb_layers
int nb_layers
Number of layers in the frame.
Definition: hwcontext_drm.h:145
AV_PIX_FMT_DRM_PRIME
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:351
AV_PIX_FMT_YUVA420P10
#define AV_PIX_FMT_YUVA420P10
Definition: pixfmt.h:590
AVVulkanFramesContext::create_pnext
void * create_pnext
Extension data for image creation.
Definition: hwcontext_vulkan.h:251
ff_vk_find_struct
static const void * ff_vk_find_struct(const void *chain, VkStructureType stype)
Definition: vulkan.h:375
pthread_mutex_lock
static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition: os2threads.h:119
av_hwframe_map
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:793
COPY_VAL
#define COPY_VAL(VAL)
nb_vk_formats_list
static const int nb_vk_formats_list
Definition: hwcontext_vulkan.c:516
data
const char data[16]
Definition: mxf.c:149
AVVulkanDeviceContext::queue_family_encode_index
attribute_deprecated int queue_family_encode_index
Queue family index for video encode ops, and the amount of queues enabled.
Definition: hwcontext_vulkan.h:156
AV_PIX_FMT_RGBA128
#define AV_PIX_FMT_RGBA128
Definition: pixfmt.h:630
AV_PIX_FMT_YUV420P10
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:539
AVVulkanDeviceContext::inst
VkInstance inst
Vulkan instance.
Definition: hwcontext_vulkan.h:74
AV_PIX_FMT_XV30
#define AV_PIX_FMT_XV30
Definition: pixfmt.h:609
ff_vk_flush_buffer
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.
Definition: vulkan.c:1171
AVVulkanFramesContext::lock_frame
void(* lock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Locks a frame, preventing other threads from changing frame properties.
Definition: hwcontext_vulkan.h:296
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
AVVAAPIDeviceContext::display
VADisplay display
The VADisplay handle, to be filled by the user.
Definition: hwcontext_vaapi.h:72
switch_new_props
static void switch_new_props(enum PrepMode pmode, VkImageLayout *new_layout, VkAccessFlags2 *new_access)
Definition: hwcontext_vulkan.c:2529
FF_VULKAN_DEBUG_PRACTICES
@ FF_VULKAN_DEBUG_PRACTICES
Definition: hwcontext_vulkan.c:850
vulkan_map_from
static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vulkan.c:4278
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
FFVkFormatEntry::vkf
VkFormat vkf
Definition: hwcontext_vulkan.c:397
ff_vk_exec_get
FFVkExecContext * ff_vk_exec_get(FFVulkanContext *s, FFVkExecPool *pool)
Retrieve an execution pool.
Definition: vulkan.c:548
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2836
AVDictionary
Definition: dict.c:32
ff_hwframe_map_create
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:741
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
HWMapDescriptor::priv
void * priv
Hardware-specific private data associated with the mapping.
Definition: hwcontext_internal.h:139
FF_VK_EXT_COOP_MATRIX
#define FF_VK_EXT_COOP_MATRIX
Definition: vulkan_functions.h:44
av_popcount
#define av_popcount
Definition: common.h:154
AVDRMFrameDescriptor
DRM frame descriptor.
Definition: hwcontext_drm.h:133
AVHWFramesConstraints::valid_hw_formats
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:449
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:220
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:604
AV_PIX_FMT_YUVA422P10
#define AV_PIX_FMT_YUVA422P10
Definition: pixfmt.h:591
dummy
static int dummy
Definition: ffplay.c:3751
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
VulkanDeviceSelection::uuid
uint8_t uuid[VK_UUID_SIZE]
Definition: hwcontext_vulkan.c:1305
ff_vk_exec_add_dep_frame
int ff_vk_exec_add_dep_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f, VkPipelineStageFlagBits2 wait_stage, VkPipelineStageFlagBits2 signal_stage)
Definition: vulkan.c:780
FF_VULKAN_DEBUG_PRINTF
@ FF_VULKAN_DEBUG_PRINTF
Definition: hwcontext_vulkan.c:848
AV_PIX_FMT_P212
#define AV_PIX_FMT_P212
Definition: pixfmt.h:618
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:448
AVVulkanDeviceContext::unlock_queue
attribute_deprecated void(* unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Similar to lock_queue(), unlocks a queue.
Definition: hwcontext_vulkan.h:189
av_vk_get_optional_device_extensions
const char ** av_vk_get_optional_device_extensions(int *count)
Returns an array of optional Vulkan device extensions that FFmpeg may use if enabled.
Definition: hwcontext_vulkan.c:755
FFVkBuffer::buf
VkBuffer buf
Definition: vulkan.h:126
VulkanDeviceFeatures::host_image_copy
VkPhysicalDeviceHostImageCopyFeaturesEXT host_image_copy
Definition: hwcontext_vulkan.c:83
av_image_copy_plane
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.
Definition: imgutils.c:374
alloc_mem
static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkMemoryPropertyFlagBits req_flags, const void *alloc_extension, VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem)
Definition: hwcontext_vulkan.c:2317
AV_HWDEVICE_TYPE_VULKAN
@ AV_HWDEVICE_TYPE_VULKAN
Definition: hwcontext.h:39
VulkanDevicePriv::compute_qf
AVVulkanDeviceQueueFamily * compute_qf
Definition: hwcontext_vulkan.c:132
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:444
FF_VK_EXT_HOST_IMAGE_COPY
#define FF_VK_EXT_HOST_IMAGE_COPY
Definition: vulkan_functions.h:51
AV_HWDEVICE_TYPE_CUDA
@ AV_HWDEVICE_TYPE_CUDA
Definition: hwcontext.h:30
FF_VK_EXT_EXPECT_ASSUME
#define FF_VK_EXT_EXPECT_ASSUME
Definition: vulkan_functions.h:49
AVDRMDeviceContext::fd
int fd
File descriptor of DRM device.
Definition: hwcontext_drm.h:166
PREP_MODE_DECODING_DPB
@ PREP_MODE_DECODING_DPB
Definition: hwcontext_vulkan.c:2525
FF_VK_EXT_EXTERNAL_FD_SEM
#define FF_VK_EXT_EXTERNAL_FD_SEM
Definition: vulkan_functions.h:35
VulkanDeviceFeatures::device
VkPhysicalDeviceFeatures2 device
Definition: hwcontext_vulkan.c:76
VulkanDeviceFeatures::video_maintenance_1
VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1
Definition: hwcontext_vulkan.c:102
close
static av_cold void close(AVCodecParserContext *s)
Definition: apv_parser.c:197
av_pix_fmt_count_planes
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3496
ASPECT_3PLANE
#define ASPECT_3PLANE
Definition: hwcontext_vulkan.c:394
FF_VK_EXT_LONG_VECTOR
#define FF_VK_EXT_LONG_VECTOR
Definition: vulkan_functions.h:55
VulkanDevicePriv::hprops
VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops
Definition: hwcontext_vulkan.c:138
vulkan_device_derive
static int vulkan_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
Definition: hwcontext_vulkan.c:2168
VulkanOptExtension::flag
FFVulkanExtensions flag
Definition: hwcontext_vulkan.c:672
AVVulkanDeviceContext::alloc
const VkAllocationCallbacks * alloc
Custom memory allocator, else NULL.
Definition: hwcontext_vulkan.h:63
AV_PIX_FMT_GBRP14
#define AV_PIX_FMT_GBRP14
Definition: pixfmt.h:560
AVVkFrame::img
VkImage img[AV_NUM_DATA_POINTERS]
Vulkan images to which the memory is bound to.
Definition: hwcontext_vulkan.h:315
AV_PIX_FMT_GBRAP
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition: pixfmt.h:212
VulkanDeviceSelection::drm_minor
uint32_t drm_minor
Definition: hwcontext_vulkan.c:1308
AVVulkanDeviceContext::lock_queue
attribute_deprecated void(* lock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Locks a queue, preventing other threads from submitting any command buffers to this queue.
Definition: hwcontext_vulkan.h:181
lock_frame
static void lock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
Definition: hwcontext_vulkan.c:2952
fail
#define fail()
Definition: checkasm.h:223
AVDRMLayerDescriptor::nb_planes
int nb_planes
Number of planes in the layer.
Definition: hwcontext_drm.h:106
ff_vk_exec_add_dep_bool_sem
int ff_vk_exec_add_dep_bool_sem(FFVulkanContext *s, FFVkExecContext *e, VkSemaphore *sem, int nb, VkPipelineStageFlagBits2 stage, int wait)
Definition: vulkan.c:714
AV_PIX_FMT_GBRP10
#define AV_PIX_FMT_GBRP10
Definition: pixfmt.h:558
AV_PIX_FMT_YUVA444P16
#define AV_PIX_FMT_YUVA444P16
Definition: pixfmt.h:597
AVVulkanFramesContext::flags
AVVkFrameFlags flags
A combination of AVVkFrameFlags.
Definition: hwcontext_vulkan.h:267
VulkanDevicePriv
Definition: hwcontext_vulkan.c:122
AVVulkanDeviceContext::nb_tx_queues
attribute_deprecated int nb_tx_queues
Definition: hwcontext_vulkan.h:139
AVDRMLayerDescriptor::planes
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
Definition: hwcontext_drm.h:110
AVVkFrame::mem
VkDeviceMemory mem[AV_NUM_DATA_POINTERS]
Memory backing the images.
Definition: hwcontext_vulkan.h:328
switch_layout
static int switch_layout(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
Definition: hwcontext_vulkan.c:2564
device_features_copy_needed
static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceFeatures *src)
Definition: hwcontext_vulkan.c:288
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:220
ff_vk_frame_barrier
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)
Definition: vulkan.c:2050
av_buffer_pool_init2
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.
Definition: buffer.c:259
AVHWFramesConstraints::min_width
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:462
lock_queue
static void lock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Definition: hwcontext_vulkan.c:1897
AVCUDADeviceContextInternal::cuda_device
CUdevice cuda_device
Definition: hwcontext_cuda_internal.h:34
VulkanDevicePriv::limit_queues
int limit_queues
Definition: hwcontext_vulkan.c:169
VulkanDevicePriv::vkctx
FFVulkanContext vkctx
Definition: hwcontext_vulkan.c:131
AV_PIX_FMT_XV48
#define AV_PIX_FMT_XV48
Definition: pixfmt.h:611
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
FF_VK_EXT_VIDEO_ENCODE_H265
#define FF_VK_EXT_VIDEO_ENCODE_H265
Definition: vulkan_functions.h:70
ff_vk_host_map_buffer
int ff_vk_host_map_buffer(FFVulkanContext *s, AVBufferRef **dst, uint8_t *src_data, const AVBufferRef *src_buf, VkBufferUsageFlags usage)
Maps a system RAM buffer into a Vulkan buffer.
Definition: vulkan.c:1391
ff_vk_ret2str
const char * ff_vk_ret2str(VkResult res)
Converts Vulkan return values to strings.
Definition: vulkan.c:40
AV_PIX_FMT_GRAY16
#define AV_PIX_FMT_GRAY16
Definition: pixfmt.h:522
VulkanDeviceFeatures::vulkan_1_3
VkPhysicalDeviceVulkan13Features vulkan_1_3
Definition: hwcontext_vulkan.c:80
FF_VK_EXT_EXTERNAL_WIN32_SEM
#define FF_VK_EXT_EXTERNAL_WIN32_SEM
Definition: vulkan_functions.h:40
AVVulkanDeviceContext::queue_family_decode_index
attribute_deprecated int queue_family_decode_index
Queue family index for video decode ops, and the amount of queues enabled.
Definition: hwcontext_vulkan.h:166
VulkanDevicePriv::props
VkPhysicalDeviceProperties2 props
Definition: hwcontext_vulkan.c:136
ff_vk_aspect_flag
VkImageAspectFlags ff_vk_aspect_flag(AVFrame *f, int p)
Get the aspect flag for a plane from an image.
Definition: vulkan.c:1532
VulkanFramesPriv::drm_format_modifier_properties
VkDrmFormatModifierPropertiesEXT drm_format_modifier_properties[5]
Definition: hwcontext_vulkan.c:192
vk_find_format_entry
static const struct FFVkFormatEntry * vk_find_format_entry(enum AVPixelFormat p)
Definition: hwcontext_vulkan.c:526
AVDRMPlaneDescriptor::offset
ptrdiff_t offset
Offset within that object of this plane.
Definition: hwcontext_drm.h:83
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:52
AV_PIX_FMT_YUV444P10
#define AV_PIX_FMT_YUV444P10
Definition: pixfmt.h:542
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:606
AVVulkanDeviceQueueFamily::num
int num
Definition: hwcontext_vulkan.h:37
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
ffhwframesctx
static FFHWFramesContext * ffhwframesctx(AVHWFramesContext *ctx)
Definition: hwcontext_internal.h:115
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
ff_vk_link_struct
static void ff_vk_link_struct(void *chain, const void *in)
Definition: vulkan.h:388
check_layers
static int check_layers(AVHWDeviceContext *ctx, AVDictionary *opts, const char *const **dst, uint32_t *num, enum FFVulkanDebugMode *debug_mode)
Definition: hwcontext_vulkan.c:1020
AV_PIX_FMT_YUV422P16
#define AV_PIX_FMT_YUV422P16
Definition: pixfmt.h:551
AVVulkanDeviceContext::nb_encode_queues
attribute_deprecated int nb_encode_queues
Definition: hwcontext_vulkan.h:158
AVHWFramesContext::height
int height
Definition: hwcontext.h:220
AVHWFramesConstraints::valid_sw_formats
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:456
vulkan_map_to
static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_vulkan.c:4069
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:60
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:390
AV_PIX_FMT_GBRAP10
#define AV_PIX_FMT_GBRAP10
Definition: pixfmt.h:562
AVHWFramesContext::pool
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:181
VulkanDeviceSelection::pci_device
uint32_t pci_device
Definition: hwcontext_vulkan.c:1311
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_PIX_FMT_GBRAP14
#define AV_PIX_FMT_GBRAP14
Definition: pixfmt.h:564
AV_PIX_FMT_GBRAP12
#define AV_PIX_FMT_GBRAP12
Definition: pixfmt.h:563
AV_PIX_FMT_YUVA420P
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition: pixfmt.h:108
AV_PIX_FMT_RGB96
#define AV_PIX_FMT_RGB96
Definition: pixfmt.h:629
pthread_mutex_unlock
static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition: os2threads.h:126
AV_PIX_FMT_YUV444P16
#define AV_PIX_FMT_YUV444P16
Definition: pixfmt.h:552
offsets
static const int offsets[]
Definition: hevc_pel.c:34
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
ff_vk_load_functions
static int ff_vk_load_functions(AVHWDeviceContext *ctx, FFVulkanFunctions *vk, uint64_t extensions_mask, int has_inst, int has_dev)
Function loader.
Definition: vulkan_loader.h:128
VulkanDevicePriv::ext_sem_props_opaque
VkExternalSemaphoreProperties ext_sem_props_opaque
Definition: hwcontext_vulkan.c:142
prepare_frame
static int prepare_frame(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
Definition: hwcontext_vulkan.c:2672
vulkan_transfer_frame
static int vulkan_transfer_frame(AVHWFramesContext *hwfc, AVFrame *swf, AVFrame *hwf, int upload)
Definition: hwcontext_vulkan.c:4562
FF_VK_EXT_DEVICE_DRM
#define FF_VK_EXT_DEVICE_DRM
Definition: vulkan_functions.h:42
ff_vk_exec_wait
void ff_vk_exec_wait(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:553
av_strtok
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().
Definition: avstring.c:179
ASPECT_2PLANE
#define ASPECT_2PLANE
Definition: hwcontext_vulkan.c:393
vulkan_device_uninit
static void vulkan_device_uninit(AVHWDeviceContext *ctx)
Definition: hwcontext_vulkan.c:1777
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:494
AVVulkanFramesContext::unlock_frame
void(* unlock_frame)(struct AVHWFramesContext *fc, AVVkFrame *vkf)
Similar to lock_frame(), unlocks a frame.
Definition: hwcontext_vulkan.h:301
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
AVVulkanFramesContext::img_flags
VkImageCreateFlags img_flags
Flags to set during image creation.
Definition: hwcontext_vulkan.h:273
AV_PIX_FMT_GBRAP32
#define AV_PIX_FMT_GBRAP32
Definition: pixfmt.h:566
AV_PIX_FMT_YUVA444P12
#define AV_PIX_FMT_YUVA444P12
Definition: pixfmt.h:594
vulkan_frames_uninit
static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
Definition: hwcontext_vulkan.c:2962
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
AV_PIX_FMT_YUV420P16
#define AV_PIX_FMT_YUV420P16
Definition: pixfmt.h:550
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
AVDRMObjectDescriptor::fd
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
AV_PIX_FMT_GRAY14
#define AV_PIX_FMT_GRAY14
Definition: pixfmt.h:521
ff_vk_exec_add_dep_buf
int ff_vk_exec_add_dep_buf(FFVulkanContext *s, FFVkExecContext *e, AVBufferRef **deps, int nb_deps, int ref)
Execution dependency management.
Definition: vulkan.c:620
VulkanDeviceSelection::index
int index
Definition: hwcontext_vulkan.c:1313
AV_PIX_FMT_RGBF32
#define AV_PIX_FMT_RGBF32
Definition: pixfmt.h:626
VulkanFramesPriv::p
AVVulkanFramesContext p
The public AVVulkanFramesContext.
Definition: hwcontext_vulkan.c:176
vulkan_transfer_get_formats
static int vulkan_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_vulkan.c:3218
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:73
VulkanDevicePriv::avoid_host_import
int avoid_host_import
Definition: hwcontext_vulkan.c:166
ff_vk_exec_pool_free
void ff_vk_exec_pool_free(FFVulkanContext *s, FFVkExecPool *pool)
Definition: vulkan.c:299
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
FFVulkanDebugMode
FFVulkanDebugMode
Definition: hwcontext_vulkan.c:843
AV_PIX_FMT_GRAYF32
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:582
LIBAVUTIL_VERSION_MINOR
#define LIBAVUTIL_VERSION_MINOR
Definition: version.h:82
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
FFVkFormatEntry::nb_images_fallback
int nb_images_fallback
Definition: hwcontext_vulkan.c:402
vulkan_frame_free_cb
static void vulkan_frame_free_cb(void *opaque, uint8_t *data)
Definition: hwcontext_vulkan.c:2445
AV_PIX_FMT_GRAY10
#define AV_PIX_FMT_GRAY10
Definition: pixfmt.h:519
if
if(ret)
Definition: filter_design.txt:179
av_vkfmt_from_pixfmt
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.
Definition: hwcontext_vulkan.c:518
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
VulkanDevicePriv::qf_mutex
pthread_mutex_t ** qf_mutex
Definition: hwcontext_vulkan.c:148
AV_PIX_FMT_GBRP16
#define AV_PIX_FMT_GBRP16
Definition: pixfmt.h:561
opts
static AVDictionary * opts
Definition: movenc.c:51
PREP_MODE_WRITE
@ PREP_MODE_WRITE
Definition: hwcontext_vulkan.c:2521
AV_PIX_FMT_RGBA64
#define AV_PIX_FMT_RGBA64
Definition: pixfmt.h:529
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:213
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
FF_VK_EXT_DRM_MODIFIER_FLAGS
#define FF_VK_EXT_DRM_MODIFIER_FLAGS
Definition: vulkan_functions.h:33
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AVVulkanDeviceContext::nb_enabled_dev_extensions
int nb_enabled_dev_extensions
Definition: hwcontext_vulkan.h:117
FFVkFormatEntry
Definition: hwcontext_vulkan.c:396
FF_VK_EXT_SHADER_OBJECT
#define FF_VK_EXT_SHADER_OBJECT
Definition: vulkan_functions.h:46
AV_DRM_MAX_PLANES
@ AV_DRM_MAX_PLANES
The maximum number of layers/planes in a DRM frame.
Definition: hwcontext_drm.h:39
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
AVVkFrameInternal
Definition: hwcontext_vulkan.c:195
FF_VK_EXT_VIDEO_DECODE_VP9
#define FF_VK_EXT_VIDEO_DECODE_VP9
Definition: vulkan_functions.h:65
FF_VK_EXT_SUBGROUP_ROTATE
#define FF_VK_EXT_SUBGROUP_ROTATE
Definition: vulkan_functions.h:50
FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
Definition: vulkan_functions.h:68
VulkanDevicePriv::debug_ctx
VkDebugUtilsMessengerEXT debug_ctx
Definition: hwcontext_vulkan.c:154
FF_VULKAN_DEBUG_NONE
@ FF_VULKAN_DEBUG_NONE
Definition: hwcontext_vulkan.c:844
AVVulkanFramesContext::alloc_pnext
void * alloc_pnext[AV_NUM_DATA_POINTERS]
Extension data for memory allocation.
Definition: hwcontext_vulkan.h:260
setup_queue_families
static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
Definition: hwcontext_vulkan.c:1557
LIBAVUTIL_VERSION_MAJOR
#define LIBAVUTIL_VERSION_MAJOR
Definition: version.h:81
AVVulkanDeviceContext::nb_decode_queues
attribute_deprecated int nb_decode_queues
Definition: hwcontext_vulkan.h:168
planes
static const struct @577 planes[]
AV_PIX_FMT_P410
#define AV_PIX_FMT_P410
Definition: pixfmt.h:617
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
AVVulkanDeviceContext::nb_qf
int nb_qf
Definition: hwcontext_vulkan.h:201
ff_hwcontext_type_vulkan
const HWContextType ff_hwcontext_type_vulkan
Definition: hwcontext_vulkan.c:4896
hwcontext_vulkan.h
AVVulkanDeviceContext::queue_family_tx_index
attribute_deprecated int queue_family_tx_index
Queue family index for transfer operations and the number of queues enabled.
Definition: hwcontext_vulkan.h:137
AVVulkanDeviceContext::enabled_inst_extensions
const char *const * enabled_inst_extensions
Enabled instance extensions.
Definition: hwcontext_vulkan.h:103
vk_formats_list
static const struct FFVkFormatEntry vk_formats_list[]
AVVulkanFramesContext::format
VkFormat format[AV_NUM_DATA_POINTERS]
Vulkan format for each image.
Definition: hwcontext_vulkan.h:281
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:240
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
AV_PIX_FMT_YUV422P10
#define AV_PIX_FMT_YUV422P10
Definition: pixfmt.h:540
alloc_bind_mem
static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, void *alloc_pnext, size_t alloc_pnext_stride)
Definition: hwcontext_vulkan.c:2450
FFVkBuffer::mapped_mem
uint8_t * mapped_mem
Definition: vulkan.h:134
AVVulkanDeviceContext::qf
AVVulkanDeviceQueueFamily qf[64]
Queue families used.
Definition: hwcontext_vulkan.h:200
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
FFVulkanContext
Definition: vulkan.h:312
exp
int8_t exp
Definition: eval.c:76
FF_VK_EXT_REPLICATED_COMPOSITES
#define FF_VK_EXT_REPLICATED_COMPOSITES
Definition: vulkan_functions.h:54
AV_PIX_FMT_GBRPF16
#define AV_PIX_FMT_GBRPF16
Definition: pixfmt.h:576
VulkanFramesPriv
Definition: hwcontext_vulkan.c:172
vulkan_frame_free
static void vulkan_frame_free(AVHWFramesContext *hwfc, AVVkFrame *f)
Definition: hwcontext_vulkan.c:2411
pick_video_queue_family
static int pick_video_queue_family(VkQueueFamilyProperties2 *qf, VkQueueFamilyVideoPropertiesKHR *qf_vid, uint32_t num_qf, VkVideoCodecOperationFlagsKHR flags)
Definition: hwcontext_vulkan.c:1528
index
int index
Definition: gxfenc.c:90
av_buffer_create
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.
Definition: buffer.c:55
vkfmt_from_pixfmt2
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)
Definition: hwcontext_vulkan.c:534
VulkanDeviceSelection
Definition: hwcontext_vulkan.c:1304
source
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a source
Definition: filter_design.txt:256
VulkanDevicePriv::nb_tot_qfs
uint32_t nb_tot_qfs
Definition: hwcontext_vulkan.c:149
VulkanDeviceFeatures
Definition: hwcontext_vulkan.c:75
AVDRMFrameDescriptor::layers
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
Definition: hwcontext_drm.h:149
usage
const char * usage
Definition: floatimg_cmp.c:62
PREP_MODE_DECODING_DST
@ PREP_MODE_DECODING_DST
Definition: hwcontext_vulkan.c:2524
AVVkFrame::size
size_t size[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:329
vulkan_pool_alloc
static AVBufferRef * vulkan_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_vulkan.c:2877
VulkanDevicePriv::dprops
VkPhysicalDeviceDriverProperties dprops
Definition: hwcontext_vulkan.c:139
AV_PIX_FMT_X2BGR10
#define AV_PIX_FMT_X2BGR10
Definition: pixfmt.h:614
PrepMode
PrepMode
Definition: hwcontext_vulkan.c:2519
FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
Definition: vulkan_functions.h:59
VulkanDeviceSelection::has_drm
uint32_t has_drm
Definition: hwcontext_vulkan.c:1309
f
f
Definition: af_crystalizer.c:122
AVCUDADeviceContext::internal
AVCUDADeviceContextInternal * internal
Definition: hwcontext_cuda.h:45
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
VulkanDeviceFeatures::vulkan_1_1
VkPhysicalDeviceVulkan11Features vulkan_1_1
Definition: hwcontext_vulkan.c:78
sem_wait
#define sem_wait(psem)
Definition: semaphore.h:27
AV_PIX_FMT_P012
#define AV_PIX_FMT_P012
Definition: pixfmt.h:603
AV_PIX_FMT_FLAG_RGB
#define AV_PIX_FMT_FLAG_RGB
The pixel format contains RGB-like data (as opposed to YUV/grayscale).
Definition: pixdesc.h:136
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
AVVkFrame
Definition: hwcontext_vulkan.h:310
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
av_vk_frame_alloc
AVVkFrame * av_vk_frame_alloc(void)
Allocates a single AVVkFrame and initializes everything as 0.
Definition: hwcontext_vulkan.c:4873
FF_VULKAN_DEBUG_VALIDATE
@ FF_VULKAN_DEBUG_VALIDATE
Definition: hwcontext_vulkan.c:846
vulkan.h
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
FF_VK_EXT_EXTERNAL_DMABUF_MEMORY
#define FF_VK_EXT_EXTERNAL_DMABUF_MEMORY
Definition: vulkan_functions.h:32
vulkan_device_free
static void vulkan_device_free(AVHWDeviceContext *ctx)
Definition: hwcontext_vulkan.c:1754
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
FF_VK_EXT_NO_FLAG
#define FF_VK_EXT_NO_FLAG
Definition: vulkan_functions.h:74
AV_PIX_FMT_GBRPF32
#define AV_PIX_FMT_GBRPF32
Definition: pixfmt.h:578
AV_PIX_FMT_YUV422P12
#define AV_PIX_FMT_YUV422P12
Definition: pixfmt.h:544
VulkanDeviceFeatures::cooperative_matrix
VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix
Definition: hwcontext_vulkan.c:114
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:525
size
int size
Definition: twinvq_data.h:10344
ff_vk_exec_add_dep_sw_frame
int ff_vk_exec_add_dep_sw_frame(FFVulkanContext *s, FFVkExecContext *e, AVFrame *f)
Definition: vulkan.c:647
vulkan_transfer_data_from
static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_vulkan.c:4842
AV_NUM_DATA_POINTERS
#define AV_NUM_DATA_POINTERS
Definition: frame.h:428
FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_PUSH_DESCRIPTOR
Definition: vulkan_functions.h:47
VulkanDevicePriv::use_linear_images
int use_linear_images
Definition: hwcontext_vulkan.c:157
AV_PIX_FMT_YUV444P12
#define AV_PIX_FMT_YUV444P12
Definition: pixfmt.h:546
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:514
AV_PIX_FMT_NV16
@ AV_PIX_FMT_NV16
interleaved chroma YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:198
VulkanDeviceSelection::vendor_id
uint32_t vendor_id
Definition: hwcontext_vulkan.c:1312
PREP_MODE_GENERAL
@ PREP_MODE_GENERAL
Definition: hwcontext_vulkan.c:2520
AV_PIX_FMT_Y212
#define AV_PIX_FMT_Y212
Definition: pixfmt.h:607
AVVulkanDeviceContext::queue_family_index
attribute_deprecated int queue_family_index
Queue family index for graphics operations, and the number of queues enabled for it.
Definition: hwcontext_vulkan.h:128
AVDRMObjectDescriptor::size
size_t size
Total size of the object.
Definition: hwcontext_drm.h:58
AV_PIX_FMT_YUVA444P
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition: pixfmt.h:174
VulkanFramesPriv::upload_exec
FFVkExecPool upload_exec
Definition: hwcontext_vulkan.c:182
AVVulkanDeviceQueueFamily::idx
int idx
Definition: hwcontext_vulkan.h:35
AV_PIX_FMT_YUVA444P10
#define AV_PIX_FMT_YUVA444P10
Definition: pixfmt.h:592
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
AVHWFramesConstraints::max_width
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:469
FFVkExecContext
Definition: vulkan.h:145
VulkanOptExtension
Definition: hwcontext_vulkan.c:670
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
AV_PIX_FMT_P216
#define AV_PIX_FMT_P216
Definition: pixfmt.h:620
CHECK_CU
#define CHECK_CU(x)
Definition: cuviddec.c:117
AV_PIX_FMT_P210
#define AV_PIX_FMT_P210
Definition: pixfmt.h:616
AV_PIX_FMT_VAAPI
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
Definition: pixfmt.h:126
VulkanDeviceFeatures::subgroup_rotate
VkPhysicalDeviceShaderSubgroupRotateFeaturesKHR subgroup_rotate
Definition: hwcontext_vulkan.c:82
FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
Definition: vulkan_functions.h:62
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
vulkan_free_internal
static void vulkan_free_internal(AVVkFrame *f)
Definition: hwcontext_vulkan.c:2375
VulkanDeviceFeatures::timeline_semaphore
VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore
Definition: hwcontext_vulkan.c:81
AV_HWDEVICE_TYPE_VAAPI
@ AV_HWDEVICE_TYPE_VAAPI
Definition: hwcontext.h:31
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
layout
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel layout
Definition: filter_design.txt:18
FF_VK_EXT_EXTERNAL_HOST_MEMORY
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
Definition: vulkan_functions.h:36
FF_VK_EXT_EXPLICIT_MEM_LAYOUT
#define FF_VK_EXT_EXPLICIT_MEM_LAYOUT
Definition: vulkan_functions.h:53
AV_PIX_FMT_UYVA
@ AV_PIX_FMT_UYVA
packed UYVA 4:4:4:4, 32bpp (1 Cr & Cb sample per 1x1 Y & A samples), UYVAUYVA...
Definition: pixfmt.h:444
AVDRMFrameDescriptor::objects
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
Definition: hwcontext_drm.h:141
AVCUDADeviceContextInternal::cuda_dl
CudaFunctions * cuda_dl
Definition: hwcontext_cuda_internal.h:32
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:68
ff_vk_exec_start
int ff_vk_exec_start(FFVulkanContext *s, FFVkExecContext *e)
Start/submit/wait an execution.
Definition: vulkan.c:560
FF_VK_EXT_RELAXED_EXTENDED_INSTR
#define FF_VK_EXT_RELAXED_EXTENDED_INSTR
Definition: vulkan_functions.h:48
FF_VK_EXT_VIDEO_DECODE_H264
#define FF_VK_EXT_VIDEO_DECODE_H264
Definition: vulkan_functions.h:63
VulkanFramesPriv::compute_exec
FFVkExecPool compute_exec
Definition: hwcontext_vulkan.c:179
AVVulkanDeviceContext::queue_family_comp_index
attribute_deprecated int queue_family_comp_index
Queue family index for compute operations and the number of queues enabled.
Definition: hwcontext_vulkan.h:146
AVDRMObjectDescriptor::format_modifier
uint64_t format_modifier
Format modifier applied to the object (DRM_FORMAT_MOD_*).
Definition: hwcontext_drm.h:65
VkFormat
enum VkFormat VkFormat
Definition: hwcontext_stub.c:25
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
AV_PIX_FMT_GBRP12
#define AV_PIX_FMT_GBRP12
Definition: pixfmt.h:559
weights
static const int weights[]
Definition: hevc_pel.c:32
AV_PIX_FMT_NV24
@ 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...
Definition: pixfmt.h:371
plane_info
Definition: vf_edgedetect.c:53
VulkanDevicePriv::nb_img_qfs
uint32_t nb_img_qfs
Definition: hwcontext_vulkan.c:151
vulkan_frames_init
static int vulkan_frames_init(AVHWFramesContext *hwfc)
Definition: hwcontext_vulkan.c:2980
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_PIX_FMT_X2RGB10
#define AV_PIX_FMT_X2RGB10
Definition: pixfmt.h:613
VulkanDeviceSelection::has_uuid
int has_uuid
Definition: hwcontext_vulkan.c:1306
hwcontext_drm.h
AVDRMPlaneDescriptor::object_index
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor.
Definition: hwcontext_drm.h:79
AV_PIX_FMT_BGR565
#define AV_PIX_FMT_BGR565
Definition: pixfmt.h:531
ff_hwframe_map_replace
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)-...
Definition: hwcontext.c:948
VulkanDevicePriv::img_qfs
uint32_t img_qfs[64]
Definition: hwcontext_vulkan.c:150
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
mod
static int mod(int a, int b)
Modulo operation with only positive remainders.
Definition: vf_v360.c:755
AV_PIX_FMT_P016
#define AV_PIX_FMT_P016
Definition: pixfmt.h:604
AV_PIX_FMT_RGB565
#define AV_PIX_FMT_RGB565
Definition: pixfmt.h:526
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:406
AVVkFrame::sem
VkSemaphore sem[AV_NUM_DATA_POINTERS]
Synchronization timeline semaphores, one for each VkImage.
Definition: hwcontext_vulkan.h:348
create_instance
static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts, enum FFVulkanDebugMode *debug_mode)
Definition: hwcontext_vulkan.c:1167
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
FF_VK_EXT_EXTERNAL_FD_MEMORY
#define FF_VK_EXT_EXTERNAL_FD_MEMORY
Definition: vulkan_functions.h:34
AVCUDADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_cuda.h:42
hwcontext_vaapi.h
AVDRMLayerDescriptor::format
uint32_t format
Format of the layer (DRM_FORMAT_*).
Definition: hwcontext_drm.h:100
VulkanDevicePriv::transfer_qf
AVVulkanDeviceQueueFamily * transfer_qf
Definition: hwcontext_vulkan.c:133
ret
ret
Definition: filter_design.txt:187
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:75
AV_PIX_FMT_NV12
@ 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...
Definition: pixfmt.h:96
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:137
FFVulkanContext::vkfn
FFVulkanFunctions vkfn
Definition: vulkan.h:316
cuda_check.h
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:153
VulkanFramesPriv::tmp
AVBufferPool * tmp
Definition: hwcontext_vulkan.c:186
vulkan_get_buffer
static int vulkan_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
Definition: hwcontext_vulkan.c:3204
pick_queue_family
static int pick_queue_family(VkQueueFamilyProperties2 *qf, uint32_t num_qf, VkQueueFlagBits flags)
Definition: hwcontext_vulkan.c:1499
FFVkExecPool
Definition: vulkan.h:290
vulkan_transfer_host
static int vulkan_transfer_host(AVHWFramesContext *hwfc, AVFrame *hwf, AVFrame *swf, int upload)
Definition: hwcontext_vulkan.c:4443
unlock_queue
static void unlock_queue(AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Definition: hwcontext_vulkan.c:1903
AVHWFramesConstraints::max_height
int max_height
Definition: hwcontext.h:470
AVVkFrame::internal
struct AVVkFrameInternal * internal
Internal data.
Definition: hwcontext_vulkan.h:361
ff_vk_qf_find
AVVulkanDeviceQueueFamily * ff_vk_qf_find(FFVulkanContext *s, VkQueueFlagBits dev_family, VkVideoCodecOperationFlagBitsKHR vid_ops)
Chooses an appropriate QF.
Definition: vulkan.c:286
AV_PIX_FMT_YUV420P12
#define AV_PIX_FMT_YUV420P12
Definition: pixfmt.h:543
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
check_extensions
static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *const **dst, uint32_t *num, enum FFVulkanDebugMode debug_mode)
Definition: hwcontext_vulkan.c:855
FFVkExecContext::buf
VkCommandBuffer buf
Definition: vulkan.h:156
vulkan_device_create
static int vulkan_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_vulkan.c:2152
AVFrame::height
int height
Definition: frame.h:499
PREP_MODE_ENCODING_DPB
@ PREP_MODE_ENCODING_DPB
Definition: hwcontext_vulkan.c:2526
FFVkFormatEntry::pixfmt
enum AVPixelFormat pixfmt
Definition: hwcontext_vulkan.c:398
AVHWFramesConstraints::min_height
int min_height
Definition: hwcontext.h:463
RELEASE_PROPS
#define RELEASE_PROPS(props, count)
Definition: hwcontext_vulkan.c:816
mode
mode
Definition: ebur128.h:83
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_PIX_FMT_YUVA422P12
#define AV_PIX_FMT_YUVA422P12
Definition: pixfmt.h:593
AV_PIX_FMT_GBRAPF32
#define AV_PIX_FMT_GBRAPF32
Definition: pixfmt.h:579
AV_HWFRAME_MAP_READ
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition: hwcontext.h:515
VulkanDevicePriv::feats
VulkanDeviceFeatures feats
Definition: hwcontext_vulkan.c:145
switch_layout_host
static int switch_layout_host(AVHWFramesContext *hwfc, FFVkExecPool *ectx, AVVkFrame *frame, enum PrepMode pmode)
Definition: hwcontext_vulkan.c:2627
LIBAVUTIL_VERSION_MICRO
#define LIBAVUTIL_VERSION_MICRO
Definition: version.h:83
AV_PIX_FMT_GBRAPF16
#define AV_PIX_FMT_GBRAPF16
Definition: pixfmt.h:577
find_device
static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select)
Definition: hwcontext_vulkan.c:1328
AVVulkanDeviceContext::nb_graphics_queues
attribute_deprecated int nb_graphics_queues
Definition: hwcontext_vulkan.h:130
FF_VK_STRUCT_EXT
#define FF_VK_STRUCT_EXT(CTX, BASE, STRUCT_P, EXT_FLAG, TYPE)
Definition: vulkan.h:397
optional_instance_exts
static const VulkanOptExtension optional_instance_exts[]
Definition: hwcontext_vulkan.c:675
AV_PIX_FMT_FLAG_PLANAR
#define AV_PIX_FMT_FLAG_PLANAR
At least one pixel component is not in the first data plane.
Definition: pixdesc.h:132
ff_vk_map_feats_to_usage
VkImageUsageFlags ff_vk_map_feats_to_usage(VkFormatFeatureFlagBits2 feats)
Map between usage and features.
FF_VK_EXT_ATOMIC_FLOAT
#define FF_VK_EXT_ATOMIC_FLOAT
Definition: vulkan_functions.h:43
FFVkFormatEntry::fallback
const VkFormat fallback[5]
Definition: hwcontext_vulkan.c:403
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
PREP_MODE_EXTERNAL_IMPORT
@ PREP_MODE_EXTERNAL_IMPORT
Definition: hwcontext_vulkan.c:2523
AV_PIX_FMT_RGBAF32
#define AV_PIX_FMT_RGBAF32
Definition: pixfmt.h:627
FF_VK_EXT_VIDEO_DECODE_AV1
#define FF_VK_EXT_VIDEO_DECODE_AV1
Definition: vulkan_functions.h:66
AV_PIX_FMT_YUV444P
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition: pixfmt.h:78
AVVulkanFramesContext::tiling
VkImageTiling tiling
Controls the tiling of allocated frames.
Definition: hwcontext_vulkan.h:229
VulkanDeviceSelection::drm_major
uint32_t drm_major
Definition: hwcontext_vulkan.c:1307
get_plane_buf
static int get_plane_buf(AVHWFramesContext *hwfc, AVBufferRef **dst, AVFrame *swf, VkBufferImageCopy *region, int upload)
Definition: hwcontext_vulkan.c:4347
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:602
unlock_frame
static void unlock_frame(AVHWFramesContext *fc, AVVkFrame *vkf)
Definition: hwcontext_vulkan.c:2957
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:72
AVVkFrame::sem_value
uint64_t sem_value[AV_NUM_DATA_POINTERS]
Up to date semaphore value at which each image becomes accessible.
Definition: hwcontext_vulkan.h:356
AV_PIX_FMT_GBRP
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition: pixfmt.h:165
desc
const char * desc
Definition: libsvtav1.c:82
AVVulkanDeviceContext::enabled_dev_extensions
const char *const * enabled_dev_extensions
Enabled device extensions.
Definition: hwcontext_vulkan.h:116
AVVulkanFramesContext::nb_layers
int nb_layers
Number of layers each image will have.
Definition: hwcontext_vulkan.h:286
AV_PIX_FMT_YUV422P
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition: pixfmt.h:77
VulkanFramesPriv::download_exec
FFVkExecPool download_exec
Definition: hwcontext_vulkan.c:183
mem.h
AVVkFrame::layout
VkImageLayout layout[AV_NUM_DATA_POINTERS]
Definition: hwcontext_vulkan.h:340
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
av_strdup
#define av_strdup(s)
Definition: ops_asmgen.c:47
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
w
uint8_t w
Definition: llvidencdsp.c:39
hwcontext_internal.h
FF_VK_EXT_VIDEO_ENCODE_H264
#define FF_VK_EXT_VIDEO_ENCODE_H264
Definition: vulkan_functions.h:69
ADD_QUEUE
#define ADD_QUEUE(ctx_qf, qc, flag)
AVVulkanDeviceContext::nb_enabled_inst_extensions
int nb_enabled_inst_extensions
Definition: hwcontext_vulkan.h:104
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVDictionaryEntry
Definition: dict.h:90
get_plane_wh
static void get_plane_wh(uint32_t *w, uint32_t *h, enum AVPixelFormat format, int frame_w, int frame_h, int plane)
Definition: hwcontext_vulkan.c:2688
ff_vk_count_images
static int ff_vk_count_images(AVVkFrame *f)
Definition: vulkan.h:366
ff_vk_exec_discard_deps
void ff_vk_exec_discard_deps(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:592
PREP_MODE_EXTERNAL_EXPORT
@ PREP_MODE_EXTERNAL_EXPORT
Definition: hwcontext_vulkan.c:2522
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AV_PIX_FMT_P416
#define AV_PIX_FMT_P416
Definition: pixfmt.h:621
VulkanDevicePriv::mprops
VkPhysicalDeviceMemoryProperties mprops
Definition: hwcontext_vulkan.c:137
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
FF_VULKAN_DEBUG_NB
@ FF_VULKAN_DEBUG_NB
Definition: hwcontext_vulkan.c:852
FFVkBuffer
Definition: vulkan.h:125
vk_dev_type
static const char * vk_dev_type(enum VkPhysicalDeviceType type)
Definition: hwcontext_vulkan.c:1316
VulkanDevicePriv::disable_multiplane
int disable_multiplane
Definition: hwcontext_vulkan.c:163
imgutils.h
ff_vk_exec_submit
int ff_vk_exec_submit(FFVulkanContext *s, FFVkExecContext *e)
Definition: vulkan.c:905
AV_PIX_FMT_XV36
#define AV_PIX_FMT_XV36
Definition: pixfmt.h:610
hwcontext.h
AVDRMPlaneDescriptor::pitch
ptrdiff_t pitch
Pitch (linesize) of this plane.
Definition: hwcontext_drm.h:87
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:472
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
FFVkFormatEntry::vk_planes
int vk_planes
Definition: hwcontext_vulkan.c:400
AVVulkanDeviceQueueFamily
Definition: hwcontext_vulkan.h:33
HWContextType
Definition: hwcontext_internal.h:29
FF_VK_EXT_VIDEO_ENCODE_AV1
#define FF_VK_EXT_VIDEO_ENCODE_AV1
Definition: vulkan_functions.h:71
AV_PIX_FMT_P412
#define AV_PIX_FMT_P412
Definition: pixfmt.h:619
device_features_init
static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *feats)
Definition: hwcontext_vulkan.c:214
VulkanDevicePriv::contiguous_planes
int contiguous_planes
Definition: hwcontext_vulkan.c:160
AVVAAPIDeviceContext
VAAPI connection details.
Definition: hwcontext_vaapi.h:68
h
h
Definition: vp9dsp_template.c:2070
AVVulkanDeviceContext::device_features
VkPhysicalDeviceFeatures2 device_features
This structure should be set to the set of features that present and enabled during device creation.
Definition: hwcontext_vulkan.h:92
AVDictionaryEntry::value
char * value
Definition: dict.h:92
avstring.h
AVDRMDeviceContext
DRM device.
Definition: hwcontext_drm.h:157
AV_PIX_FMT_GRAY12
#define AV_PIX_FMT_GRAY12
Definition: pixfmt.h:520
copy_buffer_data
static int copy_buffer_data(AVHWFramesContext *hwfc, AVBufferRef *buf, AVFrame *swf, VkBufferImageCopy *region, int planes, int upload)
Definition: hwcontext_vulkan.c:4304
VulkanDeviceFeatures::atomic_float
VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float
Definition: hwcontext_vulkan.c:115
ADD_VAL_TO_LIST
#define ADD_VAL_TO_LIST(list, count, val)
Definition: hwcontext_vulkan.c:802
AV_PIX_FMT_BAYER_RGGB16
#define AV_PIX_FMT_BAYER_RGGB16
Definition: pixfmt.h:572
AVDRMFrameDescriptor::nb_objects
int nb_objects
Number of DRM objects making up this frame.
Definition: hwcontext_drm.h:137
VulkanDeviceFeatures::shader_object
VkPhysicalDeviceShaderObjectFeaturesEXT shader_object
Definition: hwcontext_vulkan.c:113
HWMapDescriptor
Definition: hwcontext_internal.h:120
AVVulkanDeviceQueueFamily::flags
VkQueueFlagBits flags
Definition: hwcontext_vulkan.h:41
AVVulkanDeviceQueueFamily::video_caps
VkVideoCodecOperationFlagBitsKHR video_caps
Definition: hwcontext_vulkan.h:44
FF_VK_EXT_ZERO_INITIALIZE
#define FF_VK_EXT_ZERO_INITIALIZE
Definition: vulkan_functions.h:52
FFVulkanFunctions
Definition: vulkan_functions.h:274
VulkanDevicePriv::p
AVVulkanDeviceContext p
The public AVVulkanDeviceContext.
Definition: hwcontext_vulkan.c:126
VulkanFramesPriv::modifier_info
VkImageDrmFormatModifierListCreateInfoEXT * modifier_info
Definition: hwcontext_vulkan.c:189
FFVkFormatEntry::aspect
VkImageAspectFlags aspect
Definition: hwcontext_vulkan.c:399
ff_vk_get_pooled_buffer
int ff_vk_get_pooled_buffer(FFVulkanContext *ctx, AVBufferPool **buf_pool, AVBufferRef **buf, VkBufferUsageFlags usage, void *create_pNext, size_t size, VkMemoryPropertyFlagBits mem_props)
Initialize a pool and create AVBufferRefs containing FFVkBuffer.
Definition: vulkan.c:1286
VulkanDeviceSelection::name
const char * name
Definition: hwcontext_vulkan.c:1310
src
#define src
Definition: vp8dsp.c:248
AV_HWDEVICE_TYPE_DRM
@ AV_HWDEVICE_TYPE_DRM
Definition: hwcontext.h:36
AVVulkanDeviceContext::nb_comp_queues
attribute_deprecated int nb_comp_queues
Definition: hwcontext_vulkan.h:148
AV_PIX_FMT_YUVA422P
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition: pixfmt.h:173
vulkan_device_create_internal
static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VulkanDeviceSelection *dev_select, int disable_multiplane, AVDictionary *opts, int flags)
Definition: hwcontext_vulkan.c:1790
w32dlfcn.h
av_vk_get_optional_instance_extensions
const char ** av_vk_get_optional_instance_extensions(int *count)
Returns an array of optional Vulkan instance extensions that FFmpeg may use if enabled.
Definition: hwcontext_vulkan.c:741
av_get_pix_fmt_name
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.
Definition: pixdesc.c:3376
vulkan_device_has_rebar
static int vulkan_device_has_rebar(AVHWDeviceContext *ctx)
Definition: hwcontext_vulkan.c:823
try_export_flags
static void try_export_flags(AVHWFramesContext *hwfc, VkExternalMemoryHandleTypeFlags *comp_handle_types, VkExternalMemoryHandleTypeFlags *iexp, VkExternalMemoryHandleTypeFlagBits exp)
Definition: hwcontext_vulkan.c:2815