[Mesa-dev] [PATCH 13/16] anv/image: Add support for modifiers for WSI

Jason Ekstrand jason at jlekstrand.net
Fri Feb 9 23:43:29 UTC 2018


This adds support for the modifiers portion of the WSI "extension".
---
 src/intel/vulkan/anv_formats.c | 39 ++++++++++++++++++
 src/intel/vulkan/anv_image.c   | 93 +++++++++++++++++++++++++++++++++---------
 src/intel/vulkan/anv_private.h |  6 +++
 src/intel/vulkan/anv_wsi.c     | 24 +++++++++--
 src/vulkan/wsi/wsi_common.c    |  9 ++--
 5 files changed, 142 insertions(+), 29 deletions(-)

diff --git a/src/intel/vulkan/anv_formats.c b/src/intel/vulkan/anv_formats.c
index 4075ae8..cd63879 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,39 @@ 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,
+      I915_FORMAT_MOD_Y_TILED_CCS,
+   };
+
+   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 +711,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 355aff0..9bb0cad 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -508,6 +508,39 @@ 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;
+   case I915_FORMAT_MOD_Y_TILED_CCS: return 4;
+   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 +557,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 +588,8 @@ anv_image_create(VkDevice _device,
    image->tiling = pCreateInfo->tiling;
    image->disjoint = pCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR;
    image->legacy_scanout = 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);
@@ -706,8 +747,13 @@ void anv_GetImageSubresourceLayout(
     VkSubresourceLayout*                        layout)
 {
    ANV_FROM_HANDLE(anv_image, image, _image);
-   const struct anv_surface *surface =
-      get_surface(image, subresource->aspectMask);
+
+   const struct anv_surface *surface;
+   if (subresource->aspectMask == VK_IMAGE_ASPECT_PLANE_1_BIT_KHR &&
+       isl_drm_modifier_has_aux(image->drm_format_mod))
+      surface = &image->planes[0].aux_surface;
+   else
+      surface = get_surface(image, subresource->aspectMask);
 
    assert(__builtin_popcount(subresource->aspectMask) == 1);
 
@@ -822,25 +868,20 @@ anv_layout_to_aux_usage(const struct gen_device_info * const devinfo,
       }
 
 
-   case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
+   case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
       assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
 
-      /* On SKL+, the render buffer can be decompressed by the presentation
-       * engine. Support for this feature has not yet landed in the wider
-       * ecosystem. TODO: Update this code when support lands.
-       *
-       * From the BDW PRM, Vol 7, Render Target Resolve:
-       *
-       *    If the MCS is enabled on a non-multisampled render target, the
-       *    render target must be resolved before being used for other
-       *    purposes (display, texture, CPU lock) The clear value from
-       *    SURFACE_STATE is written into pixels in the render target
-       *    indicated as clear in the MCS.
-       *
-       * Pre-SKL, the render buffer must be resolved before being used for
-       * presentation. We can infer that the auxiliary buffer is not used.
+      /* When handing the image off to the presentation engine, we need to
+       * ensure that things are properly resolved.  For images with no
+       * modifier, we assume that they follow the old rules and always need
+       * a full resolve because the PE doesn't understand any form of
+       * compression.  For images with modifiers, we use the aux usage from
+       * the modifier.
        */
-      return ISL_AUX_USAGE_NONE;
+      const struct isl_drm_modifier_info *mod_info =
+         isl_drm_modifier_get_info(image->drm_format_mod);
+      return mod_info ? mod_info->aux_usage : ISL_AUX_USAGE_NONE;
+   }
 
 
    /* Rendering Layouts */
@@ -920,8 +961,20 @@ anv_layout_to_fast_clear_type(const struct gen_device_info * const devinfo,
    case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
       return ANV_FAST_CLEAR_ANY;
 
-   case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
-      return ANV_FAST_CLEAR_NONE;
+   case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: {
+      assert(image->aspects == VK_IMAGE_ASPECT_COLOR_BIT);
+
+      /* When handing the image off to the presentation engine, we need to
+       * ensure that things are properly resolved.  For images with no
+       * modifier, we assume that they follow the old rules and always need
+       * a full resolve because the PE doesn't understand any form of
+       * compression.  For images with modifiers, we use the value from the
+       * modifier.
+       */
+      const struct isl_drm_modifier_info *mod_info =
+         isl_drm_modifier_get_info(image->drm_format_mod);
+      return mod_info && mod_info->supports_clear_color;
+   }
 
    default:
       /* If the image has CCS_E enabled all the time then we can use
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 3b12ead..c4bf2d0 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2395,6 +2395,12 @@ struct anv_image {
    /** True if this is a legacy scanout image */
    bool legacy_scanout;
 
+   /**
+    * 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 6082c3d..8913a80 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
diff --git a/src/vulkan/wsi/wsi_common.c b/src/vulkan/wsi/wsi_common.c
index 4b4af78..771fbbd 100644
--- a/src/vulkan/wsi/wsi_common.c
+++ b/src/vulkan/wsi/wsi_common.c
@@ -367,13 +367,9 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
    if (result != VK_SUCCESS)
       goto fail;
 
-   if (wsi->supports_modifiers)
+   if (image_modifier_count > 0) {
       image->drm_modifier = wsi->image_get_modifier(image->image);
-   else
-      image->drm_modifier = DRM_FORMAT_MOD_INVALID;
 
-   VkSubresourceLayout image_layout;
-   if (num_modifier_lists > 0) {
       for (uint32_t j = 0; j < modifier_prop_count; j++) {
          if (modifier_props[j].modifier == image->drm_modifier) {
             image->num_planes = modifier_props[j].modifier_plane_count;
@@ -387,6 +383,7 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
             .mipLevel = 0,
             .arrayLayer = 0,
          };
+         VkSubresourceLayout image_layout;
          wsi->GetImageSubresourceLayout(chain->device, image->image,
                                         &image_subresource, &image_layout);
          image->sizes[p] = image_layout.size;
@@ -410,9 +407,11 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
          .mipLevel = 0,
          .arrayLayer = 0,
       };
+      VkSubresourceLayout image_layout;
       wsi->GetImageSubresourceLayout(chain->device, image->image,
                                      &image_subresource, &image_layout);
 
+      image->drm_modifier = DRM_FORMAT_MOD_INVALID;
       image->num_planes = 1;
       image->sizes[0] = reqs.size;
       image->row_pitches[0] = image_layout.rowPitch;
-- 
2.5.0.400.gff86faf



More information about the mesa-dev mailing list