From patchwork Sun May 10 10:51:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lynne X-Patchwork-Id: 19606 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:bac9:0:0:0:0:0 with SMTP id a9csp1068402ybk; Sun, 10 May 2020 03:51:48 -0700 (PDT) X-Google-Smtp-Source: APiQypIhbCYrXnQd9BTrRQKkSHNSo7KKOXjrZlvAbBoWG0F+vx4NrEKh3ZDJQ6FR/ULHfNFmoes9 X-Received: by 2002:a7b:c755:: with SMTP id w21mr25113527wmk.120.1589107908114; Sun, 10 May 2020 03:51:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589107908; cv=none; d=google.com; s=arc-20160816; b=xgs89yBKROTthLaFWV+TUnUS5LzQQYwmCtYnC6749hsuVMY+LTXvi8Rt7hQliWwL9p TNSVmjLFA0caYZLNXC9U/3eJFRoavPwy44tJWH7Cdk+r9LDLpkrL5s2a8rEt+/R3JJVe YlD9GQumXO1l16QWCrSj3ZV8za/tIu5JI/WESPDykbysk7ek4ZgPO7948iovkzfus+wq 59+369xquMyBbjM5wcKaLJPh4IITZP+uRLcBc7Iap8K7eWIV46jOAC2yVbd52XP2wRM9 dUcAmhbsHguuwvLonI7x5tp0xZsQBxmvcR8EM18tWg49alu1/AbKbaQFj7Lum2QO7y7p o+zw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:to:from:date:dkim-signature:delivered-to; bh=cCvC2tiS3EFDQfh4Ml96OIGP2rIu4cHmuGjBpYOKN80=; b=BhBbu3LZoE6dxzQqXBgkJ+oey6jd6h1ChG6IdANTKUIYPPwHAycJ8n/62Feo+QSZeQ wDwoXH47NQnkyKe+gThZtkhO/VpiDzmqpIs2tIgketY67nUfqzM/QaI8Yftd0QcLK2oQ 9NBwRerjsjrLtsMO3TUTRCDDdnwmSufCb47EJu0poZUhJRGpbdKxsOmkP7FDFz49c4XQ qMslCOfutAAk/5Z0YG+m6bVAt6ssLuYdyrfVSoFskZSVqGstWLCjpOU68eIO6PT21Gd4 NNtrSAAt81mFyYElIlXzgmhFrmO0wWKDEc/ZiO/lnYiE7E4lKsunPg1F5zjMxb4+fEhN 4l5Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@lynne.ee header.s=s1 header.b=iQeu2Q9Z; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=lynne.ee Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id i21si5483192wmb.33.2020.05.10.03.51.47; Sun, 10 May 2020 03:51:48 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@lynne.ee header.s=s1 header.b=iQeu2Q9Z; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=lynne.ee Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 462536882E8; Sun, 10 May 2020 13:51:44 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from w4.tutanota.de (w4.tutanota.de [81.3.6.165]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 500876808E9 for ; Sun, 10 May 2020 13:51:37 +0300 (EEST) Received: from w3.tutanota.de (unknown [192.168.1.164]) by w4.tutanota.de (Postfix) with ESMTP id DE70310602CB for ; Sun, 10 May 2020 10:51:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1589107896; s=s1; d=lynne.ee; h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender; bh=+CHSASbTo5Y/0Si0/BbWBPUX/kvnPxeVLGO7B6v0Z78=; b=iQeu2Q9ZmE2ZdL1Soc60LL18IYoSrf8VJDUTZGe8uiQF/G7IpinUa2iUdJN8GkWL zDxCapGI9beBSsZRCbyj4x6I2pB1ifFgPZENikPBsKZiVRaXcUQSfGILHLkfnLK0JsU bS0ZLXTS91FDj6eZCN/Y8CqqdKOq5hVJAjQIjZppaesIkCbxi3ME2bqRzBISRkcD6wg +h45UC71YUHug8IDOt9ZCgkuvUC+8/b3Hrc3eBlH88V4rmX6cgIPbbGfKz4Tzw2GzX4 mHnrYlcIERfikFy92FSa8b1maF13agX2UQZij+VnSvGvdEQsX31AdJFGJ5vV47inu2u xZq1b+DXyQ== Date: Sun, 10 May 2020 12:51:36 +0200 (CEST) From: Lynne To: Ffmpeg Devel Message-ID: MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] hwcontext_vulkan: let users enable device and instance extensions using options X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: xwJpH5L1X1mx Content-Length: 6470 Also documents all options supported by the hwdevice. This lets users enable all extensions they need without writing their own instance initialization code. Patch attached. Subject: [PATCH 1/2] hwcontext_vulkan: let users enable device and instance extensions using options Also documents all options supported by the hwdevice. This lets users enable all extensions they need without writing their own instance initialization code. --- doc/ffmpeg.texi | 15 +++++++++++++++ libavutil/hwcontext_vulkan.c | 31 ++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 29753f06ca..d2a30fc868 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -1034,6 +1034,18 @@ If @var{device} is an integer, it selects the device by its index in a system-dependent list of devices. If @var{device} is any other string, it selects the first device with a name containing that string as a substring. +The following options are recognized: +@table @option +@item debug +If set to 1, enables the validation layer, if installed. +@item linear_images +If set to 1, images allocated by the hwcontext will be linear and locally mappable. +@item instance_extensions +A vertical bar separated list of additional instance extensions to enable. +@item device_extensions +A vertical bar separated list of additional device extensions to enable. +@end table + Examples: @table @emph @item -init_hw_device vulkan:1 @@ -1041,6 +1053,9 @@ Choose the second device on the system. @item -init_hw_device vulkan:RADV Choose the first device with a name containing the string @emph{RADV}. + +@item -init_hw_device vulkan:0,instance_extensions=VK_KHR_wayland_surface|VK_KHR_xcb_surface +Choose the first device and enable the Wayland and XCB instance extensions. @end table @end table diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 43e7cddbc5..a35c1d3a4f 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -261,7 +261,7 @@ static VkBool32 vk_dbg_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, return 0; } -static int check_extensions(AVHWDeviceContext *ctx, int dev, +static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char * const **dst, uint32_t *num, int debug) { const char *tstr; @@ -274,12 +274,14 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, int optional_exts_num; uint32_t sup_ext_count; VkExtensionProperties *sup_ext; + AVDictionaryEntry *user_exts = NULL; const VulkanOptExtension *optional_exts; if (!dev) { mod = "instance"; optional_exts = optional_instance_exts; optional_exts_num = FF_ARRAY_ELEMS(optional_instance_exts); + user_exts = av_dict_get(opts, "instance_extensions", NULL, 0); vkEnumerateInstanceExtensionProperties(NULL, &sup_ext_count, NULL); sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties)); if (!sup_ext) @@ -289,6 +291,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, mod = "device"; optional_exts = optional_device_exts; optional_exts_num = FF_ARRAY_ELEMS(optional_device_exts); + user_exts = av_dict_get(opts, "device_extensions", NULL, 0); vkEnumerateDeviceExtensionProperties(hwctx->phys_dev, NULL, &sup_ext_count, NULL); sup_ext = av_malloc_array(sup_ext_count, sizeof(VkExtensionProperties)); @@ -345,6 +348,28 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, } } + if (user_exts) { + char *save, *token = av_strtok(user_exts->value, "|", &save); + while (token) { + found = 0; + for (int j = 0; j < sup_ext_count; j++) { + if (!strcmp(token, sup_ext[j].extensionName)) { + found = 1; + break; + } + } + if (found) { + ADD_VAL_TO_LIST(extension_names, extensions_found, token); + } else { + av_log(ctx, AV_LOG_ERROR, "%s extension \"%s\" not found!\n", + mod, token); + err = AVERROR(EINVAL); + goto end; + } + token = av_strtok(NULL, "|", &save); + } + } + *dst = extension_names; *num = extensions_found; @@ -376,7 +401,7 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) }; /* Check for present/missing extensions */ - err = check_extensions(ctx, 0, &inst_props.ppEnabledExtensionNames, + err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames, &inst_props.enabledExtensionCount, debug_mode); if (err < 0) return err; @@ -777,7 +802,7 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if ((err = search_queue_families(ctx, &dev_info))) goto end; - if ((err = check_extensions(ctx, 1, &dev_info.ppEnabledExtensionNames, + if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames, &dev_info.enabledExtensionCount, 0))) goto end; From patchwork Sun May 10 10:54:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lynne X-Patchwork-Id: 19605 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:bac9:0:0:0:0:0 with SMTP id a9csp1069802ybk; Sun, 10 May 2020 03:54:44 -0700 (PDT) X-Google-Smtp-Source: APiQypJpeKBmiMLekWg6H0R5d6pWwhgtfOG4bHp/KYnJc7OiHAU85z8LvWROREGRmO6UpQO5lJR9 X-Received: by 2002:a5d:6ac1:: with SMTP id u1mr12864781wrw.319.1589108083997; Sun, 10 May 2020 03:54:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1589108083; cv=none; d=google.com; s=arc-20160816; b=qdt2xku1ZSx0XPnGlPemXFiV14Dy1IBFtr+ItNm7f8dkbEWu5BMuEg8KIx0gk0ErF/ 0ut3NTxelWlZmHtGAt6ZF1l4JgoZE4VeR4xWfZ9QlZzfXInNTsnYt/69b6AznySwNeuK T5+GjAiFpHOL4vNjQpurrvfwGFBwnsLjqFgdyXPrGzb6ShyjJP+SbrVigO3Rk40OhnU/ kZlrWqeBH2xf6I8cckk8KQEH8xwN/wptdyEhUVXflk/SRgEHPQnm135cI/KvP+GUw9wV U0lxsyyeiGHyQVqVmHu7M9007Hy1HBorKQ0itjqFdD+43+lR1E+f+Uncvru+H56rlvJ7 PXNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject :mime-version:message-id:to:from:date:dkim-signature:delivered-to; bh=kvbcHN7hzQom6DtRJ0o1oAYNvpXXIXQvYF1cLgTep1A=; b=kTIuzAo1xQalN13CjBgoieP/Qg4ra86aBYmyDBIE1zRSPLMXCSxAapBkaqBNkdY6F5 TnLUwebAmOmJsvqJPBEKePRExxeeh6ibwhImfUwr5iA2HfSbEJ9FXvTCptB7lewn/JNx oE4lEOToqQEhTeeAQVyXhsVpsBOjWErsAXL1u34nF9ADi4Bq5zwoEFfORe3AjQ/cTSi6 h6N8iqBc6uZvXw7h0CqMslod9aZ3G9SIwGmZX+Euae528a1m/lWpXCWi6dxMMx4wgih2 JKV/qtZQ2aJ9A3nPHeie2OmBoZH99I1PDUEFyBblXWw9K/T3tHISvNU1J7g/DAtKCxA2 lKOg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@lynne.ee header.s=s1 header.b=McACPkuT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=lynne.ee Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y17si6718158wrr.464.2020.05.10.03.54.43; Sun, 10 May 2020 03:54:43 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@lynne.ee header.s=s1 header.b=McACPkuT; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=lynne.ee Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 77E056882EB; Sun, 10 May 2020 13:54:40 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from w4.tutanota.de (w4.tutanota.de [81.3.6.165]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3CF9A68816F for ; Sun, 10 May 2020 13:54:34 +0300 (EEST) Received: from w3.tutanota.de (unknown [192.168.1.164]) by w4.tutanota.de (Postfix) with ESMTP id DEA0D106029E for ; Sun, 10 May 2020 10:54:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; t=1589108073; s=s1; d=lynne.ee; h=From:From:To:To:Subject:Subject:Content-Description:Content-ID:Content-Type:Content-Type:Content-Transfer-Encoding:Cc:Date:Date:In-Reply-To:MIME-Version:MIME-Version:Message-ID:Message-ID:Reply-To:References:Sender; bh=ldTVBQoDRFyyl9stfiiTZpNIetS9dSWo434gbh4cgog=; b=McACPkuTyX0GXpNJdODSUk/Qm+EXihsDQa9+VKvW3GvicINh09jDf5IfM7fmfBXz 65/MaPYrywQT+PBFBs4Lyjl8ve8xx3bVCcl4AUNdMRhAcZHX4AeliL3FhO69kD00h2p Ky7c3/4wJ2DzGQVv7ndggqIlBjMwqtTk2t4aePbbgETdCfeTYFiWSp3fA01z/kbi8Ct QLB3SrfgvvYwxC3WUGUxA88y3QHGlzlLUZeYN5mW5dW4IhECKjQ4OgyVJfkgoHdjV6M y+jg9b175eSz9C6c/xkmECf9oNfnFXCXt8O4Bpqpl8uNz/sANWyyWUNGMO3wV4f1Sok 2b6MBzxMCA== Date: Sun, 10 May 2020 12:54:33 +0200 (CEST) From: Lynne To: Ffmpeg Devel Message-ID: MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2] hwcontext_vulkan: expose enabled device and instance extensions X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: HWj7c2FIVovd Content-Length: 6079 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. Patch attached. This, and the previous patch to enable extensions through the options are really needed to make the hwcontext useful and interoperable with other Vulkan API users, so I'm planning to push them later tonight. Subject: [PATCH 2/2] 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. --- libavutil/hwcontext_vulkan.c | 27 ++++++++++++++++++++++----- libavutil/hwcontext_vulkan.h | 12 ++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index a35c1d3a4f..4135cc5209 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -415,13 +415,11 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) /* Try to create the instance */ ret = vkCreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); - /* Free used memory */ - 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)); + av_free((void *)inst_props.ppEnabledExtensionNames); return AVERROR_EXTERNAL; } @@ -444,6 +442,9 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) hwctx->alloc, &p->debug_ctx); } + hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; + hwctx->num_enabled_inst_extensions = inst_props.enabledExtensionCount; + return 0; } @@ -749,6 +750,9 @@ static void vulkan_device_free(AVHWDeviceContext *ctx) } vkDestroyInstance(hwctx->inst, hwctx->alloc); + + av_free((void *)hwctx->enabled_inst_extensions); + av_free((void *)hwctx->enabled_dev_extensions); } static int vulkan_device_create_internal(AVHWDeviceContext *ctx, @@ -809,11 +813,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, ret = vkCreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc, &hwctx->act_dev); - av_free((void *)dev_info.ppEnabledExtensionNames); - if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", vk_ret2str(ret)); + av_free((void *)dev_info.ppEnabledExtensionNames); err = AVERROR_EXTERNAL; goto end; } @@ -823,6 +826,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->num_enabled_dev_extensions = dev_info.enabledExtensionCount; + end: return err; } @@ -834,6 +840,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->num_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..2f9f92a3a2 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -42,6 +42,11 @@ typedef struct AVVulkanDeviceContext { * Instance */ VkInstance inst; + /** + * Enabled instance extensions. By default, VK_KHR_surface is enabled if found. + */ + const char * const *enabled_inst_extensions; + int num_enabled_inst_extensions; /** * Physical device */ @@ -50,6 +55,13 @@ typedef struct AVVulkanDeviceContext { * Active device */ VkDevice act_dev; + /** + * 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. + */ + const char * const *enabled_dev_extensions; + int num_enabled_dev_extensions; /** * Queue family index for graphics * @note av_hwdevice_create() will set all 3 queue indices if unset