diff mbox series

[FFmpeg-devel,4/8] hwcontext_vulkan: move device feature struct setup to a new function

Message ID 20241003055141.415483-4-dev@lynne.ee
State New
Headers show
Series [FFmpeg-devel,1/8] vulkan: always enable GL_EXT_scalar_block_layout | expand

Checks

Context Check Description
yinshiyou/configure_loongarch64 warning Failed to apply patch
andriy/configure_x86 warning Failed to apply patch

Commit Message

Lynne Oct. 3, 2024, 5:51 a.m. UTC
---
 libavutil/hwcontext_vulkan.c | 335 ++++++++++++++++-------------------
 libavutil/vulkan_functions.h |   1 +
 2 files changed, 156 insertions(+), 180 deletions(-)
diff mbox series

Patch

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 518c3d642b..9b6a6274e4 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -72,6 +72,28 @@ 
 #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x)
 #endif
 
+typedef struct VulkanDeviceFeatures {
+    VkPhysicalDeviceFeatures2 device;
+
+    VkPhysicalDeviceVulkan11Features vulkan_1_1;
+    VkPhysicalDeviceVulkan12Features vulkan_1_2;
+    VkPhysicalDeviceVulkan13Features vulkan_1_3;
+    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore;
+
+    VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maintenance_1;
+
+    VkPhysicalDeviceShaderObjectFeaturesEXT shader_object;
+    VkPhysicalDeviceCooperativeMatrixFeaturesKHR cooperative_matrix;
+    VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptor_buffer;
+    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float;
+
+    VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow;
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instruction;
+#endif
+} VulkanDeviceFeatures;
+
 typedef struct VulkanDevicePriv {
     /**
      * The public AVVulkanDeviceContext. See hwcontext_vulkan.h for it.
@@ -90,19 +112,8 @@  typedef struct VulkanDevicePriv {
     VkPhysicalDeviceMemoryProperties mprops;
     VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops;
 
-    /* Features */
-    VkPhysicalDeviceVulkan11Features device_features_1_1;
-    VkPhysicalDeviceVulkan12Features device_features_1_2;
-    VkPhysicalDeviceVulkan13Features device_features_1_3;
-    VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features;
-    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features;
-    VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features;
-    VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow_features;
-    VkPhysicalDeviceShaderObjectFeaturesEXT shader_object_features;
-    VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maint_1_features;
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instr_features;
-#endif
+    /* Enabled features */
+    VulkanDeviceFeatures feats;
 
     /* Queues */
     pthread_mutex_t **qf_mutex;
@@ -164,6 +175,118 @@  typedef struct AVVkFrameInternal {
 #endif
 } AVVkFrameInternal;
 
+/* Initialize all structs in VulkanDeviceFeatures */
+static void device_features_init(AVHWDeviceContext *ctx, VulkanDeviceFeatures *feats)
+{
+    VulkanDevicePriv *p = ctx->hwctx;
+
+#define OPT_CHAIN(STRUCT_P, EXT_FLAG, TYPE)              \
+    do {                                                 \
+        if ((EXT_FLAG == FF_VK_EXT_NO_FLAG) ||           \
+            (p->vkctx.extensions & EXT_FLAG)) {          \
+            (STRUCT_P)->sType = TYPE;                    \
+            ff_vk_link_struct(&feats->device, STRUCT_P); \
+        }                                                \
+    } while (0)
+
+    feats->device = (VkPhysicalDeviceFeatures2) {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
+    };
+
+    OPT_CHAIN(&feats->vulkan_1_1, FF_VK_EXT_NO_FLAG,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES);
+    OPT_CHAIN(&feats->vulkan_1_2, FF_VK_EXT_NO_FLAG,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
+    OPT_CHAIN(&feats->vulkan_1_3, FF_VK_EXT_NO_FLAG,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES);
+
+    OPT_CHAIN(&feats->timeline_semaphore, FF_VK_EXT_PORTABILITY_SUBSET,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES);
+
+    OPT_CHAIN(&feats->video_maintenance_1, FF_VK_EXT_VIDEO_MAINTENANCE_1,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
+
+    OPT_CHAIN(&feats->shader_object, FF_VK_EXT_SHADER_OBJECT,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
+    OPT_CHAIN(&feats->cooperative_matrix, FF_VK_EXT_COOP_MATRIX,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
+    OPT_CHAIN(&feats->descriptor_buffer, FF_VK_EXT_DESCRIPTOR_BUFFER,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT);
+    OPT_CHAIN(&feats->atomic_float, FF_VK_EXT_ATOMIC_FLOAT,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
+
+#ifdef VK_KHR_shader_relaxed_extended_instruction
+    OPT_CHAIN(&feats->relaxed_extended_instruction, FF_VK_EXT_RELAXED_EXTENDED_INSTR,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR);
+#endif
+
+    OPT_CHAIN(&feats->optical_flow, FF_VK_EXT_OPTICAL_FLOW,
+              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV);
+#undef OPT_CHAIN
+}
+
+/* Copy all needed device features */
+static void device_features_copy_needed(VulkanDeviceFeatures *dst, VulkanDeviceFeatures *src)
+{
+#define COPY_VAL(VAL)        \
+    do {                     \
+        dst->VAL = src->VAL; \
+    } while (0)              \
+
+    COPY_VAL(device.features.shaderImageGatherExtended);
+    COPY_VAL(device.features.shaderStorageImageReadWithoutFormat);
+    COPY_VAL(device.features.shaderStorageImageWriteWithoutFormat);
+    COPY_VAL(device.features.fragmentStoresAndAtomics);
+    COPY_VAL(device.features.vertexPipelineStoresAndAtomics);
+    COPY_VAL(device.features.shaderInt64);
+    COPY_VAL(device.features.shaderInt16);
+    COPY_VAL(device.features.shaderFloat64);
+
+    COPY_VAL(vulkan_1_1.samplerYcbcrConversion);
+    COPY_VAL(vulkan_1_1.storagePushConstant16);
+    COPY_VAL(vulkan_1_1.storageBuffer16BitAccess);
+    COPY_VAL(vulkan_1_1.uniformAndStorageBuffer16BitAccess);
+
+    COPY_VAL(vulkan_1_2.timelineSemaphore);
+    COPY_VAL(vulkan_1_2.scalarBlockLayout);
+    COPY_VAL(vulkan_1_2.bufferDeviceAddress);
+    COPY_VAL(vulkan_1_2.hostQueryReset);
+    COPY_VAL(vulkan_1_2.storagePushConstant8);
+    COPY_VAL(vulkan_1_2.shaderInt8);
+    COPY_VAL(vulkan_1_2.storageBuffer8BitAccess);
+    COPY_VAL(vulkan_1_2.uniformAndStorageBuffer8BitAccess);
+    COPY_VAL(vulkan_1_2.shaderFloat16);
+    COPY_VAL(vulkan_1_2.shaderSharedInt64Atomics);
+    COPY_VAL(vulkan_1_2.vulkanMemoryModel);
+    COPY_VAL(vulkan_1_2.vulkanMemoryModelDeviceScope);
+    COPY_VAL(vulkan_1_2.hostQueryReset);
+
+    COPY_VAL(vulkan_1_3.dynamicRendering);
+    COPY_VAL(vulkan_1_3.maintenance4);
+    COPY_VAL(vulkan_1_3.synchronization2);
+    COPY_VAL(vulkan_1_3.computeFullSubgroups);
+    COPY_VAL(vulkan_1_3.shaderZeroInitializeWorkgroupMemory);
+    COPY_VAL(vulkan_1_3.dynamicRendering);
+
+    COPY_VAL(timeline_semaphore.timelineSemaphore);
+
+    COPY_VAL(video_maintenance_1.videoMaintenance1);
+
+    COPY_VAL(shader_object.shaderObject);
+
+    COPY_VAL(cooperative_matrix.cooperativeMatrix);
+
+    COPY_VAL(descriptor_buffer.descriptorBuffer);
+    COPY_VAL(descriptor_buffer.descriptorBufferPushDescriptors);
+
+    COPY_VAL(atomic_float.shaderBufferFloat32Atomics);
+    COPY_VAL(atomic_float.shaderBufferFloat32AtomicAdd);
+    COPY_VAL(relaxed_extended_instruction.shaderRelaxedExtendedInstruction);
+
+    COPY_VAL(optical_flow.opticalFlow);
+#undef COPY_VAL
+}
+
 #define ASPECT_2PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT)
 #define ASPECT_3PLANE (VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT | VK_IMAGE_ASPECT_PLANE_2_BIT)
 
@@ -424,9 +547,9 @@  static const VulkanOptExtension optional_instance_exts[] = {
 
 static const VulkanOptExtension optional_device_exts[] = {
     /* Misc or required by other extensions */
-    { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,               FF_VK_EXT_NO_FLAG                },
+    { VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,               FF_VK_EXT_PORTABILITY_SUBSET     },
     { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME,                  FF_VK_EXT_PUSH_DESCRIPTOR        },
-    { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,                FF_VK_EXT_DESCRIPTOR_BUFFER,     },
+    { VK_EXT_DESCRIPTOR_BUFFER_EXTENSION_NAME,                FF_VK_EXT_DESCRIPTOR_BUFFER      },
     { 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            },
@@ -1435,146 +1558,20 @@  static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
     AVVulkanDeviceContext *hwctx = &p->p;
     FFVulkanFunctions *vk = &p->vkctx.vkfn;
     enum FFVulkanDebugMode debug_mode = FF_VULKAN_DEBUG_NONE;
-
-    /*
-     * VkPhysicalDeviceVulkan12Features has a timelineSemaphore field, but
-     * MoltenVK doesn't implement VkPhysicalDeviceVulkan12Features yet, so we
-     * use VkPhysicalDeviceTimelineSemaphoreFeatures directly.
-     */
-    VkPhysicalDeviceTimelineSemaphoreFeatures timeline_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES,
-    };
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    VkPhysicalDeviceShaderRelaxedExtendedInstructionFeaturesKHR relaxed_extended_instr_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_RELAXED_EXTENDED_INSTRUCTION_FEATURES_KHR,
-        .pNext = &timeline_features,
-    };
-#endif
-    VkPhysicalDeviceVideoMaintenance1FeaturesKHR video_maint_1_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR,
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-        .pNext = &relaxed_extended_instr_features,
-#else
-        .pNext = &timeline_features,
-#endif
-    };
-    VkPhysicalDeviceShaderObjectFeaturesEXT shader_object_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT,
-        .pNext = &video_maint_1_features,
-    };
-    VkPhysicalDeviceOpticalFlowFeaturesNV optical_flow_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV,
-        .pNext = &shader_object_features,
-    };
-    VkPhysicalDeviceCooperativeMatrixFeaturesKHR coop_matrix_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR,
-        .pNext = &optical_flow_features,
-    };
-    VkPhysicalDeviceShaderAtomicFloatFeaturesEXT atomic_float_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT,
-        .pNext = &coop_matrix_features,
-    };
-    VkPhysicalDeviceDescriptorBufferFeaturesEXT desc_buf_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT,
-        .pNext = &atomic_float_features,
-    };
-    VkPhysicalDeviceVulkan13Features dev_features_1_3 = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
-        .pNext = &desc_buf_features,
-    };
-    VkPhysicalDeviceVulkan12Features dev_features_1_2 = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
-        .pNext = &dev_features_1_3,
-    };
-    VkPhysicalDeviceVulkan11Features dev_features_1_1 = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
-        .pNext = &dev_features_1_2,
-    };
-    VkPhysicalDeviceFeatures2 dev_features = {
-        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
-        .pNext = &dev_features_1_1,
-    };
-
+    VulkanDeviceFeatures supported_feats = { 0 };
     VkDeviceCreateInfo dev_info = {
         .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
     };
 
-    ctx->free = vulkan_device_free;
-
     /* Create an instance if not given one */
     if ((err = create_instance(ctx, opts, &debug_mode)))
         goto end;
 
-    /* Find a device (if not given one) */
+    /* Find a physical device (if not given one) */
     if ((err = find_device(ctx, dev_select)))
         goto end;
 
-    vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &dev_features);
-
-    /* Try to keep in sync with libplacebo */
-#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.features.NAME;
-    COPY_FEATURE(hwctx->device_features, shaderImageGatherExtended)
-    COPY_FEATURE(hwctx->device_features, shaderStorageImageReadWithoutFormat)
-    COPY_FEATURE(hwctx->device_features, shaderStorageImageWriteWithoutFormat)
-    COPY_FEATURE(hwctx->device_features, fragmentStoresAndAtomics)
-    COPY_FEATURE(hwctx->device_features, vertexPipelineStoresAndAtomics)
-    COPY_FEATURE(hwctx->device_features, shaderInt64)
-    COPY_FEATURE(hwctx->device_features, shaderInt16)
-    COPY_FEATURE(hwctx->device_features, shaderFloat64)
-#undef COPY_FEATURE
-
-    /* We require timeline semaphores */
-    if (!timeline_features.timelineSemaphore) {
-        av_log(ctx, AV_LOG_ERROR, "Device does not support timeline semaphores!\n");
-        err = AVERROR(ENOSYS);
-        goto end;
-    }
-
-    p->device_features_1_1.samplerYcbcrConversion = dev_features_1_1.samplerYcbcrConversion;
-    p->device_features_1_1.storagePushConstant16 = dev_features_1_1.storagePushConstant16;
-    p->device_features_1_1.storageBuffer16BitAccess = dev_features_1_1.storageBuffer16BitAccess;
-    p->device_features_1_1.uniformAndStorageBuffer16BitAccess = dev_features_1_1.uniformAndStorageBuffer16BitAccess;
-
-    p->device_features_1_2.timelineSemaphore = 1;
-    p->device_features_1_2.scalarBlockLayout = dev_features_1_2.scalarBlockLayout;
-    p->device_features_1_2.bufferDeviceAddress = dev_features_1_2.bufferDeviceAddress;
-    p->device_features_1_2.hostQueryReset = dev_features_1_2.hostQueryReset;
-    p->device_features_1_2.storagePushConstant8 = dev_features_1_2.storagePushConstant8;
-    p->device_features_1_2.shaderInt8 = dev_features_1_2.shaderInt8;
-    p->device_features_1_2.storageBuffer8BitAccess = dev_features_1_2.storageBuffer8BitAccess;
-    p->device_features_1_2.uniformAndStorageBuffer8BitAccess = dev_features_1_2.uniformAndStorageBuffer8BitAccess;
-    p->device_features_1_2.shaderFloat16 = dev_features_1_2.shaderFloat16;
-    p->device_features_1_2.shaderSharedInt64Atomics = dev_features_1_2.shaderSharedInt64Atomics;
-    p->device_features_1_2.vulkanMemoryModel = dev_features_1_2.vulkanMemoryModel;
-    p->device_features_1_2.vulkanMemoryModelDeviceScope = dev_features_1_2.vulkanMemoryModelDeviceScope;
-    p->device_features_1_2.hostQueryReset = dev_features_1_2.hostQueryReset;
-
-    p->device_features_1_3.dynamicRendering = dev_features_1_3.dynamicRendering;
-    p->device_features_1_3.maintenance4 = dev_features_1_3.maintenance4;
-    p->device_features_1_3.synchronization2 = dev_features_1_3.synchronization2;
-    p->device_features_1_3.computeFullSubgroups = dev_features_1_3.computeFullSubgroups;
-    p->device_features_1_3.shaderZeroInitializeWorkgroupMemory = dev_features_1_3.shaderZeroInitializeWorkgroupMemory;
-    p->device_features_1_3.dynamicRendering = dev_features_1_3.dynamicRendering;
-
-    p->video_maint_1_features.videoMaintenance1 = video_maint_1_features.videoMaintenance1;
-
-    p->desc_buf_features.descriptorBuffer = desc_buf_features.descriptorBuffer;
-    p->desc_buf_features.descriptorBufferPushDescriptors = desc_buf_features.descriptorBufferPushDescriptors;
-
-    p->atomic_float_features.shaderBufferFloat32Atomics = atomic_float_features.shaderBufferFloat32Atomics;
-    p->atomic_float_features.shaderBufferFloat32AtomicAdd = atomic_float_features.shaderBufferFloat32AtomicAdd;
-
-    p->coop_matrix_features.cooperativeMatrix = coop_matrix_features.cooperativeMatrix;
-
-    p->optical_flow_features.opticalFlow = optical_flow_features.opticalFlow;
-
-    p->shader_object_features.shaderObject = shader_object_features.shaderObject;
-
-#ifdef VK_KHR_shader_relaxed_extended_instruction
-    p->relaxed_extended_instr_features.shaderRelaxedExtendedInstruction = relaxed_extended_instr_features.shaderRelaxedExtendedInstruction;
-#endif
-
-    /* Find and enable extensions */
+    /* Find and enable extensions for the physical device */
     if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames,
                                 &dev_info.enabledExtensionCount, debug_mode))) {
         for (int i = 0; i < dev_info.queueCreateInfoCount; i++)
@@ -1583,45 +1580,21 @@  static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
         goto end;
     }
 
-    /* Setup enabled device features */
-    hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
-    hwctx->device_features.pNext = &p->device_features_1_1;
-    p->device_features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
-    p->device_features_1_1.pNext = &p->device_features_1_2;
-    p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
-    p->device_features_1_2.pNext = &p->device_features_1_3;
-    p->device_features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
-    p->device_features_1_3.pNext = NULL;
-
-#define OPT_CHAIN(EXT_FLAG, STRUCT_P, TYPE)                            \
-    do {                                                               \
-        if (p->vkctx.extensions & EXT_FLAG) {                          \
-            (STRUCT_P)->sType = TYPE;                                  \
-            ff_vk_link_struct(hwctx->device_features.pNext, STRUCT_P); \
-        }                                                              \
-    } while (0)
-
-    OPT_CHAIN(FF_VK_EXT_DESCRIPTOR_BUFFER, &p->desc_buf_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_FEATURES_EXT);
-    OPT_CHAIN(FF_VK_EXT_ATOMIC_FLOAT, &p->atomic_float_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT);
-    OPT_CHAIN(FF_VK_EXT_COOP_MATRIX, &p->coop_matrix_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_FEATURES_KHR);
-    OPT_CHAIN(FF_VK_EXT_SHADER_OBJECT, &p->shader_object_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT);
-    OPT_CHAIN(FF_VK_EXT_OPTICAL_FLOW, &p->optical_flow_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPTICAL_FLOW_FEATURES_NV);
-    OPT_CHAIN(FF_VK_EXT_VIDEO_MAINTENANCE_1, &p->video_maint_1_features,
-              VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VIDEO_MAINTENANCE_1_FEATURES_KHR);
-#undef OPT_CHAIN
+    /* Get all supported features for the physical device */
+    device_features_init(ctx, &supported_feats);
+    vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &supported_feats.device);
 
-    /* Add the enabled features into the pnext chain of device creation */
-    dev_info.pNext = &hwctx->device_features;
+    /* Copy all needed features from those supported and activate them */
+    device_features_init(ctx, &p->feats);
+    device_features_copy_needed(&p->feats, &supported_feats);
+    dev_info.pNext = p->feats.device.pNext;
+    dev_info.pEnabledFeatures = &p->feats.device.features;
 
     /* Setup enabled queue families */
     if ((err = setup_queue_families(ctx, &dev_info)))
         goto end;
 
+    /* Finally create the device */
     ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc,
                            &hwctx->act_dev);
 
@@ -1644,9 +1617,7 @@  static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
     if (opt_d)
         p->use_linear_images = strtol(opt_d->value, NULL, 10);
 
-    /*
-     * The disable_multiplane argument takes precedent over the option.
-     */
+    /* The disable_multiplane argument takes precedent over the option */
     p->disable_multiplane = disable_multiplane;
     if (!p->disable_multiplane) {
         opt_d = av_dict_get(opts, "disable_multiplane", NULL, 0);
@@ -1654,9 +1625,13 @@  static int vulkan_device_create_internal(AVHWDeviceContext *ctx,
             p->disable_multiplane = strtol(opt_d->value, NULL, 10);
     }
 
+    /* Set the list of all active extensions */
     hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames;
     hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount;
 
+    /* The extension lists need to be freed */
+    ctx->free = vulkan_device_free;
+
 end:
     return err;
 }
diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h
index 7a5385381b..b1ae4d181e 100644
--- a/libavutil/vulkan_functions.h
+++ b/libavutil/vulkan_functions.h
@@ -62,6 +62,7 @@  typedef uint64_t FFVulkanExtensions;
 #define FF_VK_EXT_VIDEO_ENCODE_H264      (1ULL << 51) /* VK_KHR_video_encode_h264 */
 #define FF_VK_EXT_VIDEO_ENCODE_H265      (1ULL << 52) /* VK_KHR_video_encode_h265 */
 
+#define FF_VK_EXT_PORTABILITY_SUBSET     (1ULL << 62)
 #define FF_VK_EXT_NO_FLAG                (1ULL << 63)
 
 /* Macro containing every function that we utilize in our codebase */