anv: implement VK_KHR_swapchain revision 70
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>
Mon, 25 Mar 2019 15:02:47 +0000 (15:02 +0000)
committerLionel Landwerlin <lionel.g.landwerlin@intel.com>
Mon, 8 Apr 2019 17:27:02 +0000 (18:27 +0100)
This revision allows for images to be :

   - created by reusing image parameters from swapchain

   - bound to memory from a swapchain

v2: Add color attachment flag
    Use same implicit WSI parameters (tiling, samples, usage)

v3: Fix missing break in vk_foreach_struct_const() switch (Lionel)

v4: Fix accessing image aspects before android resolve (Tapani)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Tapani Pälli <tapani.palli@intel.com>
src/intel/vulkan/anv_extensions.py
src/intel/vulkan/anv_image.c
src/intel/vulkan/anv_private.h
src/vulkan/util/vk_util.h

index 0d691b59004c36a00191f3f8971aec1af96eb48d..37c1203416e9ade63e9c00e79288dc7c516365df 100644 (file)
@@ -108,7 +108,7 @@ EXTENSIONS = [
     Extension('VK_KHR_storage_buffer_storage_class',      1, True),
     Extension('VK_KHR_surface',                          25, 'ANV_HAS_SURFACE'),
     Extension('VK_KHR_surface_protected_capabilities',    1, 'ANV_HAS_SURFACE'),
-    Extension('VK_KHR_swapchain',                        68, 'ANV_HAS_SURFACE'),
+    Extension('VK_KHR_swapchain',                        70, 'ANV_HAS_SURFACE'),
     Extension('VK_KHR_variable_pointers',                 1, True),
     Extension('VK_KHR_wayland_surface',                   6, 'VK_USE_PLATFORM_WAYLAND_KHR'),
     Extension('VK_KHR_xcb_surface',                       6, 'VK_USE_PLATFORM_XCB_KHR'),
index 6ed7748148880e897b5d13880d7aac016dc4ec81..3841234df14c5313944aa0aac9c34806b506bf84 100644 (file)
@@ -638,6 +638,70 @@ fail:
    return r;
 }
 
+static struct anv_image *
+anv_swapchain_get_image(VkSwapchainKHR swapchain,
+                        uint32_t index)
+{
+   uint32_t n_images = index + 1;
+   VkImage *images = malloc(sizeof(*images) * n_images);
+   VkResult result = wsi_common_get_images(swapchain, &n_images, images);
+
+   if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
+      free(images);
+      return NULL;
+   }
+
+   ANV_FROM_HANDLE(anv_image, image, images[index]);
+   free(images);
+
+   return image;
+}
+
+static VkResult
+anv_image_from_swapchain(VkDevice device,
+                         const VkImageCreateInfo *pCreateInfo,
+                         const VkImageSwapchainCreateInfoKHR *swapchain_info,
+                         const VkAllocationCallbacks *pAllocator,
+                         VkImage *pImage)
+{
+   struct anv_image *swapchain_image = anv_swapchain_get_image(swapchain_info->swapchain, 0);
+   assert(swapchain_image);
+
+   assert(swapchain_image->type == pCreateInfo->imageType);
+   assert(swapchain_image->vk_format == pCreateInfo->format);
+   assert(swapchain_image->extent.width == pCreateInfo->extent.width);
+   assert(swapchain_image->extent.height == pCreateInfo->extent.height);
+   assert(swapchain_image->extent.depth == pCreateInfo->extent.depth);
+   assert(swapchain_image->array_size == pCreateInfo->arrayLayers);
+   /* Color attachment is added by the wsi code. */
+   assert(swapchain_image->usage == (pCreateInfo->usage | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
+
+   VkImageCreateInfo local_create_info;
+   local_create_info = *pCreateInfo;
+   local_create_info.pNext = NULL;
+   /* The following parameters are implictly selected by the wsi code. */
+   local_create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
+   local_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
+   local_create_info.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+
+   /* If the image has a particular modifier, specify that modifier. */
+   struct wsi_image_create_info local_wsi_info = {
+      .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
+      .modifier_count = 1,
+      .modifiers = &swapchain_image->drm_format_mod,
+   };
+   if (swapchain_image->drm_format_mod != DRM_FORMAT_MOD_INVALID)
+      __vk_append_struct(&local_create_info, &local_wsi_info);
+
+   return anv_image_create(device,
+      &(struct anv_image_create_info) {
+         .vk_info = &local_create_info,
+         .external_format = swapchain_image->external_format,
+      },
+      pAllocator,
+      pImage);
+}
+
 VkResult
 anv_CreateImage(VkDevice device,
                 const VkImageCreateInfo *pCreateInfo,
@@ -658,6 +722,12 @@ anv_CreateImage(VkDevice device,
       return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,
                                     pAllocator, pImage);
 
+   const VkImageSwapchainCreateInfoKHR *swapchain_info =
+      vk_find_struct_const(pCreateInfo->pNext, IMAGE_SWAPCHAIN_CREATE_INFO_KHR);
+   if (swapchain_info && swapchain_info->swapchain != VK_NULL_HANDLE)
+      return anv_image_from_swapchain(device, pCreateInfo, swapchain_info,
+                                      pAllocator, pImage);
+
    return anv_image_create(device,
       &(struct anv_image_create_info) {
          .vk_info = pCreateInfo,
@@ -818,7 +888,8 @@ VkResult anv_BindImageMemory2(
       ANV_FROM_HANDLE(anv_device_memory, mem, bind_info->memory);
       ANV_FROM_HANDLE(anv_image, image, bind_info->image);
 
-      if (mem->ahw)
+      /* Resolve will alter the image's aspects, do this first. */
+      if (mem && mem->ahw)
          resolve_ahw_image(device, image, mem);
 
       VkImageAspectFlags aspects = image->aspects;
@@ -831,12 +902,41 @@ VkResult anv_BindImageMemory2(
             aspects = plane_info->planeAspect;
             break;
          }
+         case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: {
+            const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
+               (const VkBindImageMemorySwapchainInfoKHR *) s;
+            struct anv_image *swapchain_image =
+               anv_swapchain_get_image(swapchain_info->swapchain,
+                                       swapchain_info->imageIndex);
+            assert(swapchain_image);
+            assert(image->aspects == swapchain_image->aspects);
+            assert(mem == NULL);
+
+            uint32_t aspect_bit;
+            anv_foreach_image_aspect_bit(aspect_bit, image, aspects) {
+               uint32_t plane =
+                  anv_image_aspect_to_plane(image->aspects, 1UL << aspect_bit);
+               struct anv_device_memory mem = {
+                  .bo = swapchain_image->planes[plane].address.bo,
+               };
+               anv_image_bind_memory_plane(device, image, plane,
+                                           &mem, bind_info->memoryOffset);
+            }
+            break;
+         }
          default:
             anv_debug_ignored_stype(s->sType);
             break;
          }
       }
 
+      /* VkBindImageMemorySwapchainInfoKHR requires memory to be
+       * VK_NULL_HANDLE. In such case, just carry one with the next bind
+       * item.
+       */
+      if (!mem)
+         continue;
+
       uint32_t aspect_bit;
       anv_foreach_image_aspect_bit(aspect_bit, image, aspects) {
          uint32_t plane =
index daeadea3a6449fc21a53a3839ffb16b65b2dca12..1316077ae09e1ffade29dad939484e667454ee7e 100644 (file)
@@ -2881,7 +2881,7 @@ struct anv_surface {
 };
 
 struct anv_image {
-   VkImageType type;
+   VkImageType type; /**< VkImageCreateInfo::imageType */
    /* The original VkFormat provided by the client.  This may not match any
     * of the actual surface formats.
     */
index 89b90a60d207d1c551b5837837b6771b4ce33824..8ae384b9fb514d96fa22570734853b064c805c94 100644 (file)
@@ -196,6 +196,18 @@ __vk_find_struct(void *start, VkStructureType sType)
 #define vk_find_struct_const(__start, __sType) \
    (const void *)__vk_find_struct((void *)(__start), VK_STRUCTURE_TYPE_##__sType)
 
+static inline void
+__vk_append_struct(void *start, void *element)
+{
+   vk_foreach_struct(s, start) {
+      if (s->pNext)
+         continue;
+
+      s->pNext = (struct VkBaseOutStructure *) element;
+      break;
+   }
+}
+
 uint32_t vk_get_driver_version(void);
 
 uint32_t vk_get_version_override(void);