vulkan/wsi: Add modifiers support to wsi_create_native_image
authorJason Ekstrand <jason@jlekstrand.net>
Fri, 9 Feb 2018 23:43:27 +0000 (15:43 -0800)
committerDaniel Stone <daniels@collabora.com>
Wed, 21 Feb 2018 22:37:10 +0000 (22:37 +0000)
This involves extending our fake extension a bit to allow for additional
querying and passing of modifier information.  The added bits are
intended to look a lot like the draft of VK_EXT_image_drm_format_modifier.
Once the extension gets finalized, we'll simply transition all of the
structs used in wsi_common to the real extension structs.

Reviewed-by: Daniel Stone <daniels@collabora.com>
src/vulkan/wsi/wsi_common.c
src/vulkan/wsi/wsi_common.h
src/vulkan/wsi/wsi_common_private.h
src/vulkan/wsi/wsi_common_wayland.c
src/vulkan/wsi/wsi_common_x11.c

index c235128e562d0f429da7419fa576bcf54997063b..edba13a13de1a9493ecb56aa7fe302ab00307942 100644 (file)
@@ -26,6 +26,8 @@
 #include "util/macros.h"
 #include "vk_util.h"
 
+#include <unistd.h>
+
 VkResult
 wsi_device_init(struct wsi_device *wsi,
                 VkPhysicalDevice pdevice,
@@ -36,6 +38,8 @@ wsi_device_init(struct wsi_device *wsi,
 
    memset(wsi, 0, sizeof(*wsi));
 
+   wsi->pdevice = pdevice;
+
 #define WSI_GET_CB(func) \
    PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
    WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
@@ -69,6 +73,7 @@ wsi_device_init(struct wsi_device *wsi,
    WSI_GET_CB(GetImageSubresourceLayout);
    WSI_GET_CB(GetMemoryFdKHR);
    WSI_GET_CB(GetPhysicalDeviceFormatProperties);
+   WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
    WSI_GET_CB(ResetFences);
    WSI_GET_CB(QueueSubmit);
    WSI_GET_CB(WaitForFences);
@@ -196,6 +201,9 @@ align_u32(uint32_t v, uint32_t a)
 VkResult
 wsi_create_native_image(const struct wsi_swapchain *chain,
                         const VkSwapchainCreateInfoKHR *pCreateInfo,
+                        uint32_t num_modifier_lists,
+                        const uint32_t *num_modifiers,
+                        const uint64_t *const *modifiers,
                         struct wsi_image *image)
 {
    const struct wsi_device *wsi = chain->wsi;
@@ -205,11 +213,91 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
    for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
       image->fds[i] = -1;
 
-   const struct wsi_image_create_info image_wsi_info = {
+   struct wsi_image_create_info image_wsi_info = {
       .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
       .pNext = NULL,
-      .scanout = true,
    };
+
+   uint32_t image_modifier_count = 0, modifier_prop_count = 0;
+   struct wsi_format_modifier_properties *modifier_props = NULL;
+   uint64_t *image_modifiers = NULL;
+   if (num_modifier_lists == 0) {
+      /* If we don't have modifiers, fall back to the legacy "scanout" flag */
+      image_wsi_info.scanout = true;
+   } else {
+      /* The winsys can't request modifiers if we don't support them. */
+      assert(wsi->supports_modifiers);
+      struct wsi_format_modifier_properties_list modifier_props_list = {
+         .sType = VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA,
+         .pNext = NULL,
+      };
+      VkFormatProperties2KHR format_props = {
+         .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR,
+         .pNext = &modifier_props_list,
+      };
+      wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
+                                                 pCreateInfo->imageFormat,
+                                                 &format_props);
+      assert(modifier_props_list.modifier_count > 0);
+      modifier_props = vk_alloc(&chain->alloc,
+                                sizeof(*modifier_props) *
+                                modifier_props_list.modifier_count,
+                                8,
+                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+      if (!modifier_props) {
+         result = VK_ERROR_OUT_OF_HOST_MEMORY;
+         goto fail;
+      }
+
+      modifier_props_list.modifier_properties = modifier_props;
+      wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
+                                                 pCreateInfo->imageFormat,
+                                                 &format_props);
+      modifier_prop_count = modifier_props_list.modifier_count;
+
+      uint32_t max_modifier_count = 0;
+      for (uint32_t l = 0; l < num_modifier_lists; l++)
+         max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
+
+      image_modifiers = vk_alloc(&chain->alloc,
+                                 sizeof(*image_modifiers) *
+                                 max_modifier_count,
+                                 8,
+                                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+      if (!image_modifiers) {
+         result = VK_ERROR_OUT_OF_HOST_MEMORY;
+         goto fail;
+      }
+
+      image_modifier_count = 0;
+      for (uint32_t l = 0; l < num_modifier_lists; l++) {
+         /* Walk the modifier lists and construct a list of supported
+          * modifiers.
+          */
+         for (uint32_t i = 0; i < num_modifiers[l]; i++) {
+            for (uint32_t j = 0; j < modifier_prop_count; j++) {
+               if (modifier_props[j].modifier == modifiers[l][i])
+                  image_modifiers[image_modifier_count++] = modifiers[l][i];
+            }
+         }
+
+         /* We only want to take the modifiers from the first list */
+         if (image_modifier_count > 0)
+            break;
+      }
+
+      if (image_modifier_count > 0) {
+         image_wsi_info.modifier_count = image_modifier_count;
+         image_wsi_info.modifiers = image_modifiers;
+      } else {
+         /* TODO: Add a proper error here */
+         assert(!"Failed to find a supported modifier!  This should never "
+                 "happen because LINEAR should always be available");
+         result = VK_ERROR_OUT_OF_HOST_MEMORY;
+         goto fail;
+      }
+   }
+
    const VkImageCreateInfo image_info = {
       .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
       .pNext = &image_wsi_info,
@@ -239,15 +327,6 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
    VkMemoryRequirements reqs;
    wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
 
-   VkSubresourceLayout image_layout;
-   const VkImageSubresource image_subresource = {
-      .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
-      .mipLevel = 0,
-      .arrayLayer = 0,
-   };
-   wsi->GetImageSubresourceLayout(chain->device, image->image,
-                                  &image_subresource, &image_layout);
-
    const struct wsi_memory_allocate_info memory_wsi_info = {
       .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
       .pNext = NULL,
@@ -292,16 +371,67 @@ wsi_create_native_image(const struct wsi_swapchain *chain,
    if (result != VK_SUCCESS)
       goto fail;
 
-   image->drm_modifier = DRM_FORMAT_MOD_INVALID;
-   image->num_planes = 1;
-   image->sizes[0] = reqs.size;
-   image->row_pitches[0] = image_layout.rowPitch;
-   image->offsets[0] = 0;
-   image->fds[0] = fd;
+   if (num_modifier_lists > 0) {
+      image->drm_modifier = wsi->image_get_modifier(image->image);
+      assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
+
+      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;
+            break;
+         }
+      }
+
+      for (uint32_t p = 0; p < image->num_planes; p++) {
+         const VkImageSubresource image_subresource = {
+            .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT_KHR << p,
+            .mipLevel = 0,
+            .arrayLayer = 0,
+         };
+         VkSubresourceLayout image_layout;
+         wsi->GetImageSubresourceLayout(chain->device, image->image,
+                                        &image_subresource, &image_layout);
+         image->sizes[p] = image_layout.size;
+         image->row_pitches[p] = image_layout.rowPitch;
+         image->offsets[p] = image_layout.offset;
+         if (p == 0) {
+            image->fds[p] = fd;
+         } else {
+            image->fds[p] = dup(fd);
+            if (image->fds[p] == -1) {
+               for (uint32_t i = 0; i < p; i++)
+                  close(image->fds[p]);
+
+               goto fail;
+            }
+         }
+      }
+   } else {
+      const VkImageSubresource image_subresource = {
+         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+         .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;
+      image->offsets[0] = 0;
+      image->fds[0] = fd;
+   }
+
+   vk_free(&chain->alloc, modifier_props);
+   vk_free(&chain->alloc, image_modifiers);
 
    return VK_SUCCESS;
 
 fail:
+   vk_free(&chain->alloc, modifier_props);
+   vk_free(&chain->alloc, image_modifiers);
    wsi_destroy_image(chain, image);
 
    return result;
index 3e0d3be1c24155aa395ab9463e56f32a3e61c545..6cf729ba025f4072b3584b44ea50e390291aaaf8 100644 (file)
  */
 #define VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA (VkStructureType)1000001002
 #define VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA (VkStructureType)1000001003
+#define VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA (VkStructureType)1000001004
 
 struct wsi_image_create_info {
     VkStructureType sType;
     const void *pNext;
     bool scanout;
+
+    uint32_t modifier_count;
+    const uint64_t *modifiers;
 };
 
 struct wsi_memory_allocate_info {
@@ -48,14 +52,32 @@ struct wsi_memory_allocate_info {
     bool implicit_sync;
 };
 
+struct wsi_format_modifier_properties {
+   uint64_t modifier;
+   uint32_t modifier_plane_count;
+};
+
+/* Chain in for vkGetPhysicalDeviceFormatProperties2KHR */
+struct wsi_format_modifier_properties_list {
+   VkStructureType sType;
+   const void *pNext;
+
+   uint32_t modifier_count;
+   struct wsi_format_modifier_properties *modifier_properties;
+};
+
 struct wsi_interface;
 
 #define VK_ICD_WSI_PLATFORM_MAX 5
 
 struct wsi_device {
+   VkPhysicalDevice pdevice;
    VkPhysicalDeviceMemoryProperties memory_props;
    uint32_t queue_family_count;
 
+   bool supports_modifiers;
+   uint64_t (*image_get_modifier)(VkImage image);
+
 #define WSI_CB(cb) PFN_vk##cb cb
    WSI_CB(AllocateMemory);
    WSI_CB(AllocateCommandBuffers);
@@ -79,6 +101,7 @@ struct wsi_device {
    WSI_CB(GetImageSubresourceLayout);
    WSI_CB(GetMemoryFdKHR);
    WSI_CB(GetPhysicalDeviceFormatProperties);
+   WSI_CB(GetPhysicalDeviceFormatProperties2KHR);
    WSI_CB(ResetFences);
    WSI_CB(QueueSubmit);
    WSI_CB(WaitForFences);
index 781e84635f9d779db52f8d4b4c70044227e426e0..b608119b96962919e7ac45e8e3aeb8241207db39 100644 (file)
@@ -81,6 +81,9 @@ void wsi_swapchain_finish(struct wsi_swapchain *chain);
 VkResult
 wsi_create_native_image(const struct wsi_swapchain *chain,
                         const VkSwapchainCreateInfoKHR *pCreateInfo,
+                        uint32_t num_modifier_lists,
+                        const uint32_t *num_modifiers,
+                        const uint64_t *const *modifiers,
                         struct wsi_image *image);
 
 VkResult
index 8290170c9ec38b232559b81125aea769f936864f..1162b92c35fca97a11503a710cd3ffc4ad1e0698 100644 (file)
@@ -708,7 +708,8 @@ wsi_wl_image_init(struct wsi_wl_swapchain *chain,
 {
    VkResult result;
 
-   result = wsi_create_native_image(&chain->base, pCreateInfo, &image->base);
+   result = wsi_create_native_image(&chain->base, pCreateInfo,
+                                    0, NULL, NULL, &image->base);
    if (result != VK_SUCCESS)
       return result;
 
index b42b8234064c1aff81999c0d66dc530dd26428a4..2cc7a67c63febe065e9257fb2fc2c4f5ee0cc92e 100644 (file)
@@ -929,7 +929,8 @@ x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
    if (chain->base.use_prime_blit) {
       result = wsi_create_prime_image(&chain->base, pCreateInfo, &image->base);
    } else {
-      result = wsi_create_native_image(&chain->base, pCreateInfo, &image->base);
+      result = wsi_create_native_image(&chain->base, pCreateInfo,
+                                       0, NULL, NULL, &image->base);
    }
    if (result != VK_SUCCESS)
       return result;