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