diff mbox series

[FFmpeg-devel,7/7] libavutil/hwcontext_vulkan: specify the modifier to create VKImage

Message ID 20211109091843.2024927-7-wenbin.chen@intel.com
State New
Headers show
Series [FFmpeg-devel,1/7] hwcontext_vaapi: Use PRIME_2 memory type for modifiers. | expand

Checks

Context Check Description
andriy/configurex86 warning Failed to apply patch
andriy/configureppc warning Failed to apply patch

Commit Message

Wenbin Chen Nov. 9, 2021, 9:18 a.m. UTC
When vulkan image exports to drm, the tilling need to be
VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan
image using this format.

Now the following command line works:

ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \
vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \
scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264

Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
---
 libavutil/hwcontext_vulkan.c | 76 +++++++++++++++++++++++++++++++++---
 libavutil/hwcontext_vulkan.h |  5 +++
 2 files changed, 75 insertions(+), 6 deletions(-)

Comments

Lynne Nov. 12, 2021, 7:10 a.m. UTC | #1
9 Nov 2021, 10:18 by wenbin.chen@intel.com:

> When vulkan image exports to drm, the tilling need to be
> VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to create vulkan
> image using this format.
>
> Now the following command line works:
>
> ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format \
> vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan, \
> scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v h264_vaapi output.264
>
> Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> ---
>  libavutil/hwcontext_vulkan.c | 76 +++++++++++++++++++++++++++++++++---
>  libavutil/hwcontext_vulkan.h |  5 +++
>  2 files changed, 75 insertions(+), 6 deletions(-)
>
> diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
> index 29ade94b7f..e252c2177e 100644
> --- a/libavutil/hwcontext_vulkan.c
> +++ b/libavutil/hwcontext_vulkan.c
> @@ -1919,6 +1919,7 @@ static void try_export_flags(AVHWFramesContext *hwfc,
>  AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
>  VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
>  FFVulkanFunctions *vk = &p->vkfn;
> +    const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
>  VkExternalImageFormatProperties eprops = {
>  .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
>  };
> @@ -1926,9 +1927,18 @@ static void try_export_flags(AVHWFramesContext *hwfc,
>  .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
>  .pNext = &eprops,
>  };
> +    VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
> +        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
> +        .pNext = NULL,
> +        .pQueueFamilyIndices   = p->qfs,
> +        .queueFamilyIndexCount = p->num_qfs,
> +        .sharingMode           = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
> +                                                  VK_SHARING_MODE_EXCLUSIVE,
> +    };
>  VkPhysicalDeviceExternalImageFormatInfo enext = {
>  .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
>  .handleType = exp,
> +        .pNext = has_modifiers ? &phy_dev_mod_info : NULL,
>  };
>  VkPhysicalDeviceImageFormatInfo2 pinfo = {
>  .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
> @@ -1940,11 +1950,15 @@ static void try_export_flags(AVHWFramesContext *hwfc,
>  .flags  = VK_IMAGE_CREATE_ALIAS_BIT,
>  };
>  
> -    ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
> -                                                      &pinfo, &props);
> -    if (ret == VK_SUCCESS) {
> -        *iexp |= exp;
> -        *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
> +    for (int i = 0; i < (has_modifiers ? hwctx->modifier_count : 1); i++) {
> +        if (has_modifiers && hwctx->modifier_count)
> +            phy_dev_mod_info.drmFormatModifier = hwctx->modifiers[i];
> +        ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
> +                                                        &pinfo, &props);
> +        if (ret == VK_SUCCESS) {
> +            *iexp |= exp;
> +            *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
> +        }
>  }
>  }
>  
> @@ -2007,6 +2021,7 @@ fail:
>  static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
>  {
>  VulkanFramesPriv *fp = hwfc->internal->priv;
> +    AVVulkanFramesContext *hwctx = hwfc->hwctx;
>  
>  free_exec_ctx(hwfc, &fp->conv_ctx);
>  free_exec_ctx(hwfc, &fp->upload_ctx);
> @@ -2021,11 +2036,60 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc)
>  VulkanFramesPriv *fp = hwfc->internal->priv;
>  AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
>  VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
> +    const int has_modifiers = !!(p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS);
>  
>  /* Default pool flags */
> -    hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ?
> +    hwctx->tiling = hwctx->tiling ? hwctx->tiling : has_modifiers ?
> +                    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : p->use_linear_images ?
>  VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
>  
> +    /* get the supported modifier */
> +    if (has_modifiers) {
> +        const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format);
> +        FFVulkanFunctions *vk = &p->vkfn;
> +        VkDrmFormatModifierPropertiesEXT mod_props[MAX_VULKAN_MODIFIERS];
> +
> +        VkDrmFormatModifierPropertiesListEXT mod_props_list = {
> +            .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
> +            .pNext = NULL,
> +            .drmFormatModifierCount = 0,
> +            .pDrmFormatModifierProperties = NULL,
> +        };
> +        VkFormatProperties2 prop = {
> +            .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
> +            .pNext = &mod_props_list,
> +        };
> +
> +        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop);
> +        if (!mod_props_list.drmFormatModifierCount) {
> +            av_log(hwfc, AV_LOG_ERROR, "There are not supported modifiers for sw_format\n");
> +            return AVERROR(EINVAL);
> +        }
> +        mod_props_list.drmFormatModifierCount =
> +            FFMIN(mod_props_list.drmFormatModifierCount, MAX_VULKAN_MODIFIERS);
> +
> +        mod_props_list.pDrmFormatModifierProperties = mod_props;
> +        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop);
> +
> +        hwctx->modifier_count = 0;
> +        for (int i = 0; i < mod_props_list.drmFormatModifierCount; i++) {
> +            if (!(mod_props[i].drmFormatModifierTilingFeatures & DEFAULT_USAGE_FLAGS))
> +                continue;
> +            hwctx->modifiers[hwctx->modifier_count++] = mod_props[i].drmFormatModifier;
> +        }
> +        if (!hwctx->modifier_count) {
> +            av_log(hwfc, AV_LOG_ERROR, "The supported modifiers doesn't support"
> +                                       "default usage\n");
> +            return AVERROR(EINVAL);
> +        }
> +
> +        hwctx->create_pnext = &hwctx->modifier_info;
> +        hwctx->modifier_info.pNext = NULL;
> +        hwctx->modifier_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT;
> +        hwctx->modifier_info.drmFormatModifierCount = hwctx->modifier_count;
> +        hwctx->modifier_info.pDrmFormatModifiers = hwctx->modifiers;
> +    }
> +
>  if (!hwctx->usage)
>  hwctx->usage = DEFAULT_USAGE_FLAGS;
>  
> diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
> index efb602ef27..113448bb51 100644
> --- a/libavutil/hwcontext_vulkan.h
> +++ b/libavutil/hwcontext_vulkan.h
> @@ -32,6 +32,7 @@
>  * with the data pointer set to an AVVkFrame.
>  */
>  
> +#define MAX_VULKAN_MODIFIERS 16
>  /**
>  * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
>  * All of these can be set before init to change what the context uses
> @@ -149,6 +150,10 @@ typedef struct AVVulkanFramesContext {
>  */
>  void *create_pnext;
>  
> +    VkImageDrmFormatModifierListCreateInfoEXT modifier_info;
> +    uint64_t modifiers[MAX_VULKAN_MODIFIERS];
> +    int modifier_count;
>

I don't like having a platform-specific variable in the context, but I
understand why it's necessary. Wouldn't a single modifier be sufficient,
though, rather than exposing all supported modifiers? Since all images
that are allocated by the frames context should all have the same
modifier.
Wenbin Chen Nov. 15, 2021, 8:30 a.m. UTC | #2
> 9 Nov 2021, 10:18 by wenbin.chen@intel.com:
> 
> > When vulkan image exports to drm, the tilling need to be
> > VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT. Now add code to
> create vulkan
> > image using this format.
> >
> > Now the following command line works:
> >
> > ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -
> hwaccel_output_format \
> > vaapi -i input_1080p.264 -vf "hwmap=derive_device=vulkan,format=vulkan,
> \
> > scale_vulkan=1920:1080,hwmap=derive_device=vaapi,format=vaapi" -c:v
> h264_vaapi output.264
> >
> > Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> > ---
> >  libavutil/hwcontext_vulkan.c | 76 +++++++++++++++++++++++++++++++++-
> --
> >  libavutil/hwcontext_vulkan.h |  5 +++
> >  2 files changed, 75 insertions(+), 6 deletions(-)
> >
> > diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
> > index 29ade94b7f..e252c2177e 100644
> > --- a/libavutil/hwcontext_vulkan.c
> > +++ b/libavutil/hwcontext_vulkan.c
> > @@ -1919,6 +1919,7 @@ static void
> try_export_flags(AVHWFramesContext *hwfc,
> >  AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
> >  VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
> >  FFVulkanFunctions *vk = &p->vkfn;
> > +    const int has_modifiers = hwctx->tiling ==
> VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
> >  VkExternalImageFormatProperties eprops = {
> >  .sType =
> VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
> >  };
> > @@ -1926,9 +1927,18 @@ static void
> try_export_flags(AVHWFramesContext *hwfc,
> >  .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
> >  .pNext = &eprops,
> >  };
> > +    VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info
> = {
> > +        .sType =
> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER
> _INFO_EXT,
> > +        .pNext = NULL,
> > +        .pQueueFamilyIndices   = p->qfs,
> > +        .queueFamilyIndexCount = p->num_qfs,
> > +        .sharingMode           = p->num_qfs > 1 ?
> VK_SHARING_MODE_CONCURRENT :
> > +                                                  VK_SHARING_MODE_EXCLUSIVE,
> > +    };
> >  VkPhysicalDeviceExternalImageFormatInfo enext = {
> >  .sType =
> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
> >  .handleType = exp,
> > +        .pNext = has_modifiers ? &phy_dev_mod_info : NULL,
> >  };
> >  VkPhysicalDeviceImageFormatInfo2 pinfo = {
> >  .sType  =
> VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
> > @@ -1940,11 +1950,15 @@ static void
> try_export_flags(AVHWFramesContext *hwfc,
> >  .flags  = VK_IMAGE_CREATE_ALIAS_BIT,
> >  };
> >
> > -    ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx-
> >phys_dev,
> > -                                                      &pinfo, &props);
> > -    if (ret == VK_SUCCESS) {
> > -        *iexp |= exp;
> > -        *comp_handle_types |=
> eprops.externalMemoryProperties.compatibleHandleTypes;
> > +    for (int i = 0; i < (has_modifiers ? hwctx->modifier_count : 1); i++) {
> > +        if (has_modifiers && hwctx->modifier_count)
> > +            phy_dev_mod_info.drmFormatModifier = hwctx->modifiers[i];
> > +        ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx-
> >phys_dev,
> > +                                                        &pinfo, &props);
> > +        if (ret == VK_SUCCESS) {
> > +            *iexp |= exp;
> > +            *comp_handle_types |=
> eprops.externalMemoryProperties.compatibleHandleTypes;
> > +        }
> >  }
> >  }
> >
> > @@ -2007,6 +2021,7 @@ fail:
> >  static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
> >  {
> >  VulkanFramesPriv *fp = hwfc->internal->priv;
> > +    AVVulkanFramesContext *hwctx = hwfc->hwctx;
> >
> >  free_exec_ctx(hwfc, &fp->conv_ctx);
> >  free_exec_ctx(hwfc, &fp->upload_ctx);
> > @@ -2021,11 +2036,60 @@ static int
> vulkan_frames_init(AVHWFramesContext *hwfc)
> >  VulkanFramesPriv *fp = hwfc->internal->priv;
> >  AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
> >  VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
> > +    const int has_modifiers = !!(p->extensions &
> FF_VK_EXT_DRM_MODIFIER_FLAGS);
> >
> >  /* Default pool flags */
> > -    hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ?
> > +    hwctx->tiling = hwctx->tiling ? hwctx->tiling : has_modifiers ?
> > +                    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : p-
> >use_linear_images ?
> >  VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
> >
> > +    /* get the supported modifier */
> > +    if (has_modifiers) {
> > +        const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format);
> > +        FFVulkanFunctions *vk = &p->vkfn;
> > +        VkDrmFormatModifierPropertiesEXT
> mod_props[MAX_VULKAN_MODIFIERS];
> > +
> > +        VkDrmFormatModifierPropertiesListEXT mod_props_list = {
> > +            .sType =
> VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
> > +            .pNext = NULL,
> > +            .drmFormatModifierCount = 0,
> > +            .pDrmFormatModifierProperties = NULL,
> > +        };
> > +        VkFormatProperties2 prop = {
> > +            .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
> > +            .pNext = &mod_props_list,
> > +        };
> > +
> > +        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev,
> fmt[0], &prop);
> > +        if (!mod_props_list.drmFormatModifierCount) {
> > +            av_log(hwfc, AV_LOG_ERROR, "There are not supported modifiers
> for sw_format\n");
> > +            return AVERROR(EINVAL);
> > +        }
> > +        mod_props_list.drmFormatModifierCount =
> > +            FFMIN(mod_props_list.drmFormatModifierCount,
> MAX_VULKAN_MODIFIERS);
> > +
> > +        mod_props_list.pDrmFormatModifierProperties = mod_props;
> > +        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev,
> fmt[0], &prop);
> > +
> > +        hwctx->modifier_count = 0;
> > +        for (int i = 0; i < mod_props_list.drmFormatModifierCount; i++) {
> > +            if (!(mod_props[i].drmFormatModifierTilingFeatures &
> DEFAULT_USAGE_FLAGS))
> > +                continue;
> > +            hwctx->modifiers[hwctx->modifier_count++] =
> mod_props[i].drmFormatModifier;
> > +        }
> > +        if (!hwctx->modifier_count) {
> > +            av_log(hwfc, AV_LOG_ERROR, "The supported modifiers doesn't
> support"
> > +                                       "default usage\n");
> > +            return AVERROR(EINVAL);
> > +        }
> > +
> > +        hwctx->create_pnext = &hwctx->modifier_info;
> > +        hwctx->modifier_info.pNext = NULL;
> > +        hwctx->modifier_info.sType =
> VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INF
> O_EXT;
> > +        hwctx->modifier_info.drmFormatModifierCount = hwctx-
> >modifier_count;
> > +        hwctx->modifier_info.pDrmFormatModifiers = hwctx->modifiers;
> > +    }
> > +
> >  if (!hwctx->usage)
> >  hwctx->usage = DEFAULT_USAGE_FLAGS;
> >
> > diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
> > index efb602ef27..113448bb51 100644
> > --- a/libavutil/hwcontext_vulkan.h
> > +++ b/libavutil/hwcontext_vulkan.h
> > @@ -32,6 +32,7 @@
> >  * with the data pointer set to an AVVkFrame.
> >  */
> >
> > +#define MAX_VULKAN_MODIFIERS 16
> >  /**
> >  * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
> >  * All of these can be set before init to change what the context uses
> > @@ -149,6 +150,10 @@ typedef struct AVVulkanFramesContext {
> >  */
> >  void *create_pnext;
> >
> > +    VkImageDrmFormatModifierListCreateInfoEXT modifier_info;
> > +    uint64_t modifiers[MAX_VULKAN_MODIFIERS];
> > +    int modifier_count;
> >
> 
> I don't like having a platform-specific variable in the context, but I
> understand why it's necessary. Wouldn't a single modifier be sufficient,
> though, rather than exposing all supported modifiers? Since all images
> that are allocated by the frames context should all have the same
> modifier.

It is sufficient but it is not optimal, because driver can choose the optimal 
modifier from the list according to the platform but user can't.
I can use dynamic allocation instead of putting these variables in context. 

Thanks
Wenbin
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
index 29ade94b7f..e252c2177e 100644
--- a/libavutil/hwcontext_vulkan.c
+++ b/libavutil/hwcontext_vulkan.c
@@ -1919,6 +1919,7 @@  static void try_export_flags(AVHWFramesContext *hwfc,
     AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
     VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
     FFVulkanFunctions *vk = &p->vkfn;
+    const int has_modifiers = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
     VkExternalImageFormatProperties eprops = {
         .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR,
     };
@@ -1926,9 +1927,18 @@  static void try_export_flags(AVHWFramesContext *hwfc,
         .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
         .pNext = &eprops,
     };
+    VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = {
+        .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
+        .pNext = NULL,
+        .pQueueFamilyIndices   = p->qfs,
+        .queueFamilyIndexCount = p->num_qfs,
+        .sharingMode           = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT :
+                                                  VK_SHARING_MODE_EXCLUSIVE,
+    };
     VkPhysicalDeviceExternalImageFormatInfo enext = {
         .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
         .handleType = exp,
+        .pNext = has_modifiers ? &phy_dev_mod_info : NULL,
     };
     VkPhysicalDeviceImageFormatInfo2 pinfo = {
         .sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
@@ -1940,11 +1950,15 @@  static void try_export_flags(AVHWFramesContext *hwfc,
         .flags  = VK_IMAGE_CREATE_ALIAS_BIT,
     };
 
-    ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
-                                                      &pinfo, &props);
-    if (ret == VK_SUCCESS) {
-        *iexp |= exp;
-        *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
+    for (int i = 0; i < (has_modifiers ? hwctx->modifier_count : 1); i++) {
+        if (has_modifiers && hwctx->modifier_count)
+            phy_dev_mod_info.drmFormatModifier = hwctx->modifiers[i];
+        ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev,
+                                                        &pinfo, &props);
+        if (ret == VK_SUCCESS) {
+            *iexp |= exp;
+            *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes;
+        }
     }
 }
 
@@ -2007,6 +2021,7 @@  fail:
 static void vulkan_frames_uninit(AVHWFramesContext *hwfc)
 {
     VulkanFramesPriv *fp = hwfc->internal->priv;
+    AVVulkanFramesContext *hwctx = hwfc->hwctx;
 
     free_exec_ctx(hwfc, &fp->conv_ctx);
     free_exec_ctx(hwfc, &fp->upload_ctx);
@@ -2021,11 +2036,60 @@  static int vulkan_frames_init(AVHWFramesContext *hwfc)
     VulkanFramesPriv *fp = hwfc->internal->priv;
     AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx;
     VulkanDevicePriv *p = hwfc->device_ctx->internal->priv;
+    const int has_modifiers = !!(p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS);
 
     /* Default pool flags */
-    hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ?
+    hwctx->tiling = hwctx->tiling ? hwctx->tiling : has_modifiers ?
+                    VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : p->use_linear_images ?
                     VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
 
+    /* get the supported modifier */
+    if (has_modifiers) {
+        const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format);
+        FFVulkanFunctions *vk = &p->vkfn;
+        VkDrmFormatModifierPropertiesEXT mod_props[MAX_VULKAN_MODIFIERS];
+
+        VkDrmFormatModifierPropertiesListEXT mod_props_list = {
+            .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
+            .pNext = NULL,
+            .drmFormatModifierCount = 0,
+            .pDrmFormatModifierProperties = NULL,
+        };
+        VkFormatProperties2 prop = {
+            .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
+            .pNext = &mod_props_list,
+        };
+
+        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop);
+        if (!mod_props_list.drmFormatModifierCount) {
+            av_log(hwfc, AV_LOG_ERROR, "There are not supported modifiers for sw_format\n");
+            return AVERROR(EINVAL);
+        }
+        mod_props_list.drmFormatModifierCount =
+            FFMIN(mod_props_list.drmFormatModifierCount, MAX_VULKAN_MODIFIERS);
+
+        mod_props_list.pDrmFormatModifierProperties = mod_props;
+        vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop);
+
+        hwctx->modifier_count = 0;
+        for (int i = 0; i < mod_props_list.drmFormatModifierCount; i++) {
+            if (!(mod_props[i].drmFormatModifierTilingFeatures & DEFAULT_USAGE_FLAGS))
+                continue;
+            hwctx->modifiers[hwctx->modifier_count++] = mod_props[i].drmFormatModifier;
+        }
+        if (!hwctx->modifier_count) {
+            av_log(hwfc, AV_LOG_ERROR, "The supported modifiers doesn't support"
+                                       "default usage\n");
+            return AVERROR(EINVAL);
+        }
+
+        hwctx->create_pnext = &hwctx->modifier_info;
+        hwctx->modifier_info.pNext = NULL;
+        hwctx->modifier_info.sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT;
+        hwctx->modifier_info.drmFormatModifierCount = hwctx->modifier_count;
+        hwctx->modifier_info.pDrmFormatModifiers = hwctx->modifiers;
+    }
+
     if (!hwctx->usage)
         hwctx->usage = DEFAULT_USAGE_FLAGS;
 
diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h
index efb602ef27..113448bb51 100644
--- a/libavutil/hwcontext_vulkan.h
+++ b/libavutil/hwcontext_vulkan.h
@@ -32,6 +32,7 @@ 
  * with the data pointer set to an AVVkFrame.
  */
 
+#define MAX_VULKAN_MODIFIERS 16
 /**
  * Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
  * All of these can be set before init to change what the context uses
@@ -149,6 +150,10 @@  typedef struct AVVulkanFramesContext {
      */
     void *create_pnext;
 
+    VkImageDrmFormatModifierListCreateInfoEXT modifier_info;
+    uint64_t modifiers[MAX_VULKAN_MODIFIERS];
+    int modifier_count;
+
     /**
      * Extension data for memory allocation. Must have as many entries as
      * the number of planes of the sw_format.