anv/image: Add support for modifiers for WSI
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 14 Nov 2017 00:44:07 +0000 (16:44 -0800)
committerDaniel Stone <daniels@collabora.com>
Wed, 21 Feb 2018 22:37:10 +0000 (22:37 +0000)
This adds support for the modifiers portion of the WSI "extension".

Reviewed-by: Daniel Stone <daniels@collabora.com>
src/intel/vulkan/anv_formats.c
src/intel/vulkan/anv_image.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/anv_wsi.c

index 4075ae8e6209bb517bf92636ac15d7962f12ab52..9c52ad5acbd79275489a88366da62c15dd9f6ccc 100644 (file)
@@ -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;
index c3d1810cee80ea670a500012f4c5cb24cfe8c4cc..a2bae7b3827f2449f5438372c9bbcbfbb7609f00 100644 (file)
@@ -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);
index 3d5259794bc6e5a8bc9e8c1a1b465a0cd3b89ecb..104b28ee5db503e55e5109064403ffb492af21c1 100644 (file)
@@ -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;
 
index 6082c3dd0937262c02e31140bdf09f348b514315..8913a8022c4d8954770298d634cf29509c9332f6 100644 (file)
@@ -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