From dccd07f66dfc236206bd37633a4666dbe666c0d5 Mon Sep 17 00:00:00 2001 From: Lynne Date: Sun, 10 May 2020 11:47:50 +0100 Subject: hwcontext_vulkan: expose enabled device and instance extensions This solves a huge oversight - it lets users reliably use their own AVVulkanDeviceContext. Otherwise, the extensions supplied and enabled are not discoverable by anything outside of hwcontext_vulkan. Also clarifies that any user-supplied VkInstance must be at least 1.1. --- doc/APIchanges | 4 ++++ libavutil/hwcontext_vulkan.c | 40 +++++++++++++++++++++++++++++++--------- libavutil/hwcontext_vulkan.h | 21 ++++++++++++++++++++- libavutil/version.h | 2 +- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index b3e7e89412..75cfdb08b0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,10 @@ libavutil: 2017-10-21 API changes, most recent first: +2020-05-10 - xxxxxxxxxx - lavu 56.44.100 - hwcontext_vulkan.h + Add enabled_inst_extensions, num_enabled_inst_extensions, enabled_dev_extensions + and num_enabled_dev_extensions fields to AVVulkanDeviceContext + 2020-04-22 - 0e1db79e37 - lavc 58.81.100 - packet.h - lavu 56.43.100 - dovi_meta.h Add AV_PKT_DATA_DOVI_CONF and AVDOVIDecoderConfigurationRecord. diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index cb805b0d1b..aca34a35a8 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -445,15 +445,13 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) /* Try to create the instance */ ret = vkCreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); - /* Free used memory */ - for (int i = 0; i < inst_props.enabledExtensionCount; i++) - av_free((void *)inst_props.ppEnabledExtensionNames[i]); - av_free((void *)inst_props.ppEnabledExtensionNames); - /* Check for errors */ if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n", vk_ret2str(ret)); + for (int i = 0; i < inst_props.enabledExtensionCount; i++) + av_free((void *)inst_props.ppEnabledExtensionNames[i]); + av_free((void *)inst_props.ppEnabledExtensionNames); return AVERROR_EXTERNAL; } @@ -476,6 +474,9 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) hwctx->alloc, &p->debug_ctx); } + hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; + hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; + return 0; } @@ -781,6 +782,14 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) } vkDestroyInstance(hwctx->inst, hwctx->alloc); + + for (int i = 0; i < hwctx->nb_enabled_inst_extensions; i++) + av_free((void *)hwctx->enabled_inst_extensions[i]); + av_free((void *)hwctx->enabled_inst_extensions); + + for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) + av_free((void *)hwctx->enabled_dev_extensions[i]); + av_free((void *)hwctx->enabled_dev_extensions); } static int vulkan_device_create_internal(AVHWDeviceContext *ctx, @@ -841,13 +850,12 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, ret = vkCreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc, &hwctx->act_dev); - for (int i = 0; i < dev_info.enabledExtensionCount; i++) - av_free((void *)dev_info.ppEnabledExtensionNames[i]); - av_free((void *)dev_info.ppEnabledExtensionNames); - if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", vk_ret2str(ret)); + for (int i = 0; i < dev_info.enabledExtensionCount; i++) + av_free((void *)dev_info.ppEnabledExtensionNames[i]); + av_free((void *)dev_info.ppEnabledExtensionNames); err = AVERROR_EXTERNAL; goto end; } @@ -857,6 +865,9 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; + hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; + end: return err; } @@ -868,6 +879,17 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; + /* Set device extension flags */ + for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) { + for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) { + if (!strcmp(hwctx->enabled_dev_extensions[i], + optional_device_exts[j].name)) { + p->extensions |= optional_device_exts[j].flag; + break; + } + } + } + vkGetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { av_log(ctx, AV_LOG_ERROR, "Failed to get queues!\n"); diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index ebc28916f3..7f921d7af1 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -39,7 +39,7 @@ typedef struct AVVulkanDeviceContext { */ const VkAllocationCallbacks *alloc; /** - * Instance + * Vulkan instance. Must be at least version 1.1. */ VkInstance inst; /** @@ -65,6 +65,25 @@ typedef struct AVVulkanDeviceContext { * Queue family index for compute ops */ int queue_family_comp_index; + /** + * Enabled instance extensions. By default, VK_KHR_surface is enabled if found. + * If supplying your own device context, set this to an array of strings, with + * each entry containing the specified Vulkan extension string to enable. + * Duplicates are possible and accepted. + * If no extensions are enabled, set these fields to NULL, and 0 respectively. + */ + const char * const *enabled_inst_extensions; + int nb_enabled_inst_extensions; + /** + * Enabled device extensions. By default, VK_KHR_external_memory_fd, + * VK_EXT_external_memory_dma_buf, VK_EXT_image_drm_format_modifier and + * VK_KHR_external_semaphore_fd are enabled if found. + * If supplying your own device context, these fields takes the same format as + * the above fields, with the same conditions that duplicates are possible + * and accepted, and that NULL and 0 respectively means no extensions are enabled. + */ + const char * const *enabled_dev_extensions; + int nb_enabled_dev_extensions; } AVVulkanDeviceContext; /** diff --git a/libavutil/version.h b/libavutil/version.h index ea9363e8e9..48d8a38c42 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 56 -#define LIBAVUTIL_VERSION_MINOR 43 +#define LIBAVUTIL_VERSION_MINOR 44 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ -- cgit v1.2.3