Mesa (master): venus: handle wsi image queue ownership transfer for Android

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Apr 29 17:43:49 UTC 2021


Module: Mesa
Branch: master
Commit: 96ec6b3d8fa828bd4bc58cd2183797953caaa405
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=96ec6b3d8fa828bd4bc58cd2183797953caaa405

Author: Yiwei Zhang <zzyiwei at chromium.org>
Date:   Wed Apr 28 23:03:10 2021 +0000

venus: handle wsi image queue ownership transfer for Android

1. pre-allocate command pools at device creation if anb enabled
2. force VK_SHARING_MODE_CONCURRENT for wsi image if necessary
3. pre-allocate and record command buffers at android wsi image creation
4. transfer in the ownership at vkAcquireImageANDROID
5. transfer out the ownership at vkQueueSignalReleaseImageANDROID

Signed-off-by: Yiwei Zhang <zzyiwei at chromium.org>
Reviewed-by: Chia-I Wu <olvaffe at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10335>

---

 src/virtio/vulkan/vn_android.c | 179 +++++++++++++++++++++++++++++++++++++++--
 src/virtio/vulkan/vn_android.h |  35 ++++++++
 src/virtio/vulkan/vn_device.c  |   9 +++
 src/virtio/vulkan/vn_device.h  |   2 +
 src/virtio/vulkan/vn_image.c   | 152 ++++++++++++++++++++++++++++++++++
 src/virtio/vulkan/vn_image.h   |  18 +++++
 6 files changed, 388 insertions(+), 7 deletions(-)

diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c
index fc14da62ce2..523b1a1fdae 100644
--- a/src/virtio/vulkan/vn_android.c
+++ b/src/virtio/vulkan/vn_android.c
@@ -9,7 +9,6 @@
  */
 
 #include "vn_android.h"
-#include "vn_common.h"
 
 #include <drm/drm_fourcc.h>
 #include <hardware/hwvulkan.h>
@@ -189,12 +188,36 @@ vn_image_from_anb(struct vn_device *dev,
    VkImageCreateInfo local_image_info = *image_info;
    local_image_info.pNext = &drm_mod_info;
    local_image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
+
+   /* Force VK_SHARING_MODE_CONCURRENT if necessary.
+    * For physical devices supporting multiple queue families, if a swapchain is
+    * created with exclusive mode, we must transfer the image ownership into the
+    * queue family of the present queue. However, there's no way to get that
+    * queue at the 1st acquire of the image. Thus, when multiple queue families
+    * are supported in a physical device, we include all queue families in the
+    * image create info along with VK_SHARING_MODE_CONCURRENT, which forces us
+    * to transfer the ownership into VK_QUEUE_FAMILY_IGNORED. Then if there's
+    * only one queue family, we can safely use queue family index 0.
+    */
+   if (dev->physical_device->queue_family_count > 1) {
+      local_image_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
+      local_image_info.queueFamilyIndexCount =
+         dev->physical_device->queue_family_count;
+      local_image_info.pQueueFamilyIndices =
+         dev->android_wsi->queue_family_indices;
+   }
+
    /* encoder will strip the Android specific pNext structs */
    result = vn_image_create(dev, &local_image_info, alloc, &img);
    if (result != VK_SUCCESS)
       goto fail;
 
    image = vn_image_to_handle(img);
+
+   result = vn_image_android_wsi_init(dev, img, alloc);
+   if (result != VK_SUCCESS)
+      goto fail;
+
    VkMemoryRequirements mem_req;
    vn_GetImageMemoryRequirements(device, image, &mem_req);
    if (!mem_req.memoryTypeBits) {
@@ -272,9 +295,19 @@ fail:
    return vn_error(dev->instance, result);
 }
 
+static bool
+vn_is_queue_compatible_with_wsi(struct vn_queue *queue)
+{
+   static const int32_t compatible_flags =
+      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT;
+   return compatible_flags & queue->device->physical_device
+                                ->queue_family_properties[queue->family]
+                                .queueFamilyProperties.queueFlags;
+}
+
 VkResult
 vn_AcquireImageANDROID(VkDevice device,
-                       UNUSED VkImage image,
+                       VkImage image,
                        int nativeFenceFd,
                        VkSemaphore semaphore,
                        VkFence fence)
@@ -285,6 +318,8 @@ vn_AcquireImageANDROID(VkDevice device,
    struct vn_device *dev = vn_device_from_handle(device);
    struct vn_semaphore *sem = vn_semaphore_from_handle(semaphore);
    struct vn_fence *fen = vn_fence_from_handle(fence);
+   struct vn_image *img = vn_image_from_handle(image);
+   struct vn_queue *queue = img->acquire_queue;
 
    if (nativeFenceFd >= 0) {
       int ret = sync_wait(nativeFenceFd, INT32_MAX);
@@ -300,7 +335,41 @@ vn_AcquireImageANDROID(VkDevice device,
    if (fen)
       vn_fence_signal_wsi(dev, fen);
 
-   return VK_SUCCESS;
+   if (!queue) {
+      /* pick a compatible queue for the 1st acquire of this image */
+      for (uint32_t i = 0; i < dev->queue_count; i++) {
+         if (vn_is_queue_compatible_with_wsi(&dev->queues[i])) {
+            queue = &dev->queues[i];
+            break;
+         }
+      }
+   }
+   if (!queue)
+      return vn_error(dev->instance, VK_ERROR_UNKNOWN);
+
+   const VkSubmitInfo submit_info = {
+      .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
+      .pNext = NULL,
+      .waitSemaphoreCount = 0,
+      .pWaitSemaphores = NULL,
+      .pWaitDstStageMask = NULL,
+      .commandBufferCount = 1,
+      .pCommandBuffers =
+         &img->ownership_cmds[queue->family].cmds[VN_IMAGE_OWNERSHIP_ACQUIRE],
+      .signalSemaphoreCount = 0,
+      .pSignalSemaphores = NULL,
+   };
+
+   VkResult result = vn_QueueSubmit(vn_queue_to_handle(queue), 1,
+                                    &submit_info, queue->wait_fence);
+   if (result != VK_SUCCESS)
+      return vn_error(dev->instance, result);
+
+   result =
+      vn_WaitForFences(device, 1, &queue->wait_fence, VK_TRUE, UINT64_MAX);
+   vn_ResetFences(device, 1, &queue->wait_fence);
+
+   return vn_result(dev->instance, result);
 }
 
 VkResult
@@ -316,13 +385,14 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
     */
    VkResult result = VK_SUCCESS;
    struct vn_queue *que = vn_queue_from_handle(queue);
+   struct vn_image *img = vn_image_from_handle(image);
    const VkAllocationCallbacks *alloc = &que->device->base.base.alloc;
    VkDevice device = vn_device_to_handle(que->device);
    VkPipelineStageFlags local_stage_masks[8];
    VkPipelineStageFlags *stage_masks = local_stage_masks;
 
-   if (waitSemaphoreCount == 0)
-      goto out;
+   if (!vn_is_queue_compatible_with_wsi(que))
+      return vn_error(que->device->instance, VK_ERROR_UNKNOWN);
 
    if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {
       stage_masks =
@@ -343,12 +413,15 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
       .waitSemaphoreCount = waitSemaphoreCount,
       .pWaitSemaphores = pWaitSemaphores,
       .pWaitDstStageMask = stage_masks,
-      .commandBufferCount = 0,
-      .pCommandBuffers = NULL,
+      .commandBufferCount = 1,
+      .pCommandBuffers =
+         &img->ownership_cmds[que->family].cmds[VN_IMAGE_OWNERSHIP_RELEASE],
       .signalSemaphoreCount = 0,
       .pSignalSemaphores = NULL,
    };
    result = vn_QueueSubmit(queue, 1, &submit_info, que->wait_fence);
+   if (stage_masks != local_stage_masks)
+      vk_free(alloc, stage_masks);
    if (result != VK_SUCCESS)
       goto out;
 
@@ -356,7 +429,99 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
       vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);
    vn_ResetFences(device, 1, &que->wait_fence);
 
+   img->acquire_queue = que;
+
 out:
    *pNativeFenceFd = -1;
    return result;
 }
+
+VkResult
+vn_android_wsi_init(struct vn_device *dev, const VkAllocationCallbacks *alloc)
+{
+   VkResult result = VK_SUCCESS;
+
+   struct vn_android_wsi *android_wsi =
+      vk_zalloc(alloc, sizeof(struct vn_android_wsi), VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!android_wsi)
+      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   const uint32_t count = dev->physical_device->queue_family_count;
+   if (count > 1) {
+      android_wsi->queue_family_indices =
+         vk_alloc(alloc, sizeof(uint32_t) * count, VN_DEFAULT_ALIGN,
+                  VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+      if (!android_wsi->queue_family_indices) {
+         result = VK_ERROR_OUT_OF_HOST_MEMORY;
+         goto fail;
+      }
+
+      for (uint32_t i = 0; i < count; i++)
+         android_wsi->queue_family_indices[i] = i;
+   }
+
+   android_wsi->cmd_pools =
+      vk_zalloc(alloc, sizeof(VkCommandPool) * count, VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!android_wsi->cmd_pools) {
+      result = VK_ERROR_OUT_OF_HOST_MEMORY;
+      goto fail;
+   }
+
+   VkDevice device = vn_device_to_handle(dev);
+   for (uint32_t i = 0; i < count; i++) {
+      const VkCommandPoolCreateInfo cmd_pool_info = {
+         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+         .pNext = NULL,
+         .flags = 0,
+         .queueFamilyIndex = i,
+      };
+      result = vn_CreateCommandPool(device, &cmd_pool_info, alloc,
+                                    &android_wsi->cmd_pools[i]);
+      if (result != VK_SUCCESS)
+         goto fail;
+   }
+
+   mtx_init(&android_wsi->cmd_pools_lock, mtx_plain);
+
+   dev->android_wsi = android_wsi;
+
+   return VK_SUCCESS;
+
+fail:
+   if (android_wsi->cmd_pools) {
+      for (uint32_t i = 0; i < count; i++) {
+         if (android_wsi->cmd_pools[i] != VK_NULL_HANDLE)
+            vn_DestroyCommandPool(device, android_wsi->cmd_pools[i], alloc);
+      }
+      vk_free(alloc, android_wsi->cmd_pools);
+   }
+
+   if (android_wsi->queue_family_indices)
+      vk_free(alloc, android_wsi->queue_family_indices);
+
+   vk_free(alloc, android_wsi);
+
+   return vn_error(dev->instance, result);
+}
+
+void
+vn_android_wsi_fini(struct vn_device *dev, const VkAllocationCallbacks *alloc)
+{
+   if (!dev->android_wsi)
+      return;
+
+   mtx_destroy(&dev->android_wsi->cmd_pools_lock);
+
+   VkDevice device = vn_device_to_handle(dev);
+   for (uint32_t i = 0; i < dev->physical_device->queue_family_count; i++) {
+      vn_DestroyCommandPool(device, dev->android_wsi->cmd_pools[i], alloc);
+   }
+   vk_free(alloc, dev->android_wsi->cmd_pools);
+
+   if (dev->android_wsi->queue_family_indices)
+      vk_free(alloc, dev->android_wsi->queue_family_indices);
+
+   vk_free(alloc, dev->android_wsi);
+}
diff --git a/src/virtio/vulkan/vn_android.h b/src/virtio/vulkan/vn_android.h
index f18ce7f2694..0d53656214c 100644
--- a/src/virtio/vulkan/vn_android.h
+++ b/src/virtio/vulkan/vn_android.h
@@ -11,6 +11,8 @@
 #ifndef VN_ANDROID_H
 #define VN_ANDROID_H
 
+#include "vn_common.h"
+
 #include <vulkan/vk_android_native_buffer.h>
 #include <vulkan/vulkan.h>
 
@@ -20,6 +22,15 @@
 struct vn_device;
 struct vn_image;
 
+struct vn_android_wsi {
+   /* command pools, one per queue family */
+   VkCommandPool *cmd_pools;
+   /* use one lock to simplify */
+   mtx_t cmd_pools_lock;
+   /* for forcing VK_SHARING_MODE_CONCURRENT */
+   uint32_t *queue_family_indices;
+};
+
 VkResult
 vn_image_from_anb(struct vn_device *dev,
                   const VkImageCreateInfo *image_info,
@@ -27,4 +38,28 @@ vn_image_from_anb(struct vn_device *dev,
                   const VkAllocationCallbacks *alloc,
                   struct vn_image **out_img);
 
+#ifdef ANDROID
+VkResult
+vn_android_wsi_init(struct vn_device *dev,
+                    const VkAllocationCallbacks *alloc);
+
+void
+vn_android_wsi_fini(struct vn_device *dev,
+                    const VkAllocationCallbacks *alloc);
+#else
+static inline VkResult
+vn_android_wsi_init(UNUSED struct vn_device *dev,
+                    UNUSED const VkAllocationCallbacks *alloc)
+{
+   return VK_SUCCESS;
+}
+
+static inline void
+vn_android_wsi_fini(UNUSED struct vn_device *dev,
+                    UNUSED const VkAllocationCallbacks *alloc)
+{
+   return;
+}
+#endif
+
 #endif /* VN_ANDROID_H */
diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index 0a742d3e00c..ef7af79501e 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -3158,6 +3158,12 @@ vn_CreateDevice(VkPhysicalDevice physicalDevice,
       goto fail;
    }
 
+   if (dev->base.base.enabled_extensions.ANDROID_native_buffer) {
+      result = vn_android_wsi_init(dev, alloc);
+      if (result != VK_SUCCESS)
+         goto fail;
+   }
+
    for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++) {
       struct vn_device_memory_pool *pool = &dev->memory_pools[i];
       mtx_init(&pool->mutex, mtx_plain);
@@ -3188,6 +3194,9 @@ vn_DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
    if (!dev)
       return;
 
+   if (dev->base.base.enabled_extensions.ANDROID_native_buffer)
+      vn_android_wsi_fini(dev, alloc);
+
    for (uint32_t i = 0; i < ARRAY_SIZE(dev->memory_pools); i++)
       vn_device_memory_pool_fini(dev, i);
 
diff --git a/src/virtio/vulkan/vn_device.h b/src/virtio/vulkan/vn_device.h
index 554c23fb7e1..ebac430e5b2 100644
--- a/src/virtio/vulkan/vn_device.h
+++ b/src/virtio/vulkan/vn_device.h
@@ -112,6 +112,8 @@ struct vn_device {
    uint32_t queue_count;
 
    struct vn_device_memory_pool memory_pools[VK_MAX_MEMORY_TYPES];
+
+   struct vn_android_wsi *android_wsi;
 };
 VK_DEFINE_HANDLE_CASTS(vn_device,
                        base.base.base,
diff --git a/src/virtio/vulkan/vn_image.c b/src/virtio/vulkan/vn_image.c
index 6e86c8aaba9..c7e6bbd0b47 100644
--- a/src/virtio/vulkan/vn_image.c
+++ b/src/virtio/vulkan/vn_image.c
@@ -18,6 +18,154 @@
 #include "vn_android.h"
 #include "vn_device.h"
 #include "vn_device_memory.h"
+#include "vn_queue.h"
+
+static VkResult
+vn_record_ownership_cmds(struct vn_device *dev,
+                         struct vn_image *img,
+                         uint32_t family,
+                         uint32_t internal_index,
+                         uint32_t external_index,
+                         VkCommandBuffer *out_cmds)
+{
+   VkResult result = VK_SUCCESS;
+   VkDevice device = vn_device_to_handle(dev);
+   VkImage image = vn_image_to_handle(img);
+   VkCommandBuffer cmds[2];
+
+   const VkCommandBufferAllocateInfo cmd_info = {
+      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+      .pNext = NULL,
+      .commandPool = dev->android_wsi->cmd_pools[family],
+      .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+      .commandBufferCount = 2,
+   };
+
+   mtx_lock(&dev->android_wsi->cmd_pools_lock);
+   result = vn_AllocateCommandBuffers(device, &cmd_info, cmds);
+   mtx_unlock(&dev->android_wsi->cmd_pools_lock);
+
+   if (result != VK_SUCCESS)
+      return vn_error(dev->instance, result);
+
+   /* record the foreign/external queue to internal queue transfer */
+   const VkCommandBufferBeginInfo begin_info = {
+      .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+   };
+   vn_BeginCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_ACQUIRE], &begin_info);
+   VkImageMemoryBarrier barrier = {
+         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+         .pNext = NULL,
+         .srcAccessMask = 0,
+         .dstAccessMask = 0,
+         .oldLayout = VK_IMAGE_LAYOUT_GENERAL,
+         .newLayout = VK_IMAGE_LAYOUT_GENERAL,
+         .srcQueueFamilyIndex = external_index,
+         .dstQueueFamilyIndex = internal_index,
+         .image = image,
+         .subresourceRange =
+                 {
+                         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                         .baseMipLevel = 0,
+                         .levelCount = 1,
+                         .baseArrayLayer = 0,
+                         .layerCount = 1,
+                 },
+   };
+   vn_CmdPipelineBarrier(
+      cmds[VN_IMAGE_OWNERSHIP_ACQUIRE], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+      VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
+   vn_EndCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_ACQUIRE]);
+
+   /* record the internal queue to foreign/external queue transfer */
+   vn_BeginCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_RELEASE], &begin_info);
+   barrier.srcQueueFamilyIndex = internal_index;
+   barrier.dstQueueFamilyIndex = external_index;
+   vn_CmdPipelineBarrier(
+      cmds[VN_IMAGE_OWNERSHIP_RELEASE], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+      VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);
+   vn_EndCommandBuffer(cmds[VN_IMAGE_OWNERSHIP_RELEASE]);
+
+   out_cmds[VN_IMAGE_OWNERSHIP_ACQUIRE] = cmds[VN_IMAGE_OWNERSHIP_ACQUIRE];
+   out_cmds[VN_IMAGE_OWNERSHIP_RELEASE] = cmds[VN_IMAGE_OWNERSHIP_RELEASE];
+
+   return VK_SUCCESS;
+}
+
+VkResult
+vn_image_android_wsi_init(struct vn_device *dev,
+                          struct vn_image *img,
+                          const VkAllocationCallbacks *alloc)
+{
+   VkDevice device = vn_device_to_handle(dev);
+   VkResult result = VK_SUCCESS;
+   const uint32_t internal_index =
+      img->sharing_mode == VK_SHARING_MODE_EXCLUSIVE
+         ? 0
+         : VK_QUEUE_FAMILY_IGNORED;
+   const uint32_t external_index =
+      (dev->base.base.enabled_extensions.EXT_queue_family_foreign ||
+       dev->physical_device->renderer_extensions.EXT_queue_family_foreign)
+         ? VK_QUEUE_FAMILY_FOREIGN_EXT
+         : VK_QUEUE_FAMILY_EXTERNAL;
+   const uint32_t count = dev->physical_device->queue_family_count;
+
+   struct vn_image_ownership_cmds *local_cmds =
+      vk_zalloc(alloc, sizeof(*local_cmds) * count, VN_DEFAULT_ALIGN,
+                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!local_cmds)
+      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   for (uint32_t i = 0; i < count; i++) {
+      /* skip recording if no queue is created from this family */
+      uint32_t j = 0;
+      for (; j < dev->queue_count; j++) {
+         if (dev->queues[j].family == i)
+            break;
+      }
+      if (j == dev->queue_count)
+         continue;
+
+      result = vn_record_ownership_cmds(dev, img, i, internal_index,
+                                        external_index, local_cmds[i].cmds);
+      if (result != VK_SUCCESS)
+         goto fail;
+   }
+
+   img->ownership_cmds = local_cmds;
+
+   return VK_SUCCESS;
+
+fail:
+   for (uint32_t i = 0; i < count; i++) {
+      if (local_cmds[i].cmds[0] != VK_NULL_HANDLE)
+         vn_FreeCommandBuffers(device, dev->android_wsi->cmd_pools[i], 2,
+                               local_cmds[i].cmds);
+   }
+   vk_free(alloc, local_cmds);
+   return vn_error(dev->instance, result);
+}
+
+static void
+vn_image_android_wsi_fini(struct vn_device *dev,
+                          struct vn_image *img,
+                          const VkAllocationCallbacks *alloc)
+{
+   if (!dev->android_wsi || !img->ownership_cmds)
+      return;
+
+   VkDevice device = vn_device_to_handle(dev);
+
+   mtx_lock(&dev->android_wsi->cmd_pools_lock);
+   for (uint32_t i = 0; i < dev->physical_device->queue_family_count; i++) {
+      if (img->ownership_cmds[i].cmds[0] != VK_NULL_HANDLE)
+         vn_FreeCommandBuffers(device, dev->android_wsi->cmd_pools[i], 2,
+                               img->ownership_cmds[i].cmds);
+   }
+   mtx_unlock(&dev->android_wsi->cmd_pools_lock);
+
+   vk_free(alloc, img->ownership_cmds);
+}
 
 static void
 vn_image_init_memory_requirements(struct vn_image *img,
@@ -125,6 +273,8 @@ vn_image_create(struct vn_device *dev,
 
    vn_image_init_memory_requirements(img, dev, create_info);
 
+   img->sharing_mode = create_info->sharingMode;
+
    *out_img = img;
 
    return VK_SUCCESS;
@@ -186,6 +336,8 @@ vn_DestroyImage(VkDevice device,
    if (!img)
       return;
 
+   vn_image_android_wsi_fini(dev, img, alloc);
+
    if (img->private_memory != VK_NULL_HANDLE)
       vn_FreeMemory(device, img->private_memory, pAllocator);
 
diff --git a/src/virtio/vulkan/vn_image.h b/src/virtio/vulkan/vn_image.h
index f134ca2640a..b8fe8d3c6b4 100644
--- a/src/virtio/vulkan/vn_image.h
+++ b/src/virtio/vulkan/vn_image.h
@@ -13,6 +13,15 @@
 
 #include "vn_common.h"
 
+enum {
+   VN_IMAGE_OWNERSHIP_ACQUIRE = 0,
+   VN_IMAGE_OWNERSHIP_RELEASE = 1,
+};
+
+struct vn_image_ownership_cmds {
+   VkCommandBuffer cmds[2];
+};
+
 struct vn_image {
    struct vn_object_base base;
 
@@ -20,6 +29,10 @@ struct vn_image {
    VkMemoryDedicatedRequirements dedicated_requirements[4];
    /* For VK_ANDROID_native_buffer, the WSI image owns the memory, */
    VkDeviceMemory private_memory;
+   /* For queue family ownership transfer of WSI images */
+   VkSharingMode sharing_mode;
+   struct vn_image_ownership_cmds *ownership_cmds;
+   struct vn_queue *acquire_queue;
 };
 VK_DEFINE_NONDISP_HANDLE_CASTS(vn_image,
                                base.base,
@@ -56,4 +69,9 @@ vn_image_create(struct vn_device *dev,
                 const VkAllocationCallbacks *alloc,
                 struct vn_image **out_img);
 
+VkResult
+vn_image_android_wsi_init(struct vn_device *dev,
+                          struct vn_image *img,
+                          const VkAllocationCallbacks *alloc);
+
 #endif /* VN_IMAGE_H */



More information about the mesa-commit mailing list