FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
vulkan_loader.h
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #ifndef AVUTIL_VULKAN_LOADER_H
20 #define AVUTIL_VULKAN_LOADER_H
21 
22 #include <stdio.h>
23 
24 #include "avassert.h"
25 #include "vulkan_functions.h"
26 
27 /* Macro to turn a function name into a loader struct */
28 #define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \
29  { \
30  req_inst, \
31  req_dev, \
32  offsetof(FFVulkanFunctions, name), \
33  ext_flag, \
34  },
35 
36 static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
37  int nb_extensions)
38 {
39  static const struct ExtensionMap {
40  const char *name;
42  } extension_map[] = {
43  /* Instance extensions */
44  { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS },
45 
46  /* Device extensions */
47 #ifdef VK_KHR_shader_relaxed_extended_instruction
48  { VK_KHR_SHADER_RELAXED_EXTENDED_INSTRUCTION_EXTENSION_NAME, FF_VK_EXT_RELAXED_EXTENDED_INSTR },
49 #endif
50  { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
51  { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS },
52  { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY },
53  { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM },
54  { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY },
55  { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS },
56  { VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM },
57  { VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT },
58  { VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX },
59  { VK_NV_OPTICAL_FLOW_EXTENSION_NAME, FF_VK_EXT_OPTICAL_FLOW },
60  { VK_EXT_SHADER_OBJECT_EXTENSION_NAME, FF_VK_EXT_SHADER_OBJECT },
61  { VK_KHR_VIDEO_MAINTENANCE_1_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_1 },
62 #ifdef VK_KHR_video_maintenance2
63  { VK_KHR_VIDEO_MAINTENANCE_2_EXTENSION_NAME, FF_VK_EXT_VIDEO_MAINTENANCE_2 },
64 #endif
65 #ifdef _WIN32
66  { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY },
67  { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM },
68 #endif
69  { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, },
70  { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE },
71  { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_QUEUE },
72  { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE },
73  { VK_KHR_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H264 },
74  { VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 },
75  { VK_KHR_VIDEO_ENCODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_ENCODE_H265 },
76  { VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 },
77  { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_AV1 },
78  { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_PUSH_DESCRIPTOR },
79  };
80 
82 
83  for (int i = 0; i < nb_extensions; i++) {
84  for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) {
85  if (!strcmp(extensions[i], extension_map[j].name)) {
86  mask |= extension_map[j].flag;
87  continue;
88  }
89  }
90  }
91 
92  return mask;
93 }
94 
95 /**
96  * Function loader.
97  * Vulkan function from scratch loading happens in 3 stages - the first one
98  * is before any initialization has happened, and you have neither an instance
99  * structure nor a device structure. At this stage, you can only get the bare
100  * minimals to initialize an instance.
101  * The second stage is when you have an instance. At this stage, you can
102  * initialize a VkDevice, and have an idea of what extensions each device
103  * supports.
104  * Finally, in the third stage, you can proceed and load all core functions,
105  * plus you can be sure that any extensions you've enabled during device
106  * initialization will be available.
107  */
109  FFVulkanFunctions *vk,
110  uint64_t extensions_mask,
111  int has_inst, int has_dev)
112 {
113  AVVulkanDeviceContext *hwctx = ctx->hwctx;
114 
115  static const struct FunctionLoadInfo {
116  char req_inst;
117  char req_dev;
118  uint16_t struct_offset;
119  FFVulkanExtensions ext_flag;
120  } vk_load_info[] = {
122 #ifdef _WIN32
124 #endif
125  };
126  // Concatenate the names to avoid relocations. The resulting string
127  // will end with \0\0
128 #define FUNC_NAME(req_inst, req_dev, ext_flag, name) "vk"#name"\0"
129  const char *name =
131 #ifdef _WIN32
133 #endif
134  ;
135 #undef FUNC_NAME
136 
137  for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); name += strlen(name) + 1, i++) {
138  const struct FunctionLoadInfo *load = &vk_load_info[i];
139  static const char extensions[][4] = { "", "EXT", "KHR" };
140  PFN_vkVoidFunction fn;
141 
142  if (load->req_dev && !has_dev)
143  continue;
144  if (load->req_inst && !has_inst)
145  continue;
146 
147  for (int j = 0; j < FF_ARRAY_ELEMS(extensions); j++) {
148  char ext_name[128];
149  av_unused int n;
150 
151  n = snprintf(ext_name, sizeof(ext_name), "%s%s", name, extensions[j]);
152  av_assert1(n < sizeof(ext_name));
153 
154  if (load->req_dev)
155  fn = vk->GetDeviceProcAddr(hwctx->act_dev, ext_name);
156  else if (load->req_inst)
157  fn = hwctx->get_proc_addr(hwctx->inst, ext_name);
158  else
159  fn = hwctx->get_proc_addr(NULL, ext_name);
160 
161  if (fn)
162  break;
163  }
164 
165  if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) {
166  av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated "
167  "as supported, but got NULL function pointer!\n", name);
168  return AVERROR_EXTERNAL;
169  }
170 
171  *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn;
172  }
173  av_assert1(*name == '\0');
174 
175  return 0;
176 }
177 
178 #endif /* AVUTIL_VULKAN_LOADER_H */
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
FFVulkanExtensions
uint64_t FFVulkanExtensions
Definition: vulkan_functions.h:29
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:52
FF_VK_EXT_VIDEO_MAINTENANCE_2
#define FF_VK_EXT_VIDEO_MAINTENANCE_2
Definition: vulkan_functions.h:54
av_unused
#define av_unused
Definition: attributes.h:131
mask
int mask
Definition: mediacodecdec_common.c:154
FF_VK_EXT_VIDEO_DECODE_H265
#define FF_VK_EXT_VIDEO_DECODE_H265
Definition: vulkan_functions.h:58
AVVulkanDeviceContext::get_proc_addr
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
Definition: hwcontext_vulkan.h:69
AVVulkanDeviceContext::inst
VkInstance inst
Vulkan instance.
Definition: hwcontext_vulkan.h:74
FF_VK_EXT_COOP_MATRIX
#define FF_VK_EXT_COOP_MATRIX
Definition: vulkan_functions.h:45
FF_VK_EXT_EXTERNAL_FD_SEM
#define FF_VK_EXT_EXTERNAL_FD_SEM
Definition: vulkan_functions.h:35
FF_VK_EXT_VIDEO_ENCODE_H265
#define FF_VK_EXT_VIDEO_ENCODE_H265
Definition: vulkan_functions.h:63
FF_VK_EXT_EXTERNAL_WIN32_SEM
#define FF_VK_EXT_EXTERNAL_WIN32_SEM
Definition: vulkan_functions.h:40
FN_LIST_WIN32
#define FN_LIST_WIN32(MACRO)
Definition: vulkan_functions.h:256
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
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:108
PFN_LOAD_INFO
#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name)
Definition: vulkan_loader.h:28
FN_LIST
#define FN_LIST(MACRO)
Definition: vulkan_functions.h:69
FF_VK_EXT_DEVICE_DRM
#define FF_VK_EXT_DEVICE_DRM
Definition: vulkan_functions.h:43
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
NULL
#define NULL
Definition: coverity.c:32
FF_VK_EXT_DRM_MODIFIER_FLAGS
#define FF_VK_EXT_DRM_MODIFIER_FLAGS
Definition: vulkan_functions.h:33
FF_VK_EXT_SHADER_OBJECT
#define FF_VK_EXT_SHADER_OBJECT
Definition: vulkan_functions.h:47
FF_VK_EXT_VIDEO_ENCODE_QUEUE
#define FF_VK_EXT_VIDEO_ENCODE_QUEUE
Definition: vulkan_functions.h:61
FF_VK_EXT_VIDEO_MAINTENANCE_1
#define FF_VK_EXT_VIDEO_MAINTENANCE_1
Definition: vulkan_functions.h:53
FF_VK_EXT_EXTERNAL_DMABUF_MEMORY
#define FF_VK_EXT_EXTERNAL_DMABUF_MEMORY
Definition: vulkan_functions.h:32
FF_VK_EXT_NO_FLAG
#define FF_VK_EXT_NO_FLAG
Definition: vulkan_functions.h:66
FF_VK_EXT_PUSH_DESCRIPTOR
#define FF_VK_EXT_PUSH_DESCRIPTOR
Definition: vulkan_functions.h:48
fn
#define fn(a)
Definition: aap_template.c:37
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
FF_VK_EXT_VIDEO_DECODE_QUEUE
#define FF_VK_EXT_VIDEO_DECODE_QUEUE
Definition: vulkan_functions.h:56
FF_VK_EXT_EXTERNAL_HOST_MEMORY
#define FF_VK_EXT_EXTERNAL_HOST_MEMORY
Definition: vulkan_functions.h:36
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:57
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
FF_VK_EXT_EXTERNAL_FD_MEMORY
#define FF_VK_EXT_EXTERNAL_FD_MEMORY
Definition: vulkan_functions.h:34
flag
#define flag(name)
Definition: cbs_av1.c:495
FF_VK_EXT_DESCRIPTOR_BUFFER
#define FF_VK_EXT_DESCRIPTOR_BUFFER
Definition: vulkan_functions.h:42
vulkan_functions.h
FF_VK_EXT_ATOMIC_FLOAT
#define FF_VK_EXT_ATOMIC_FLOAT
Definition: vulkan_functions.h:44
FUNC_NAME
#define FUNC_NAME(req_inst, req_dev, ext_flag, name)
FF_VK_EXT_VIDEO_DECODE_AV1
#define FF_VK_EXT_VIDEO_DECODE_AV1
Definition: vulkan_functions.h:59
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
FF_VK_EXT_VIDEO_ENCODE_H264
#define FF_VK_EXT_VIDEO_ENCODE_H264
Definition: vulkan_functions.h:62
FF_VK_EXT_OPTICAL_FLOW
#define FF_VK_EXT_OPTICAL_FLOW
Definition: vulkan_functions.h:46
FF_VK_EXT_DEBUG_UTILS
#define FF_VK_EXT_DEBUG_UTILS
Definition: vulkan_functions.h:37
ff_vk_extensions_to_mask
static uint64_t ff_vk_extensions_to_mask(const char *const *extensions, int nb_extensions)
Definition: vulkan_loader.h:36
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
snprintf
#define snprintf
Definition: snprintf.h:34
FFVulkanFunctions
Definition: vulkan_functions.h:265