Mesa (main): venus: moves GPU rendering off CPU timeline for Android WSI

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jun 15 20:00:09 UTC 2021


Module: Mesa
Branch: main
Commit: 04e28356b4ca20d72453aaa35545e2d7407753c9
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=04e28356b4ca20d72453aaa35545e2d7407753c9

Author: Yiwei Zhang <zzyiwei at chromium.org>
Date:   Tue Jun 15 07:00:09 2021 +0000

venus: moves GPU rendering off CPU timeline for Android WSI

When globalFencing is supported, we can export a native sync fd for
presentation to move rendering off CPU timeline.

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/11342>

---

 src/virtio/vulkan/vn_android.c | 69 ++++++++++++++++++++++++++++--------------
 src/virtio/vulkan/vn_device.c  | 20 ++++++++----
 2 files changed, 61 insertions(+), 28 deletions(-)

diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c
index aa59b5dcd5b..61eac3a55e7 100644
--- a/src/virtio/vulkan/vn_android.c
+++ b/src/virtio/vulkan/vn_android.c
@@ -629,28 +629,26 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
                                   VkImage image,
                                   int *pNativeFenceFd)
 {
-   /* At this moment, the wait semaphores are converted to a VkFence via an
-    * empty submit. The VkFence is then waited inside until signaled, and the
-    * out native fence fd is set to -1.
-    */
-   VkResult result = VK_SUCCESS;
    struct vn_queue *que = vn_queue_from_handle(queue);
-   const VkAllocationCallbacks *alloc = &que->device->base.base.alloc;
-   VkDevice device = vn_device_to_handle(que->device);
+   struct vn_device *dev = que->device;
+   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
+   VkDevice device = vn_device_to_handle(dev);
    VkPipelineStageFlags local_stage_masks[8];
    VkPipelineStageFlags *stage_masks = local_stage_masks;
+   VkResult result = VK_SUCCESS;
+   int fd = -1;
 
-   if (waitSemaphoreCount == 0)
-      goto out;
+   if (waitSemaphoreCount == 0) {
+      *pNativeFenceFd = -1;
+      return VK_SUCCESS;
+   }
 
    if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) {
       stage_masks =
-         vk_alloc(alloc, sizeof(VkPipelineStageFlags) * waitSemaphoreCount,
+         vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount,
                   VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
-      if (!stage_masks) {
-         result = VK_ERROR_OUT_OF_HOST_MEMORY;
-         goto out;
-      }
+      if (!stage_masks)
+         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
    }
 
    for (uint32_t i = 0; i < waitSemaphoreCount; i++)
@@ -667,17 +665,44 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue,
       .signalSemaphoreCount = 0,
       .pSignalSemaphores = NULL,
    };
-   result = vn_QueueSubmit(queue, 1, &submit_info, que->wait_fence);
+   /* XXX When globalFencing is supported, our implementation is not able to
+    * reset the fence during vn_GetFenceFdKHR currently. Thus to ensure proper
+    * host driver behavior, we pass VK_NULL_HANDLE here.
+    */
+   result = vn_QueueSubmit(
+      queue, 1, &submit_info,
+      dev->instance->experimental.globalFencing == VK_TRUE ? VK_NULL_HANDLE
+                                                           : que->wait_fence);
+
+   if (stage_masks != local_stage_masks)
+      vk_free(alloc, stage_masks);
+
    if (result != VK_SUCCESS)
-      goto out;
+      return vn_error(dev->instance, result);
 
-   result =
-      vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);
-   vn_ResetFences(device, 1, &que->wait_fence);
+   if (dev->instance->experimental.globalFencing == VK_TRUE) {
+      const VkFenceGetFdInfoKHR fd_info = {
+         .sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
+         .pNext = NULL,
+         .fence = que->wait_fence,
+         .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
+      };
+      result = vn_GetFenceFdKHR(device, &fd_info, &fd);
+   } else {
+      result =
+         vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX);
+      if (result != VK_SUCCESS)
+         return vn_error(dev->instance, result);
 
-out:
-   *pNativeFenceFd = -1;
-   return result;
+      result = vn_ResetFences(device, 1, &que->wait_fence);
+   }
+
+   if (result != VK_SUCCESS)
+      return vn_error(dev->instance, result);
+
+   *pNativeFenceFd = fd;
+
+   return VK_SUCCESS;
 }
 
 static VkResult
diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index ea8a52bf1a2..58951d2983d 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -3102,12 +3102,20 @@ vn_queue_init(struct vn_device *dev,
    queue->index = queue_index;
    queue->flags = queue_info->flags;
 
-   VkResult result =
-      vn_CreateFence(vn_device_to_handle(dev),
-                     &(const VkFenceCreateInfo){
-                        .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
-                     },
-                     NULL, &queue->wait_fence);
+   const VkExportFenceCreateInfo export_fence_info = {
+      .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
+      .pNext = NULL,
+      .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
+   };
+   const VkFenceCreateInfo fence_info = {
+      .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+      .pNext = dev->instance->experimental.globalFencing == VK_TRUE
+                  ? &export_fence_info
+                  : NULL,
+      .flags = 0,
+   };
+   VkResult result = vn_CreateFence(vn_device_to_handle(dev), &fence_info,
+                                    NULL, &queue->wait_fence);
    if (result != VK_SUCCESS)
       return result;
 



More information about the mesa-commit mailing list