[Mesa-dev] [RFC PATCH v1 23/30] RFC: anv: Support VkDrmFormatModifierPropertiesListEXT

Chad Versace chadversary at chromium.org
Tue Nov 7 14:48:04 UTC 2017


Incremental implementation of VK_EXT_image_drm_format_modifier.
---
 src/intel/vulkan/anv_formats.c | 144 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 132 insertions(+), 12 deletions(-)

diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c
index 0dd990bb9a8..dc46fdb5425 100644
--- a/src/intel/vulkan/anv_formats.c
+++ b/src/intel/vulkan/anv_formats.c
@@ -21,6 +21,8 @@
  * IN THE SOFTWARE.
  */
 
+#include <drm_fourcc.h>
+
 #include "anv_private.h"
 #include "vk_enum_to_str.h"
 #include "vk_format_info.h"
@@ -425,6 +427,9 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
       return unsupported;
 
    if (aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
+      if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+         return unsupported;
+
       assert(vk_format_aspects(vk_format) &
              (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
       return plane_format;
@@ -435,6 +440,18 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
    const struct isl_format_layout *isl_layout =
       isl_format_get_layout(plane_format.isl_format);
 
+   /* For VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the image's driver-internal
+    * format must be the user-facing VkFormat. Modifying the VkFormat in any
+    * way, including swizzling, is illegal.
+    */
+
+   /* For now, for no reason other than FUD, we decline to support texture
+    * compression with modifiers.
+    */
+   if (tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
+       isl_layout->txc != ISL_TXC_NONE)
+      return unsupported;
+
    if (tiling == VK_IMAGE_TILING_OPTIMAL &&
        !util_is_power_of_two(isl_layout->bpb)) {
       /* Tiled formats *must* be power-of-two because we need up upload
@@ -456,7 +473,8 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
    /* The B4G4R4A4 format isn't available prior to Broadwell so we have to fall
     * back to a format with a more complex swizzle.
     */
-   if (vk_format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 && devinfo->gen < 8) {
+   if (tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT &&
+       vk_format == VK_FORMAT_B4G4R4A4_UNORM_PACK16 && devinfo->gen < 8) {
       plane_format.isl_format = ISL_FORMAT_B4G4R4A4_UNORM;
       plane_format.swizzle = ISL_SWIZZLE(GREEN, RED, ALPHA, BLUE);
    }
@@ -466,21 +484,29 @@ anv_get_format_plane(const struct gen_device_info *devinfo, VkFormat vk_format,
 
 // Format capabilities
 
+/**
+ * Parameter drm_format_mod must be DRM_FORMAT_MOD_INVALID unless vk_tiling is
+ * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
+ */
 static VkFormatFeatureFlags
 get_image_format_features(const struct gen_device_info *devinfo,
                           VkFormat vk_format,
                           const struct anv_format *anv_format,
-                          VkImageTiling vk_tiling)
+                          VkImageTiling vk_tiling,
+                          uint64_t drm_format_mod)
 {
    VkFormatFeatureFlags flags = 0;
 
+   if (vk_tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+      assert(drm_format_mod == DRM_FORMAT_MOD_INVALID);
+
    if (anv_format == NULL)
       return 0;
 
    const VkImageAspectFlags aspects = vk_format_aspects(vk_format);
 
    if (aspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
-      if (vk_tiling == VK_IMAGE_TILING_LINEAR)
+      if (vk_tiling != VK_IMAGE_TILING_OPTIMAL)
          return 0;
 
       flags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
@@ -503,6 +529,17 @@ get_image_format_features(const struct gen_device_info *devinfo,
    if (plane_format.isl_format == ISL_FORMAT_UNSUPPORTED)
       return 0;
 
+   const struct isl_format_layout *isl_layout =
+      isl_format_get_layout(plane_format.isl_format);
+
+   if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT)
+      assert(isl_layout->txc == ISL_TXC_NONE);
+
+   /* For VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, the base format and
+    * non-base format must be the same, because the image's driver-internal
+    * format must be the user-facing VkFormat. Modifying the VkFormat in any
+    * way, including swizzling, is illegal.
+    */
    struct anv_format_plane base_plane_format = plane_format;
    if (vk_tiling == VK_IMAGE_TILING_OPTIMAL) {
       base_plane_format = anv_get_format_plane(devinfo, vk_format,
@@ -513,8 +550,8 @@ get_image_format_features(const struct gen_device_info *devinfo,
    enum isl_format base_isl_format = base_plane_format.isl_format;
 
    /* ASTC textures must be in Y-tiled memory */
-   if (vk_tiling == VK_IMAGE_TILING_LINEAR &&
-       isl_format_get_layout(plane_format.isl_format)->txc == ISL_TXC_ASTC)
+   if (vk_tiling != VK_IMAGE_TILING_OPTIMAL &&
+       isl_layout->txc == ISL_TXC_ASTC)
       return 0;
 
    if (isl_format_supports_sampling(devinfo, plane_format.isl_format)) {
@@ -569,6 +606,11 @@ get_image_format_features(const struct gen_device_info *devinfo,
    }
 
    if (anv_format->can_ycbcr) {
+      if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+         /* FINISHME(chadv): Support YUV with DRM format modifiers. */
+         return 0;
+      }
+
       /* The sampler doesn't have support for mid point when it handles YUV on
        * its own.
        */
@@ -608,6 +650,22 @@ get_image_format_features(const struct gen_device_info *devinfo,
       flags &= ~disallowed_ycbcr_image_features;
    }
 
+   if (vk_tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT) {
+      switch (drm_format_mod) {
+      default:
+         unreachable("bad DRM format modifier");
+      case DRM_FORMAT_MOD_LINEAR:
+         break;
+      case I915_FORMAT_MOD_X_TILED:
+         /* TODO(chadv): Should we support X-tiled storage images? */
+         flags &= ~VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;
+         flags &= ~VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT;
+         break;
+      case I915_FORMAT_MOD_Y_TILED:
+         break;
+      }
+   }
+
    return flags;
 }
 
@@ -651,6 +709,60 @@ get_buffer_format_features(const struct gen_device_info *devinfo,
    return flags;
 }
 
+/**
+ * Fill the VkDrmFormatModifierPropertiesEXT struct if the VkFormat supports
+ * the DRM format modifier, and return true.  On failure, the output struct
+ * has undefined content.
+ */
+static bool
+get_drm_format_modifier_properties(const struct anv_physical_device *physical_device,
+                                   VkFormat vk_format,
+                                   const struct anv_format *anv_format,
+                                   uint64_t drm_format_mod,
+                                   VkDrmFormatModifierPropertiesEXT *props)
+{
+   const struct gen_device_info *devinfo = &physical_device->info;
+
+   *props = (VkDrmFormatModifierPropertiesEXT) {
+      .drmFormatModifier = drm_format_mod,
+      .drmFormatModifierPlaneCount = anv_format->n_planes,
+      .drmFormatModifierTilingFeatures =
+         get_image_format_features(devinfo, vk_format, anv_format,
+                                   VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
+                                   drm_format_mod),
+   };
+
+   if (props->drmFormatModifierTilingFeatures == 0)
+      return false;
+
+   return true;
+}
+
+static void
+get_drm_format_modifier_properties_list(const struct anv_physical_device *physical_device,
+                                        VkFormat vk_format,
+                                        VkDrmFormatModifierPropertiesListEXT *drm_list)
+{
+   const struct anv_format *anv_format = anv_get_format(vk_format);
+
+   VK_OUTARRAY_MAKE(out, drm_list->pDrmFormatModifierProperties,
+                    &drm_list->drmFormatModifierCount);
+
+   #define TRY_MOD(mod) ({ \
+      VkDrmFormatModifierPropertiesEXT tmp_props; \
+      if (get_drm_format_modifier_properties(physical_device, vk_format, \
+                                             anv_format, (mod), &tmp_props)) { \
+         vk_outarray_append(&out, drm_props) { *drm_props = tmp_props; }; \
+      } \
+   })
+
+   TRY_MOD(I915_FORMAT_MOD_Y_TILED);
+   TRY_MOD(I915_FORMAT_MOD_X_TILED);
+   TRY_MOD(DRM_FORMAT_MOD_LINEAR);
+
+   #undef TRY_MOD
+}
+
 void anv_GetPhysicalDeviceFormatProperties(
     VkPhysicalDevice                            physicalDevice,
     VkFormat                                    vk_format,
@@ -663,10 +775,12 @@ void anv_GetPhysicalDeviceFormatProperties(
    *pFormatProperties = (VkFormatProperties) {
       .linearTilingFeatures =
          get_image_format_features(devinfo, vk_format, anv_format,
-                                   VK_IMAGE_TILING_LINEAR),
+                                   VK_IMAGE_TILING_LINEAR,
+                                   DRM_FORMAT_MOD_INVALID),
       .optimalTilingFeatures =
          get_image_format_features(devinfo, vk_format, anv_format,
-                                   VK_IMAGE_TILING_OPTIMAL),
+                                   VK_IMAGE_TILING_OPTIMAL,
+                                   DRM_FORMAT_MOD_INVALID),
       .bufferFeatures =
          get_buffer_format_features(devinfo, vk_format, anv_format),
    };
@@ -674,14 +788,20 @@ void anv_GetPhysicalDeviceFormatProperties(
 
 void anv_GetPhysicalDeviceFormatProperties2KHR(
     VkPhysicalDevice                            physicalDevice,
-    VkFormat                                    format,
+    VkFormat                                    vk_format,
     VkFormatProperties2KHR*                     pFormatProperties)
 {
-   anv_GetPhysicalDeviceFormatProperties(physicalDevice, format,
+   ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
+
+   anv_GetPhysicalDeviceFormatProperties(physicalDevice, vk_format,
                                          &pFormatProperties->formatProperties);
 
    vk_foreach_struct(ext, pFormatProperties->pNext) {
       switch (ext->sType) {
+      case VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT:
+         get_drm_format_modifier_properties_list(physical_device, vk_format,
+            (VkDrmFormatModifierPropertiesListEXT *)ext);
+         break;
       default:
          anv_debug_ignored_stype(ext->sType);
          break;
@@ -696,7 +816,6 @@ anv_get_image_format_properties(
    VkImageFormatProperties *pImageFormatProperties,
    VkSamplerYcbcrConversionImageFormatPropertiesKHR *pYcbcrImageFormatProperties)
 {
-   VkFormatFeatureFlags format_feature_flags;
    VkExtent3D maxExtent;
    uint32_t maxMipLevels;
    uint32_t maxArraySize;
@@ -707,8 +826,9 @@ anv_get_image_format_properties(
    if (format == NULL)
       goto unsupported;
 
-   format_feature_flags = get_image_format_features(devinfo, info->format,
-                                                    format, info->tiling);
+   VkFormatFeatureFlags format_feature_flags =
+      get_image_format_features(devinfo, info->format, format, info->tiling,
+                                DRM_FORMAT_MOD_INVALID);
 
    switch (info->type) {
    default:
-- 
2.13.0



More information about the mesa-dev mailing list