Mesa (main): venus: add support for external fence on Android

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jun 11 23:54:30 UTC 2021


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

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Tue Jun  8 10:54:49 2021 -0700

venus: add support for external fence on Android

This is a hack.

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

---

 src/virtio/vulkan/vn_device.c | 13 ++++++++
 src/virtio/vulkan/vn_queue.c  | 75 +++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c
index 94465092646..2ea3efb4f85 100644
--- a/src/virtio/vulkan/vn_device.c
+++ b/src/virtio/vulkan/vn_device.c
@@ -1412,6 +1412,13 @@ vn_physical_device_init_external_fence_handles(
     * and idle waiting.
     */
    physical_dev->external_fence_handles = 0;
+
+#ifdef ANDROID
+   if (physical_dev->instance->experimental.globalFencing) {
+      physical_dev->external_fence_handles =
+         VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
+   }
+#endif
 }
 
 static void
@@ -1468,6 +1475,12 @@ vn_physical_device_get_native_extensions(
 #endif
    }
 
+#ifdef ANDROID
+   if (instance->experimental.globalFencing) {
+      exts->KHR_external_fence_fd = true;
+   }
+#endif
+
 #ifdef VN_USE_WSI_PLATFORM
    exts->KHR_incremental_present = true;
    exts->KHR_swapchain = true;
diff --git a/src/virtio/vulkan/vn_queue.c b/src/virtio/vulkan/vn_queue.c
index b1cfa79ea6a..c694d734b78 100644
--- a/src/virtio/vulkan/vn_queue.c
+++ b/src/virtio/vulkan/vn_queue.c
@@ -10,6 +10,7 @@
 
 #include "vn_queue.h"
 
+#include "util/libsync.h"
 #include "venus-protocol/vn_protocol_driver_event.h"
 #include "venus-protocol/vn_protocol_driver_fence.h"
 #include "venus-protocol/vn_protocol_driver_queue.h"
@@ -664,12 +665,60 @@ vn_WaitForFences(VkDevice device,
    return vn_result(dev->instance, result);
 }
 
+static VkResult
+vn_create_sync_file(struct vn_device *dev, int *out_fd)
+{
+   struct vn_renderer_sync *sync;
+   VkResult result = vn_renderer_sync_create(dev->renderer, 0,
+                                             VN_RENDERER_SYNC_BINARY, &sync);
+   if (result != VK_SUCCESS)
+      return vn_error(dev->instance, result);
+
+   const struct vn_renderer_submit submit = {
+      .batches =
+         &(const struct vn_renderer_submit_batch){
+            .syncs = &sync,
+            .sync_values = &(const uint64_t){ 1 },
+            .sync_count = 1,
+         },
+      .batch_count = 1,
+   };
+   result = vn_renderer_submit(dev->renderer, &submit);
+   if (result != VK_SUCCESS) {
+      vn_renderer_sync_destroy(dev->renderer, sync);
+      return vn_error(dev->instance, result);
+   }
+
+   *out_fd = vn_renderer_sync_export_syncobj(dev->renderer, sync, true);
+   vn_renderer_sync_destroy(dev->renderer, sync);
+
+   return *out_fd >= 0 ? VK_SUCCESS : VK_ERROR_TOO_MANY_OBJECTS;
+}
+
 VkResult
 vn_ImportFenceFdKHR(VkDevice device,
                     const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
 {
    struct vn_device *dev = vn_device_from_handle(device);
-   return vn_error(dev->instance, VK_ERROR_UNKNOWN);
+   struct vn_fence *fence = vn_fence_from_handle(pImportFenceFdInfo->fence);
+   ASSERTED const bool sync_file = pImportFenceFdInfo->handleType ==
+                                   VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
+   const int fd = pImportFenceFdInfo->fd;
+
+   assert(dev->instance->experimental.globalFencing);
+   assert(sync_file);
+   if (fd >= 0) {
+      const int ret = sync_wait(fd, -1);
+      if (ret)
+         return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
+
+      close(fd);
+   }
+
+   /* abuse VN_SYNC_TYPE_WSI_SIGNALED */
+   vn_fence_signal_wsi(dev, fence);
+
+   return VK_SUCCESS;
 }
 
 VkResult
@@ -678,7 +727,29 @@ vn_GetFenceFdKHR(VkDevice device,
                  int *pFd)
 {
    struct vn_device *dev = vn_device_from_handle(device);
-   return vn_error(dev->instance, VK_ERROR_UNKNOWN);
+   struct vn_fence *fence = vn_fence_from_handle(pGetFdInfo->fence);
+   const bool sync_file =
+      pGetFdInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
+   struct vn_sync_payload *payload = fence->payload;
+
+   assert(dev->instance->experimental.globalFencing);
+   assert(sync_file);
+   int fd = -1;
+   if (payload->type == VN_SYNC_TYPE_DEVICE_ONLY) {
+      VkResult result = vn_create_sync_file(dev, &fd);
+      if (result != VK_SUCCESS)
+         return vn_error(dev->instance, result);
+   }
+
+   if (sync_file) {
+      vn_sync_payload_release(dev, &fence->temporary);
+      fence->payload = &fence->permanent;
+
+      /* XXX implies reset operation on the host fence */
+   }
+
+   *pFd = fd;
+   return VK_SUCCESS;
 }
 
 /* semaphore commands */



More information about the mesa-commit mailing list