[Mesa-dev] [RFC v5 16/19] vulkan/wsi: Add wsi_image_create_with_modifiers

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Mon Nov 6 22:02:46 UTC 2017


Allow the winsys to provide a set of acceptable modifiers to the driver
when creating WSI images.

Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/amd/vulkan/radv_wsi.c      |   3 ++
 src/intel/vulkan/anv_image.c   |   9 +++-
 src/intel/vulkan/anv_private.h |   3 ++
 src/intel/vulkan/anv_wsi.c     | 101 ++++++++++++++++++++++++++++++++++++-----
 src/vulkan/wsi/wsi_common.h    |  11 +++++
 5 files changed, 114 insertions(+), 13 deletions(-)

diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index c4c6ff9736..a1881eaa35 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -223,6 +223,8 @@ radv_wsi_image_create(VkDevice device_h,
 
 	wsi_image->image = image_h;
 	wsi_image->memory = memory_h;
+	wsi_image->linear_image = VK_NULL_HANDLE;
+	wsi_image->linear_memory = VK_NULL_HANDLE;
 	wsi_image->num_planes = 1;
 	wsi_image->drm_modifier = DRM_FORMAT_MOD_INVALID;
 	wsi_image->sizes[0] = image->size;
@@ -256,6 +258,7 @@ radv_wsi_image_free(VkDevice device,
 
 static const struct wsi_image_fns radv_wsi_image_fns = {
    .create_wsi_image = radv_wsi_image_create,
+   .create_wsi_image_with_modifiers = NULL,
    .free_wsi_image = radv_wsi_image_free,
 };
 
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index cd96bfd0d6..262f6805dc 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -274,12 +274,16 @@ make_surface(const struct anv_device *dev,
    /* Translate the Vulkan tiling to an equivalent ISL tiling, then filter the
     * result with an optionally provided ISL tiling argument.
     */
-   isl_tiling_flags_t tiling_flags =
+   isl_tiling_flags_t mask =
       (vk_info->tiling == VK_IMAGE_TILING_LINEAR) ?
       ISL_TILING_LINEAR_BIT : ISL_TILING_ANY_MASK;
+   isl_tiling_flags_t tiling_flags = mask;
+   isl_tiling_flags_t suboptimal_tiling_flags = 0;
 
    if (anv_info->isl_tiling_flags)
       tiling_flags &= anv_info->isl_tiling_flags;
+   if (anv_info->isl_suboptimal_tiling_flags)
+      suboptimal_tiling_flags = anv_info->isl_suboptimal_tiling_flags & mask;
 
    assert(tiling_flags);
 
@@ -322,7 +326,8 @@ make_surface(const struct anv_device *dev,
       .min_alignment = 0,
       .row_pitch = anv_info->stride,
       .usage = usage,
-      .tiling_flags = tiling_flags);
+      .tiling_flags = tiling_flags,
+      .suboptimal_tiling_flags = suboptimal_tiling_flags);
 
    /* isl_surf_init() will fail only if provided invalid input. Invalid input
     * is illegal in Vulkan.
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index 8de5103453..5e5010fde9 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2630,6 +2630,9 @@ struct anv_image_create_info {
    /** An opt-in bitmask which filters an ISL-mapping of the Vulkan tiling. */
    isl_tiling_flags_t isl_tiling_flags;
 
+   /** Set of possible but suboptimal tiling flags. */
+   isl_tiling_flags_t isl_suboptimal_tiling_flags;
+
    /** These flags will be added to any derived from VkImageCreateInfo. */
    isl_surf_usage_flags_t isl_extra_usage_flags;
 
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 740bbff9d3..f41db86f12 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -169,12 +169,13 @@ VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
 
 
 static VkResult
-anv_wsi_image_create(VkDevice device_h,
-                     const VkSwapchainCreateInfoKHR *pCreateInfo,
-                     const VkAllocationCallbacks* pAllocator,
-                     bool should_export,
-                     bool different_gpu,
-                     struct wsi_image_base *wsi_image)
+anv_wsi_image_alloc(VkDevice device_h,
+                    const VkSwapchainCreateInfoKHR *pCreateInfo,
+                    const VkAllocationCallbacks* pAllocator,
+                    bool should_export,
+                    isl_tiling_flags_t *isl_tiling,
+                    VkImageTiling vk_tiling,
+                    struct wsi_image_base *wsi_image)
 {
    struct anv_device *device = anv_device_from_handle(device_h);
    VkImage image_h;
@@ -183,7 +184,8 @@ anv_wsi_image_create(VkDevice device_h,
    VkResult result;
    result = anv_image_create(anv_device_to_handle(device),
       &(struct anv_image_create_info) {
-         .isl_tiling_flags = ISL_TILING_X_BIT,
+         .isl_tiling_flags = isl_tiling[0],
+         .isl_suboptimal_tiling_flags = isl_tiling[1],
          .stride = 0,
          .vk_info =
       &(VkImageCreateInfo) {
@@ -198,8 +200,7 @@ anv_wsi_image_create(VkDevice device_h,
          .mipLevels = 1,
          .arrayLayers = 1,
          .samples = 1,
-         /* FIXME: Need a way to use X tiling to allow scanout */
-         .tiling = VK_IMAGE_TILING_OPTIMAL,
+         .tiling = vk_tiling,
          .usage = (pCreateInfo->imageUsage |
                    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT),
          .flags = 0,
@@ -238,10 +239,11 @@ anv_wsi_image_create(VkDevice device_h,
    assert(image->planes[0].offset == 0);
 
    struct anv_surface *surface = &image->planes[0].surface;
-   assert(surface->isl.tiling == ISL_TILING_X);
+   assert((isl_tiling[0] | isl_tiling[1]) & (1 << surface->isl.tiling));
 
    int ret = anv_gem_set_tiling(device, memory->bo->gem_handle,
-                                surface->isl.row_pitch, I915_TILING_X);
+                                surface->isl.row_pitch,
+                                isl_tiling_to_i915_tiling(surface->isl.tiling));
    if (ret) {
       /* FINISHME: Choose a better error. */
       result = vk_errorf(device->instance, device,
@@ -266,6 +268,8 @@ anv_wsi_image_create(VkDevice device_h,
 
    wsi_image->image = image_h;
    wsi_image->memory = memory_h;
+   wsi_image->linear_image = VK_NULL_HANDLE;
+   wsi_image->linear_memory = VK_NULL_HANDLE;
 
    /* We don't yet allow sharing of aux planes with the winsys. Doing so
     * would require a separate external_aux_usage member in the anv_image,
@@ -289,6 +293,80 @@ fail_create_image:
    return result;
 }
 
+static VkResult
+anv_wsi_image_create(VkDevice device_h,
+                     const VkSwapchainCreateInfoKHR *pCreateInfo,
+                     const VkAllocationCallbacks* pAllocator,
+                     bool should_export,
+                     bool different_gpu,
+                     struct wsi_image_base *wsi_image)
+{
+   isl_tiling_flags_t isl_tiling[2] = {ISL_TILING_X_BIT, 0};
+   VkImageTiling vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+
+   return anv_wsi_image_alloc(device_h,
+                              pCreateInfo,
+                              pAllocator,
+                              should_export,
+                              isl_tiling,
+                              vk_tiling,
+                              wsi_image);
+}
+
+static VkResult
+anv_wsi_image_create_with_modifiers(VkDevice device_h,
+                                    const VkSwapchainCreateInfoKHR *pCreateInfo,
+                                    const VkAllocationCallbacks* pAllocator,
+                                    bool different_gpu,
+                                    uint64_t **modifiers,
+                                    int *num_modifiers,
+                                    int num_tranches,
+                                    struct wsi_image_base *wsi_image)
+{
+   isl_tiling_flags_t isl_tiling[2] = {0,};
+   VkImageTiling vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+
+   assert(num_tranches >= 0 && num_tranches <= 2);
+
+   /* If we haven't been provided any modifiers, fall back to our previous
+    * default of X-tiling, which the other side can infer through the BO
+    * get_tiling ioctl. */
+   if (num_tranches == 0) {
+      isl_tiling[0] = ISL_TILING_X_BIT;
+   } else {
+      for (int i = 0; i < num_tranches; i++) {
+         for (int j = 0; j < num_modifiers[i]; j++) {
+            const struct isl_drm_modifier_info *info =
+               isl_drm_modifier_get_info(modifiers[i][j]);
+            if (!info || info->aux_usage != ISL_AUX_USAGE_NONE)
+               continue;
+            isl_tiling[i] |= (1 << info->tiling);
+         }
+      }
+   }
+
+   /* This isn't strictly correct; really we want something more like
+    * SURFACE_LOST, because we'll never be able to render to it in these
+    * conditions.
+    */
+   if (isl_tiling[0] == 0)
+      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+
+   if (isl_tiling[0] & ISL_TILING_NON_LINEAR_MASK ||
+       isl_tiling[1] & ISL_TILING_NON_LINEAR_MASK)
+      vk_tiling = VK_IMAGE_TILING_OPTIMAL;
+   else
+      vk_tiling = VK_IMAGE_TILING_LINEAR;
+
+   return anv_wsi_image_alloc(device_h,
+                              pCreateInfo,
+                              pAllocator,
+                              true,
+                              isl_tiling,
+                              vk_tiling,
+                              wsi_image);
+}
+
 static void
 anv_wsi_image_free(VkDevice device,
                    const VkAllocationCallbacks* pAllocator,
@@ -301,6 +379,7 @@ anv_wsi_image_free(VkDevice device,
 
 static const struct wsi_image_fns anv_wsi_image_fns = {
    .create_wsi_image = anv_wsi_image_create,
+   .create_wsi_image_with_modifiers = anv_wsi_image_create_with_modifiers,
    .free_wsi_image = anv_wsi_image_free,
 };
 
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index d808a4cfdc..0741e59875 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -33,6 +33,8 @@
 struct wsi_image_base {
    VkImage image;
    VkDeviceMemory memory;
+   VkImage linear_image;
+   VkDeviceMemory linear_memory;
 
    uint64_t drm_modifier;
    int num_planes;
@@ -50,6 +52,15 @@ struct wsi_image_fns {
                                 bool should_export,
                                 bool different_gpu,
                                 struct wsi_image_base *image_p);
+
+   VkResult (*create_wsi_image_with_modifiers)(VkDevice device_h,
+                                               const VkSwapchainCreateInfoKHR *pCreateInfo,
+                                               const VkAllocationCallbacks *pAllocator,
+                                               bool different_gpu,
+                                               uint64_t **modifiers,
+                                               int *num_modifiers,
+                                               int num_tranches,
+                                               struct wsi_image_base *image_p);
    void (*free_wsi_image)(VkDevice device,
                           const VkAllocationCallbacks *pAllocator,
                           struct wsi_image_base *image);
-- 
2.13.0



More information about the mesa-dev mailing list