diff options
-rw-r--r-- | libavutil/hwcontext_vulkan.c | 293 | ||||
-rw-r--r-- | libavutil/vulkan_functions.h | 162 | ||||
-rw-r--r-- | libavutil/vulkan_loader.h | 128 |
3 files changed, 357 insertions, 226 deletions
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 7281336d73..93a304ca95 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -30,6 +30,8 @@ #include "hwcontext_internal.h" #include "hwcontext_vulkan.h" +#include "vulkan_loader.h" + #ifdef _WIN32 #include "compat/w32dlfcn.h" #else @@ -52,126 +54,6 @@ #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) #endif -enum VulkanExtensions { - EXT_EXTERNAL_DMABUF_MEMORY = 1 << 0, /* VK_EXT_external_memory_dma_buf */ - EXT_DRM_MODIFIER_FLAGS = 1 << 1, /* VK_EXT_image_drm_format_modifier */ - EXT_EXTERNAL_FD_MEMORY = 1 << 2, /* VK_KHR_external_memory_fd */ - EXT_EXTERNAL_FD_SEM = 1 << 3, /* VK_KHR_external_semaphore_fd */ - EXT_EXTERNAL_HOST_MEMORY = 1 << 4, /* VK_EXT_external_memory_host */ - EXT_DEBUG_UTILS = 1 << 5, /* VK_EXT_debug_utils */ - - EXT_NO_FLAG = 1 << 31, -}; - -#define FN_LIST(MACRO) \ - /* Instance */ \ - MACRO(0, 0, EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ - MACRO(0, 0, EXT_NO_FLAG, CreateInstance) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyInstance) \ - \ - /* Debug */ \ - MACRO(1, 0, EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ - \ - /* Device */ \ - MACRO(1, 0, EXT_NO_FLAG, GetDeviceProcAddr) \ - MACRO(1, 0, EXT_NO_FLAG, CreateDevice) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDevice) \ - \ - MACRO(1, 0, EXT_NO_FLAG, EnumeratePhysicalDevices) \ - MACRO(1, 0, EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ - \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ - \ - /* Command pool */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateCommandPool) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyCommandPool) \ - \ - /* Command buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, AllocateCommandBuffers) \ - MACRO(1, 1, EXT_NO_FLAG, BeginCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, EndCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, FreeCommandBuffers) \ - \ - /* Queue */ \ - MACRO(1, 1, EXT_NO_FLAG, GetDeviceQueue) \ - MACRO(1, 1, EXT_NO_FLAG, QueueSubmit) \ - \ - /* Fences */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateFence) \ - MACRO(1, 1, EXT_NO_FLAG, WaitForFences) \ - MACRO(1, 1, EXT_NO_FLAG, ResetFences) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyFence) \ - \ - /* Semaphores */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, CreateSemaphore) \ - MACRO(1, 1, EXT_NO_FLAG, WaitSemaphores) \ - MACRO(1, 1, EXT_NO_FLAG, DestroySemaphore) \ - \ - /* Memory */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ - MACRO(1, 1, EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, AllocateMemory) \ - MACRO(1, 1, EXT_NO_FLAG, MapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FlushMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, UnmapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FreeMemory) \ - \ - /* Commands */ \ - MACRO(1, 1, EXT_NO_FLAG, CmdPipelineBarrier) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyBufferToImage) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyImageToBuffer) \ - \ - /* Buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, GetBufferMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, BindBufferMemory) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyBuffer) \ - \ - /* Image */ \ - MACRO(1, 1, EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateImage) \ - MACRO(1, 1, EXT_NO_FLAG, BindImageMemory2) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageSubresourceLayout) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyImage) - -#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ - PFN_vk##name name; - -typedef struct VulkanFunctions { - FN_LIST(PFN_DEF) -} VulkanFunctions; - -#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \ - { \ - req_inst, \ - req_dev, \ - offsetof(VulkanFunctions, name), \ - ext_flag, \ - { "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \ - }, - -typedef struct VulkanFunctionsLoadInfo { - int req_inst; - int req_dev; - size_t struct_offset; - enum VulkanExtensions ext_flag; - const char *names[3]; -} VulkanFunctionsLoadInfo; - -static const VulkanFunctionsLoadInfo vk_load_info[] = { - FN_LIST(PFN_LOAD_INFO) -}; - typedef struct VulkanQueueCtx { VkFence fence; VkQueue queue; @@ -194,7 +76,7 @@ typedef struct VulkanExecCtx { typedef struct VulkanDevicePriv { /* Vulkan library and loader functions */ void *libvulkan; - VulkanFunctions vkfn; + FFVulkanFunctions vkfn; /* Properties */ VkPhysicalDeviceProperties2 props; @@ -213,7 +95,7 @@ typedef struct VulkanDevicePriv { VkDebugUtilsMessengerEXT debug_ctx; /* Extensions */ - enum VulkanExtensions extensions; + FFVulkanExtensions extensions; /* Settings */ int use_linear_images; @@ -349,7 +231,7 @@ static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, { AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *priv = dev_ctx->internal->priv; - VulkanFunctions *vk = &priv->vkfn; + FFVulkanFunctions *vk = &priv->vkfn; const VkFormat *fmt = av_vkfmt_from_pixfmt(p); int planes = av_pix_fmt_count_planes(p); @@ -405,50 +287,9 @@ static int load_libvulkan(AVHWDeviceContext *ctx) return 0; } -static int load_functions(AVHWDeviceContext *ctx, int has_inst, int has_dev) -{ - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; - - for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { - const VulkanFunctionsLoadInfo *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 && ((p->extensions &~ 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; -} - typedef struct VulkanOptExtension { const char *name; - enum VulkanExtensions flag; + FFVulkanExtensions flag; } VulkanOptExtension; static const VulkanOptExtension optional_instance_exts[] = { @@ -457,25 +298,25 @@ static const VulkanOptExtension optional_instance_exts[] = { static const VulkanOptExtension optional_device_exts[] = { /* Misc or required by other extensions */ - { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_HDR_METADATA_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_HDR_METADATA_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, /* Imports/exports */ - { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_MEMORY, }, - { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, EXT_EXTERNAL_DMABUF_MEMORY, }, - { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, EXT_DRM_MODIFIER_FLAGS, }, - { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_SEM, }, - { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, EXT_EXTERNAL_HOST_MEMORY, }, + { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, + { 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_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, + { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, /* Video encoding/decoding */ - { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, EXT_NO_FLAG, }, - { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, EXT_NO_FLAG, }, + { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, }; /* Converts return values to strings */ @@ -548,7 +389,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *tstr; const char **extension_names = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int err = 0, found, extensions_found = 0; @@ -627,7 +468,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, if (found) { av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); - p->extensions |= EXT_DEBUG_UTILS; + p->extensions |= FF_VK_EXT_DEBUG_UTILS; } else { av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n", tstr); @@ -680,7 +521,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) int err = 0; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); const int debug_mode = debug_opt && strtol(debug_opt->value, NULL, 10); @@ -703,7 +544,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return err; } - err = load_functions(ctx, 0, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 0, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n"); return err; @@ -734,7 +575,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return AVERROR_EXTERNAL; } - err = load_functions(ctx, 1, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n"); return err; @@ -791,7 +632,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) uint32_t num; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkPhysicalDevice *devices = NULL; VkPhysicalDeviceIDProperties *idp = NULL; VkPhysicalDeviceProperties2 *prop = NULL; @@ -943,7 +784,7 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) float *weights; VkQueueFamilyProperties *qf = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int graph_index, comp_index, tx_index, enc_index, dec_index; @@ -1070,7 +911,7 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkResult ret; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandPoolCreateInfo cqueue_create = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -1126,7 +967,7 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) { AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; if (cmd->queues) { for (int i = 0; i < cmd->nb_queues; i++) { @@ -1179,7 +1020,7 @@ static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandBufferBeginInfo cmd_start = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -1252,7 +1093,7 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkResult ret; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ret = vk->EndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); if (ret != VK_SUCCESS) { @@ -1292,7 +1133,7 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, static void vulkan_device_free(AVHWDeviceContext *ctx) { VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); @@ -1323,7 +1164,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkResult ret; AVDictionaryEntry *opt_d; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; VkPhysicalDeviceVulkan12Features dev_features_1_2 = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, @@ -1423,7 +1264,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) uint32_t queue_num; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int graph_index, comp_index, tx_index, enc_index, dec_index; /* Set device extension flags */ @@ -1437,7 +1278,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) } } - err = load_functions(ctx, 1, 1); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 1); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n"); return err; @@ -1455,7 +1296,7 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->props.properties.limits.optimalBufferCopyRowPitchAlignment); av_log(ctx, AV_LOG_VERBOSE, " minMemoryMapAlignment: %"SIZE_SPECIFIER"\n", p->props.properties.limits.minMemoryMapAlignment); - if (p->extensions & EXT_EXTERNAL_HOST_MEMORY) + if (p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n", p->hprops.minImportedHostPointerAlignment); @@ -1657,7 +1498,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkResult ret; int index = -1; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *dev_hwctx = ctx->hwctx; VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, @@ -1745,7 +1586,7 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) AVHWFramesContext *hwfc = opaque; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkSemaphoreWaitInfo wait_info = { @@ -1776,7 +1617,7 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; @@ -1853,7 +1694,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VkAccessFlags new_access; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; @@ -1956,7 +1797,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; enum AVPixelFormat format = hwfc->sw_format; const VkFormat *img_fmts = av_vkfmt_from_pixfmt(format); @@ -1969,7 +1810,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkSemaphoreTypeCreateInfo sem_type_info = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, - .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, .initialValue = 0, }; @@ -2053,7 +1894,7 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanFramesContext *hwctx = hwfc->hwctx; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -2100,11 +1941,11 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) .pNext = hwctx->create_pnext, }; - if (p->extensions & EXT_EXTERNAL_FD_MEMORY) + if (p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); @@ -2242,7 +2083,7 @@ static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; /* Check if buffer needs flushing */ if ((map->flags & AV_HWFRAME_MAP_WRITE) && @@ -2279,7 +2120,7 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanMapping *map = av_mallocz(sizeof(VulkanMapping)); if (!map) @@ -2369,7 +2210,7 @@ static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; for (int i = 0; i < planes; i++) { vk->DestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); @@ -2414,7 +2255,7 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f AVHWDeviceContext *ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; @@ -2763,7 +2604,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data; AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; @@ -2985,13 +2826,13 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); #endif case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3032,7 +2873,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, VkResult ret; AVVkFrame *f = (AVVkFrame *)src->data[0]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); @@ -3156,13 +2997,13 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_LIBDRM case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_drm(hwfc, dst, src, flags); else return AVERROR(ENOSYS); #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & (EXT_EXTERNAL_DMABUF_MEMORY | EXT_DRM_MODIFIER_FLAGS)) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_vaapi(hwfc, dst, src, flags); else return AVERROR(ENOSYS); @@ -3185,7 +3026,7 @@ static void free_buf(void *opaque, uint8_t *data) AVHWDeviceContext *ctx = opaque; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ImageBuffer *vkbuf = (ImageBuffer *)data; if (vkbuf->buf) @@ -3215,7 +3056,7 @@ static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, int use_ded_mem; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkBufferCreateInfo buf_spawn = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -3302,7 +3143,7 @@ static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[ VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange invalidate_ctx[AV_NUM_DATA_POINTERS]; int invalidate_count = 0; @@ -3361,7 +3202,7 @@ static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange flush_ctx[AV_NUM_DATA_POINTERS]; int flush_count = 0; @@ -3410,7 +3251,7 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, AVVkFrame *frame = (AVVkFrame *)f->data[0]; VulkanFramesPriv *fp = hwfc->internal->priv; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int bar_num = 0; VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; @@ -3540,7 +3381,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, AVHWDeviceContext *dev_ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVFrame tmp; AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; @@ -3550,7 +3391,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, const int planes = av_pix_fmt_count_planes(swf->format); int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; - const int map_host = !!(p->extensions & EXT_EXTERNAL_HOST_MEMORY); + const int map_host = !!(p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY); if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) { av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n"); @@ -3696,8 +3537,8 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, switch (src->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif default: @@ -3811,8 +3652,8 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif default: diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h new file mode 100644 index 0000000000..de2054e0c2 --- /dev/null +++ b/libavutil/vulkan_functions.h @@ -0,0 +1,162 @@ +/* + * 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_FUNCTIONS_H +#define AVUTIL_VULKAN_FUNCTIONS_H + +/* An enum of bitflags for every optional extension we need */ +typedef enum FFVulkanExtensions { + FF_VK_EXT_EXTERNAL_DMABUF_MEMORY = 1ULL << 0, /* VK_EXT_external_memory_dma_buf */ + FF_VK_EXT_DRM_MODIFIER_FLAGS = 1ULL << 1, /* VK_EXT_image_drm_format_modifier */ + FF_VK_EXT_EXTERNAL_FD_MEMORY = 1ULL << 2, /* VK_KHR_external_memory_fd */ + FF_VK_EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ + FF_VK_EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ + FF_VK_EXT_DEBUG_UTILS = 1ULL << 5, /* VK_EXT_debug_utils */ + + FF_VK_EXT_NO_FLAG = 1ULL << 63, +} FFVulkanExtensions; + +/* Macro containing every function that we utilize in our codebase */ +#define FN_LIST(MACRO) \ + /* Instance */ \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, CreateInstance) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyInstance) \ + \ + /* Debug */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ + \ + /* Device */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetDeviceProcAddr) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDevice) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDevice) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumeratePhysicalDevices) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ + \ + /* Command pool */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateCommandPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyCommandPool) \ + \ + /* Command buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BeginCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, EndCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdDispatch) \ + \ + /* Queue */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetDeviceQueue) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, QueueSubmit) \ + \ + /* Fences */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateFence) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitForFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, ResetFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyFence) \ + \ + /* Semaphores */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSemaphore) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitSemaphores) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySemaphore) \ + \ + /* Memory */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, MapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FlushMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UnmapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeMemory) \ + \ + /* Commands */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPushConstants) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindPipeline) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyBufferToImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyImageToBuffer) \ + \ + /* Buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetBufferMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindBufferMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyBuffer) \ + \ + /* Image */ \ + MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindImageMemory2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageSubresourceLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImage) \ + \ + /* ImageView */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImageView) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImageView) \ + \ + /* DescriptorSet */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorSetLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorSetLayout) \ + \ + /* DescriptorUpdateTemplate */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UpdateDescriptorSetWithTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorUpdateTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorUpdateTemplate) \ + \ + /* Pipeline */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipelineLayout) \ + \ + /* PipelineLayout */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateComputePipelines) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipeline) \ + \ + /* Sampler */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSampler) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySampler) \ + \ + /* Shaders */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateShaderModule) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) + +/* Macro to turn a function name into a definition */ +#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ + PFN_vk##name name; + +/* Structure with the definition of all listed functions */ +typedef struct FFVulkanFunctions { + FN_LIST(PFN_DEF) +} FFVulkanFunctions; + +#endif /* AVUTIL_VULKAN_FUNCTIONS_H */ diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h new file mode 100644 index 0000000000..838d26d271 --- /dev/null +++ b/libavutil/vulkan_loader.h @@ -0,0 +1,128 @@ +/* + * 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 } + }; + + 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) + }; + + 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 */ |