[Mesa-dev] [PATCH v11 05/15] anv/image: Add support for modifiers for WSI

Daniel Stone daniels at collabora.com
Wed Feb 21 14:05:49 UTC 2018


From: Jason Ekstrand <jason.ekstrand at intel.com>

This adds support for the modifiers portion of the WSI "extension".

Reviewed-by: Daniel Stone <daniels at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/intel/vulkan/anv_formats.c | 38 ++++++++++++++++++++++++++++++++++++++
 src/intel/vulkan/anv_image.c   | 40 ++++++++++++++++++++++++++++++++++++++++
 src/intel/vulkan/anv_private.h |  6 ++++++
 src/intel/vulkan/anv_wsi.c     | 24 ++++++++++++++++++++----
 4 files changed, 104 insertions(+), 4 deletions(-)

diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c
index 4075ae8e620..9c52ad5acbd 100644
--- a/src/intel/vulkan/anv_formats.c
+++ b/src/intel/vulkan/anv_formats.c
@@ -22,6 +22,7 @@
  */
 
 #include "anv_private.h"
+#include "drm_fourcc.h"
 #include "vk_enum_to_str.h"
 #include "vk_format_info.h"
 #include "vk_util.h"
@@ -651,6 +652,38 @@ get_buffer_format_features(const struct gen_device_info *devinfo,
    return flags;
 }
 
+static void
+get_wsi_format_modifier_properties_list(const struct anv_physical_device *physical_device,
+                                        VkFormat vk_format,
+                                        struct wsi_format_modifier_properties_list *list)
+{
+   const struct anv_format *anv_format = anv_get_format(vk_format);
+
+   VK_OUTARRAY_MAKE(out, list->modifier_properties, &list->modifier_count);
+
+   /* This is a simplified list where all the modifiers are available */
+   assert(vk_format == VK_FORMAT_B8G8R8_SRGB ||
+          vk_format == VK_FORMAT_B8G8R8_UNORM ||
+          vk_format == VK_FORMAT_B8G8R8A8_SRGB ||
+          vk_format == VK_FORMAT_B8G8R8A8_UNORM);
+
+   uint64_t modifiers[] = {
+      DRM_FORMAT_MOD_LINEAR,
+      I915_FORMAT_MOD_X_TILED,
+      I915_FORMAT_MOD_Y_TILED,
+   };
+
+   for (uint32_t i = 0; i < ARRAY_SIZE(modifiers); i++) {
+      vk_outarray_append(&out, mod_props) {
+         mod_props->modifier = modifiers[i];
+         if (isl_drm_modifier_has_aux(modifiers[i]))
+            mod_props->modifier_plane_count = 2;
+         else
+            mod_props->modifier_plane_count = anv_format->n_planes;
+      }
+   }
+}
+
 void anv_GetPhysicalDeviceFormatProperties(
     VkPhysicalDevice                            physicalDevice,
     VkFormat                                    vk_format,
@@ -677,11 +710,16 @@ void anv_GetPhysicalDeviceFormatProperties2KHR(
     VkFormat                                    format,
     VkFormatProperties2KHR*                     pFormatProperties)
 {
+   ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
    anv_GetPhysicalDeviceFormatProperties(physicalDevice, format,
                                          &pFormatProperties->formatProperties);
 
    vk_foreach_struct(ext, pFormatProperties->pNext) {
       switch (ext->sType) {
+      case VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA:
+         get_wsi_format_modifier_properties_list(physical_device, format,
+                                                 (void *)ext);
+         break;
       default:
          anv_debug_ignored_stype(ext->sType);
          break;
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index c3d1810cee8..a2bae7b3827 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -508,6 +508,38 @@ make_surface(const struct anv_device *dev,
    return VK_SUCCESS;
 }
 
+static uint32_t
+score_drm_format_mod(uint64_t modifier)
+{
+   switch (modifier) {
+   case DRM_FORMAT_MOD_LINEAR: return 1;
+   case I915_FORMAT_MOD_X_TILED: return 2;
+   case I915_FORMAT_MOD_Y_TILED: return 3;
+   default: unreachable("bad DRM format modifier");
+   }
+}
+
+static const struct isl_drm_modifier_info *
+choose_drm_format_mod(const struct anv_physical_device *device,
+                      uint32_t modifier_count, const uint64_t *modifiers)
+{
+   uint64_t best_mod = UINT64_MAX;
+   uint32_t best_score = 0;
+
+   for (uint32_t i = 0; i < modifier_count; ++i) {
+      uint32_t score = score_drm_format_mod(modifiers[i]);
+      if (score > best_score) {
+         best_mod = modifiers[i];
+         best_score = score;
+      }
+   }
+
+   if (best_score > 0)
+      return isl_drm_modifier_get_info(best_mod);
+   else
+      return NULL;
+}
+
 VkResult
 anv_image_create(VkDevice _device,
                  const struct anv_image_create_info *create_info,
@@ -524,6 +556,12 @@ anv_image_create(VkDevice _device,
 
    const struct wsi_image_create_info *wsi_info =
       vk_find_struct_const(pCreateInfo->pNext, WSI_IMAGE_CREATE_INFO_MESA);
+   if (wsi_info && wsi_info->modifier_count > 0) {
+      isl_mod_info = choose_drm_format_mod(&device->instance->physicalDevice,
+                                           wsi_info->modifier_count,
+                                           wsi_info->modifiers);
+      assert(isl_mod_info);
+   }
 
    anv_assert(pCreateInfo->mipLevels > 0);
    anv_assert(pCreateInfo->arrayLayers > 0);
@@ -549,6 +587,8 @@ anv_image_create(VkDevice _device,
    image->tiling = pCreateInfo->tiling;
    image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR;
    image->needs_set_tiling = wsi_info && wsi_info->scanout;
+   image->drm_format_mod = isl_mod_info ? isl_mod_info->modifier :
+                                          DRM_FORMAT_MOD_INVALID;
 
    const struct anv_format *format = anv_get_format(image->vk_format);
    assert(format != NULL);
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 3d5259794bc..104b28ee5db 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2412,6 +2412,12 @@ struct anv_image {
     */
    bool needs_set_tiling;
 
+   /**
+    * Must be DRM_FORMAT_MOD_INVALID unless tiling is
+    * VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT.
+    */
+   uint64_t drm_format_mod;
+
    VkDeviceSize size;
    uint32_t alignment;
 
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 6082c3dd093..8913a8022c4 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -33,13 +33,29 @@ anv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
    return anv_lookup_entrypoint(&physical_device->info, pName);
 }
 
+static uint64_t
+anv_wsi_image_get_modifier(VkImage _image)
+{
+   ANV_FROM_HANDLE(anv_image, image, _image);
+   return image->drm_format_mod;
+}
+
 VkResult
 anv_init_wsi(struct anv_physical_device *physical_device)
 {
-   return wsi_device_init(&physical_device->wsi_device,
-                          anv_physical_device_to_handle(physical_device),
-                          anv_wsi_proc_addr,
-                          &physical_device->instance->alloc);
+   VkResult result;
+
+   result = wsi_device_init(&physical_device->wsi_device,
+                            anv_physical_device_to_handle(physical_device),
+                            anv_wsi_proc_addr,
+                            &physical_device->instance->alloc);
+   if (result != VK_SUCCESS)
+      return result;
+
+   physical_device->wsi_device.supports_modifiers = true;
+   physical_device->wsi_device.image_get_modifier = anv_wsi_image_get_modifier;
+
+   return VK_SUCCESS;
 }
 
 void
-- 
2.14.3



More information about the mesa-dev mailing list