File size: 5,996 Bytes
8ead80b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVUTIL_VULKAN_LOADER_H
#define AVUTIL_VULKAN_LOADER_H
#include "vulkan_functions.h"
/* Macro to turn a function name into a loader struct */
#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \
{ \
req_inst, \
req_dev, \
offsetof(FFVulkanFunctions, name), \
ext_flag, \
{ "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \
},
static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions,
int nb_extensions)
{
static const struct ExtensionMap {
const char *name;
FFVulkanExtensions flag;
} extension_map[] = {
{ VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY },
{ VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS },
{ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY },
{ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM },
{ VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY },
{ VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS },
{ VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, FF_VK_EXT_DEVICE_DRM },
{ VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, FF_VK_EXT_ATOMIC_FLOAT },
{ VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, FF_VK_EXT_COOP_MATRIX },
#ifdef _WIN32
{ VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY },
{ VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM },
#endif
{ VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, FF_VK_EXT_DESCRIPTOR_BUFFER, },
{ VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_QUEUE },
{ VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_QUEUE },
{ VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H264 },
{ VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_H265 },
{ "VK_MESA_video_decode_av1", FF_VK_EXT_VIDEO_DECODE_AV1 },
};
FFVulkanExtensions mask = 0x0;
for (int i = 0; i < nb_extensions; i++) {
for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) {
if (!strcmp(extensions[i], extension_map[j].name)) {
mask |= extension_map[j].flag;
continue;
}
}
}
return mask;
}
/**
* Function loader.
* Vulkan function from scratch loading happens in 3 stages - the first one
* is before any initialization has happened, and you have neither an instance
* structure nor a device structure. At this stage, you can only get the bare
* minimals to initialize an instance.
* The second stage is when you have an instance. At this stage, you can
* initialize a VkDevice, and have an idea of what extensions each device
* supports.
* Finally, in the third stage, you can proceed and load all core functions,
* plus you can be sure that any extensions you've enabled during device
* initialization will be available.
*/
static inline int ff_vk_load_functions(AVHWDeviceContext *ctx,
FFVulkanFunctions *vk,
uint64_t extensions_mask,
int has_inst, int has_dev)
{
AVVulkanDeviceContext *hwctx = ctx->hwctx;
static const struct FunctionLoadInfo {
int req_inst;
int req_dev;
size_t struct_offset;
FFVulkanExtensions ext_flag;
const char *names[3];
} vk_load_info[] = {
FN_LIST(PFN_LOAD_INFO)
#ifdef _WIN32
FN_LIST_WIN32(PFN_LOAD_INFO)
#endif
};
for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) {
const struct FunctionLoadInfo *load = &vk_load_info[i];
PFN_vkVoidFunction fn;
if (load->req_dev && !has_dev)
continue;
if (load->req_inst && !has_inst)
continue;
for (int j = 0; j < FF_ARRAY_ELEMS(load->names); j++) {
const char *name = load->names[j];
if (load->req_dev)
fn = vk->GetDeviceProcAddr(hwctx->act_dev, name);
else if (load->req_inst)
fn = hwctx->get_proc_addr(hwctx->inst, name);
else
fn = hwctx->get_proc_addr(NULL, name);
if (fn)
break;
}
if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) {
av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated "
"as supported, but got NULL function pointer!\n", load->names[0]);
return AVERROR_EXTERNAL;
}
*(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn;
}
return 0;
}
#endif /* AVUTIL_VULKAN_LOADER_H */
|