[RFC v3 19/22] vulkan/wsi: Add modifiers to wsi_image_create

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Wed Sep 27 05:28:49 UTC 2017


From: Daniel Stone <daniels at collabora.com>

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           | 36 +++++++++++++++++++++++++++++--
 src/intel/vulkan/anv_image.c        |  9 ++++++--
 src/intel/vulkan/anv_private.h      |  3 +++
 src/intel/vulkan/anv_wsi.c          | 42 ++++++++++++++++++++++++++++++++++---
 src/vulkan/wsi/wsi_common.h         |  3 +++
 src/vulkan/wsi/wsi_common_wayland.c |  3 +++
 src/vulkan/wsi/wsi_common_x11.c     |  3 +++
 7 files changed, 92 insertions(+), 7 deletions(-)

diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c
index dd820dc431..b2d0ad8eab 100644
--- a/src/amd/vulkan/radv_wsi.c
+++ b/src/amd/vulkan/radv_wsi.c
@@ -226,11 +226,42 @@ radv_wsi_image_create(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)
 {
 	VkResult result = VK_SUCCESS;
 	struct radeon_surf *surface;
 	struct radv_image *image;
+	bool linear;
+
+	/* If modifiers are provided, then try to use them. Unfortunately,
+	 * as there are no modifiers actually defined for AMD, if we're
+	 * provided with an explicit list of modifiers, then all we can do
+	 * is try to use linear.
+	 */
+	if (num_tranche == 0) {
+		linear = different_gpu;
+	} else {
+		bool linear_found = false;
+		for (int i = 0; i < num_tranches; i++) {
+			for (int j = 0; j < num_modifiers; j++) {
+				if (modifiers[i][j] == DRM_FORMAT_MOD_LINEAR) {
+					linear = true;
+					linear_found = true;
+					break;
+				}
+			}
+		}
+
+		/* The right error is probably more like SURFACE_LOST, since
+		 * we'll never be able to allocate for the surface with these
+		 * attributes, but then we'd have to lose the surface.
+		 */
+		if (!linear_found)
+			return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+	}
 
 	result = radv_wsi_image_alloc(device_h, pCreateInfo, pAllocator,
 				      false, &wsi_image->image,
@@ -238,7 +269,7 @@ radv_wsi_image_create(VkDevice device_h,
 	if (result != VK_SUCCESS)
 		return result;
 
-	if (different_gpu) {
+	if (linear) {
 		result = radv_wsi_image_alloc(device_h, pCreateInfo, pAllocator,
 					      true, &wsi_image->linear_image,
 					      &wsi_image->linear_memory);
@@ -260,7 +291,8 @@ radv_wsi_image_create(VkDevice device_h,
 		goto fail;
 
 	wsi_image->num_planes = 1;
-	wsi_image->drm_modifier = DRM_FORMAT_MOD_INVALID;
+	wsi_image->drm_modifier =
+		linear ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
 	wsi_image->sizes[0] = image->size;
 	wsi_image->offsets[0] = image->offset;
 	if (device->physical_device->rad_info.chip_class >= GFX9)
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c
index 7561b9b52b..7c47a17a13 100644
--- a/src/intel/vulkan/anv_image.c
+++ b/src/intel/vulkan/anv_image.c
@@ -250,12 +250,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);
 
@@ -295,7 +299,8 @@ make_surface(const struct anv_device *dev,
       .min_alignment = 0,
       .row_pitch = anv_info->stride,
       .usage = choose_isl_surf_usage(vk_info->flags, image->usage, aspect),
-      .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 355adbac91..49156c3cba 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -2442,6 +2442,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;
+
    uint32_t stride;
 };
 
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 750bc645ae..978a66896f 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -173,18 +173,54 @@ anv_wsi_image_create(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)
 {
    struct anv_device *device = anv_device_from_handle(device_h);
    VkImage image_h;
    struct anv_image *image;
-   isl_tiling_flags_t isl_tiling = ISL_TILING_X_BIT;
+   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;
+
    VkResult result;
    result = anv_image_create(anv_device_to_handle(device),
       &(struct anv_image_create_info) {
-         .isl_tiling_flags = isl_tiling,
+         .isl_tiling_flags = isl_tiling[0],
+         .isl_suboptimal_tiling_flags = isl_tiling[1],
          .stride = 0,
          .vk_info =
       &(VkImageCreateInfo) {
@@ -237,7 +273,7 @@ anv_wsi_image_create(VkDevice device_h,
    anv_BindImageMemory(device_h, image_h, memory_h, 0);
 
    struct anv_surface *surface = &image->color_surface;
-   assert(isl_tiling & (1 << surface->isl.tiling));
+   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,
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 8172f4b318..99836054ca 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -50,6 +50,9 @@ struct wsi_image_fns {
                                 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,
diff --git a/src/vulkan/wsi/wsi_common_wayland.c b/src/vulkan/wsi/wsi_common_wayland.c
index 22d7785a7a..3a07315e34 100644
--- a/src/vulkan/wsi/wsi_common_wayland.c
+++ b/src/vulkan/wsi/wsi_common_wayland.c
@@ -698,6 +698,9 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
                                                     pCreateInfo,
                                                     pAllocator,
                                                     false,
+                                                    NULL,
+                                                    NULL,
+                                                    0,
                                                     &image->base);
    if (result != VK_SUCCESS)
       return result;
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index 784d275dc5..8bc6dc9125 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -962,6 +962,9 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
                                                     pCreateInfo,
                                                     pAllocator,
                                                     chain->base.needs_linear_copy,
+                                                    NULL,
+                                                    NULL,
+                                                    0,
                                                     &image->base);
    if (result != VK_SUCCESS)
       return result;
-- 
2.13.0



More information about the xorg-devel mailing list