PR #21121 opened by cgutman URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21121 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21121.patch
Applications that initialize Vulkan themselves (perhaps via libplacebo or other libraries) don't currently have a way to identify the optional device/instance extensions that FFmpeg might be able to use. Instead, they have to resort to keeping a hardcoded list, like `ffplay` does, which is fragile and hinders further use of newer extensions in FFmpeg. Even the in-tree `ffplay` tool is already out of sync with `hwcontext_vulkan.c` (using `"VK_MESA_video_decode_av1"` instead of `VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME`, among others). This PR adds new APIs to query these optional device/instance extensions and replaces the hardcoded device extension list in `ffplay`. >From 4344accd80d5e145da2c655800d359e422c60b19 Mon Sep 17 00:00:00 2001 From: Cameron Gutman <[email protected]> Date: Sun, 7 Dec 2025 13:51:05 -0600 Subject: [PATCH 1/2] hwcontext_vulkan: add APIs to get optional extensions These provide a way for apps that initialize Vulkan themselves to know which extensions we may be able to use without having to hardcode it. Signed-off-by: Cameron Gutman <[email protected]> --- libavutil/hwcontext_vulkan.c | 32 ++++++++++++++++++++++++++++++++ libavutil/hwcontext_vulkan.h | 18 ++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a120e6185c..c3e57744af 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -693,6 +693,38 @@ static const VulkanOptExtension optional_device_exts[] = { { VK_KHR_VIDEO_DECODE_AV1_EXTENSION_NAME, FF_VK_EXT_VIDEO_DECODE_AV1 }, }; +const char **av_vk_get_optional_instance_extensions(int* count) +{ + const char **exts = av_malloc_array(sizeof(*exts), + FF_ARRAY_ELEMS(optional_instance_exts)); + if (!exts) { + return NULL; + } + + for (int i = 0; i < FF_ARRAY_ELEMS(optional_instance_exts); i++) { + exts[i] = optional_instance_exts[i].name; + } + + *count = FF_ARRAY_ELEMS(optional_instance_exts); + return exts; +} + +const char **av_vk_get_optional_device_extensions(int* count) +{ + const char **exts = av_malloc_array(sizeof(*exts), + FF_ARRAY_ELEMS(optional_device_exts)); + if (!exts) { + return NULL; + } + + for (int i = 0; i < FF_ARRAY_ELEMS(optional_device_exts); i++) { + exts[i] = optional_device_exts[i].name; + } + + *count = FF_ARRAY_ELEMS(optional_device_exts); + return exts; +} + static VkBool32 VKAPI_CALL vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *data, diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index 0bb536ab3f..8e741103f1 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -97,6 +97,8 @@ typedef struct AVVulkanDeviceContext { * 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. + * av_vk_get_optional_instance_extensions() can be used to enumerate extensions + * that FFmpeg may use if enabled. */ const char * const *enabled_inst_extensions; int nb_enabled_inst_extensions; @@ -108,6 +110,8 @@ typedef struct AVVulkanDeviceContext { * 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. + * av_vk_get_optional_device_extensions() can be used to enumerate extensions + * that FFmpeg may use if enabled. */ const char * const *enabled_dev_extensions; int nb_enabled_dev_extensions; @@ -375,4 +379,18 @@ AVVkFrame *av_vk_frame_alloc(void); */ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p); +/** + * Returns an array of optional Vulkan instance extensions that FFmpeg + * may use if enabled. + * @note Must be freed via av_free() + */ +const char **av_vk_get_optional_instance_extensions(int* count); + +/** + * Returns an array of optional Vulkan device extensions that FFmpeg + * may use if enabled. + * @note Must be freed via av_free() + */ +const char **av_vk_get_optional_device_extensions(int* count); + #endif /* AVUTIL_HWCONTEXT_VULKAN_H */ -- 2.49.1 >From f176e1d6558c671608bffa5d7d4f98548aee8eb1 Mon Sep 17 00:00:00 2001 From: Cameron Gutman <[email protected]> Date: Sun, 7 Dec 2025 13:57:42 -0600 Subject: [PATCH 2/2] fftools/ffplay_renderer: use new Vulkan extension API Signed-off-by: Cameron Gutman <[email protected]> --- fftools/ffplay_renderer.c | 41 +++++++++------------------------------ 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/fftools/ffplay_renderer.c b/fftools/ffplay_renderer.c index 699cd6ecd0..1321452ad8 100644 --- a/fftools/ffplay_renderer.c +++ b/fftools/ffplay_renderer.c @@ -104,36 +104,6 @@ static void vk_log_cb(void *log_priv, enum pl_log_level level, av_log(log_priv, level_map[level], "%s\n", msg); } -// Should keep sync with optional_device_exts inside hwcontext_vulkan.c -static const char *optional_device_exts[] = { - /* Misc or required by other extensions */ - VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME, - VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, - VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, - VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME, - VK_EXT_PHYSICAL_DEVICE_DRM_EXTENSION_NAME, - VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME, - VK_KHR_COOPERATIVE_MATRIX_EXTENSION_NAME, - - /* Imports/exports */ - VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, - VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, - VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, - VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, - VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, -#ifdef _WIN32 - VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, - VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, -#endif - - /* Video encoding/decoding */ - VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, - VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, - VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME, - VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME, - "VK_MESA_video_decode_av1", -}; - static inline int enable_debug(const AVDictionary *opt) { AVDictionaryEntry *entry = av_dict_get(opt, "debug", NULL, 0); @@ -374,6 +344,8 @@ static int create_vk_by_placebo(VkRenderer *renderer, int decode_index; int decode_count; int ret; + const char **dev_exts; + int num_dev_exts; ctx->get_proc_addr = SDL_Vulkan_GetVkGetInstanceProcAddr(); @@ -388,16 +360,21 @@ static int create_vk_by_placebo(VkRenderer *renderer, } ctx->inst = ctx->placebo_instance->instance; + dev_exts = av_vk_get_optional_device_extensions(&num_dev_exts); + if (!dev_exts) + return AVERROR(ENOMEM); + ctx->placebo_vulkan = pl_vulkan_create(ctx->vk_log, pl_vulkan_params( .instance = ctx->placebo_instance->instance, .get_proc_addr = ctx->placebo_instance->get_proc_addr, .surface = ctx->vk_surface, .allow_software = false, - .opt_extensions = optional_device_exts, - .num_opt_extensions = FF_ARRAY_ELEMS(optional_device_exts), + .opt_extensions = dev_exts, + .num_opt_extensions = num_dev_exts, .extra_queues = VK_QUEUE_VIDEO_DECODE_BIT_KHR, .device_name = select_device(opt), )); + av_free(dev_exts); if (!ctx->placebo_vulkan) return AVERROR_EXTERNAL; ctx->hw_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VULKAN); -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
