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

Author: Yiwei Zhang <[email protected]>
Date:   Thu Aug 18 16:55:06 2022 +0000

venus: re-implement sync_fd external fence

Instead of waiting for signal before importing, we are able to retain
the imported sync file and handle the fence related commands on the
driver side.

Signed-off-by: Yiwei Zhang <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17975>

---

 src/virtio/vulkan/vn_android.c |  1 -
 src/virtio/vulkan/vn_common.h  |  1 +
 src/virtio/vulkan/vn_queue.c   | 49 +++++++++++++++++++++++++++++++-----------
 src/virtio/vulkan/vn_queue.h   |  6 ++++++
 4 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c
index 53ce3ecd6e6..b61a6a583ac 100644
--- a/src/virtio/vulkan/vn_android.c
+++ b/src/virtio/vulkan/vn_android.c
@@ -17,7 +17,6 @@
 #include <vulkan/vk_icd.h>
 
 #include "drm-uapi/drm_fourcc.h"
-#include "util/libsync.h"
 #include "util/os_file.h"
 
 #include "vn_buffer.h"
diff --git a/src/virtio/vulkan/vn_common.h b/src/virtio/vulkan/vn_common.h
index d8a68721697..12994ec6840 100644
--- a/src/virtio/vulkan/vn_common.h
+++ b/src/virtio/vulkan/vn_common.h
@@ -26,6 +26,7 @@
 #include "util/bitscan.h"
 #include "util/bitset.h"
 #include "util/compiler.h"
+#include "util/libsync.h"
 #include "util/list.h"
 #include "util/macros.h"
 #include "util/os_time.h"
diff --git a/src/virtio/vulkan/vn_queue.c b/src/virtio/vulkan/vn_queue.c
index fc03b20c3db..a6a86425006 100644
--- a/src/virtio/vulkan/vn_queue.c
+++ b/src/virtio/vulkan/vn_queue.c
@@ -513,9 +513,12 @@ vn_QueueWaitIdle(VkQueue _queue)
 /* fence commands */
 
 static void
-vn_sync_payload_release(struct vn_device *dev,
+vn_sync_payload_release(UNUSED struct vn_device *dev,
                         struct vn_sync_payload *payload)
 {
+   if (payload->type == VN_SYNC_TYPE_IMPORTED_SYNC_FD && payload->fd >= 0)
+      close(payload->fd);
+
    payload->type = VN_SYNC_TYPE_INVALID;
 }
 
@@ -538,7 +541,8 @@ vn_fence_signal_wsi(struct vn_device *dev, struct vn_fence 
*fence)
    struct vn_sync_payload *temp = &fence->temporary;
 
    vn_sync_payload_release(dev, temp);
-   temp->type = VN_SYNC_TYPE_WSI_SIGNALED;
+   temp->type = VN_SYNC_TYPE_IMPORTED_SYNC_FD;
+   temp->fd = -1;
    fence->payload = temp;
 }
 
@@ -751,8 +755,11 @@ vn_GetFenceStatus(VkDevice device, VkFence _fence)
          result = vn_call_vkGetFenceStatus(dev->instance, device, _fence);
       }
       break;
-   case VN_SYNC_TYPE_WSI_SIGNALED:
-      result = VK_SUCCESS;
+   case VN_SYNC_TYPE_IMPORTED_SYNC_FD:
+      if (payload->fd < 0 || sync_wait(payload->fd, 0) == 0)
+         result = VK_SUCCESS;
+      else
+         result = errno == ETIME ? VK_NOT_READY : VK_ERROR_DEVICE_LOST;
       break;
    default:
       unreachable("unexpected fence payload type");
@@ -884,6 +891,15 @@ vn_create_sync_file(struct vn_device *dev, int *out_fd)
    return *out_fd >= 0 ? VK_SUCCESS : VK_ERROR_TOO_MANY_OBJECTS;
 }
 
+static inline bool
+vn_sync_valid_fd(int fd)
+{
+   /* the special value -1 for fd is treated like a valid sync file descriptor
+    * referring to an object that has already signaled
+    */
+   return (fd >= 0 && sync_valid_fd(fd)) || fd == -1;
+}
+
 VkResult
 vn_ImportFenceFdKHR(VkDevice device,
                     const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
@@ -897,15 +913,15 @@ vn_ImportFenceFdKHR(VkDevice device,
 
    assert(dev->instance->experimental.globalFencing);
    assert(sync_file);
-   if (fd >= 0) {
-      if (sync_wait(fd, -1))
-         return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
 
-      close(fd);
-   }
+   if (!vn_sync_valid_fd(fd))
+      return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
 
-   /* abuse VN_SYNC_TYPE_WSI_SIGNALED */
-   vn_fence_signal_wsi(dev, fence);
+   struct vn_sync_payload *temp = &fence->temporary;
+   vn_sync_payload_release(dev, temp);
+   temp->type = VN_SYNC_TYPE_IMPORTED_SYNC_FD;
+   temp->fd = fd;
+   fence->payload = temp;
 
    return VK_SUCCESS;
 }
@@ -941,12 +957,19 @@ vn_GetFenceFdKHR(VkDevice device,
       vn_sync_payload_release(dev, &fence->temporary);
       fence->payload = &fence->permanent;
    } else {
-      assert(payload->type == VN_SYNC_TYPE_WSI_SIGNALED);
+      assert(payload->type == VN_SYNC_TYPE_IMPORTED_SYNC_FD);
+
+      /* transfer ownership of imported sync fd to save a dup */
+      fd = payload->fd;
+      payload->fd = -1;
 
       /* reset host fence in case in signaled state before import */
       result = vn_ResetFences(device, 1, &pGetFdInfo->fence);
-      if (result != VK_SUCCESS)
+      if (result != VK_SUCCESS) {
+         /* transfer sync fd ownership back on error */
+         payload->fd = fd;
          return result;
+      }
    }
 
    *pFd = fd;
diff --git a/src/virtio/vulkan/vn_queue.h b/src/virtio/vulkan/vn_queue.h
index c815b994564..9d29609ac25 100644
--- a/src/virtio/vulkan/vn_queue.h
+++ b/src/virtio/vulkan/vn_queue.h
@@ -40,10 +40,16 @@ enum vn_sync_type {
 
    /* already signaled by WSI */
    VN_SYNC_TYPE_WSI_SIGNALED,
+
+   /* payload is an imported sync file */
+   VN_SYNC_TYPE_IMPORTED_SYNC_FD,
 };
 
 struct vn_sync_payload {
    enum vn_sync_type type;
+
+   /* If type is VN_SYNC_TYPE_IMPORTED_SYNC_FD, fd is a sync file. */
+   int fd;
 };
 
 struct vn_fence {

Reply via email to