Mesa (master): turnip: rework fences to use syncobjs

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Sep 24 14:50:16 UTC 2020


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

Author: Jonathan Marek <jonathan at marek.ca>
Date:   Thu Sep 10 22:51:53 2020 -0400

turnip: rework fences to use syncobjs

Fences are now just a syncobj, which makes our life easier.

The next step will be to fill out ImportFenceFdKHR()/GetFenceFdKHR().

Signed-off-by: Jonathan Marek <jonathan at marek.ca>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6683>

---

 src/freedreno/vulkan/meson.build      |   1 -
 src/freedreno/vulkan/tu_device.c      |  38 ++--
 src/freedreno/vulkan/tu_drm.c         | 195 +++++++++++++++-
 src/freedreno/vulkan/tu_fence.c       | 406 ----------------------------------
 src/freedreno/vulkan/tu_kgsl.c        |  69 +++++-
 src/freedreno/vulkan/tu_private.h     |  17 +-
 src/freedreno/vulkan/tu_wsi_display.c | 100 +++++----
 7 files changed, 327 insertions(+), 499 deletions(-)

diff --git a/src/freedreno/vulkan/meson.build b/src/freedreno/vulkan/meson.build
index fc544a9e52c..f50375c7a58 100644
--- a/src/freedreno/vulkan/meson.build
+++ b/src/freedreno/vulkan/meson.build
@@ -47,7 +47,6 @@ libtu_files = files(
   'tu_device.c',
   'tu_descriptor_set.c',
   'tu_descriptor_set.h',
-  'tu_fence.c',
   'tu_formats.c',
   'tu_image.c',
   'tu_nir_lower_multiview.c',
diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c
index ba550fbffcd..9578153ec55 100644
--- a/src/freedreno/vulkan/tu_device.c
+++ b/src/freedreno/vulkan/tu_device.c
@@ -975,7 +975,7 @@ tu_queue_init(struct tu_device *device,
    if (ret)
       return VK_ERROR_INITIALIZATION_FAILED;
 
-   tu_fence_init(&queue->submit_fence, false);
+   queue->fence = -1;
 
    return VK_SUCCESS;
 }
@@ -983,7 +983,8 @@ tu_queue_init(struct tu_device *device,
 static void
 tu_queue_finish(struct tu_queue *queue)
 {
-   tu_fence_finish(&queue->submit_fence);
+   if (queue->fence >= 0)
+      close(queue->fence);
    tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
 }
 
@@ -1331,8 +1332,20 @@ tu_QueueWaitIdle(VkQueue _queue)
    if (tu_device_is_lost(queue->device))
       return VK_ERROR_DEVICE_LOST;
 
-   tu_fence_wait_idle(&queue->submit_fence);
+   if (queue->fence < 0)
+      return VK_SUCCESS;
+
+   struct pollfd fds = { .fd = queue->fence, .events = POLLIN };
+   int ret;
+   do {
+      ret = poll(&fds, 1, -1);
+   } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+   /* TODO: otherwise set device lost ? */
+   assert(ret == 1 && !(fds.revents & (POLLERR | POLLNVAL)));
 
+   close(queue->fence);
+   queue->fence = -1;
    return VK_SUCCESS;
 }
 
@@ -2092,25 +2105,6 @@ tu_GetMemoryFdPropertiesKHR(VkDevice _device,
    return VK_SUCCESS;
 }
 
-VkResult
-tu_ImportFenceFdKHR(VkDevice _device,
-                    const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
-{
-   tu_stub();
-
-   return VK_SUCCESS;
-}
-
-VkResult
-tu_GetFenceFdKHR(VkDevice _device,
-                 const VkFenceGetFdInfoKHR *pGetFdInfo,
-                 int *pFd)
-{
-   tu_stub();
-
-   return VK_SUCCESS;
-}
-
 void
 tu_GetPhysicalDeviceExternalFenceProperties(
    VkPhysicalDevice physicalDevice,
diff --git a/src/freedreno/vulkan/tu_drm.c b/src/freedreno/vulkan/tu_drm.c
index 8c8d9244a92..4e6206e1577 100644
--- a/src/freedreno/vulkan/tu_drm.c
+++ b/src/freedreno/vulkan/tu_drm.c
@@ -644,13 +644,17 @@ tu_QueueSubmit(VkQueue _queue,
                VkFence _fence)
 {
    TU_FROM_HANDLE(tu_queue, queue, _queue);
+   TU_FROM_HANDLE(tu_fence, fence, _fence);
 
    for (uint32_t i = 0; i < submitCount; ++i) {
       const VkSubmitInfo *submit = pSubmits + i;
       const bool last_submit = (i == submitCount - 1);
+      uint32_t out_syncobjs_size = submit->signalSemaphoreCount;
+      if (last_submit && fence)
+         out_syncobjs_size += 1;
       /* note: assuming there won't be any very large semaphore counts */
       struct drm_msm_gem_submit_syncobj in_syncobjs[submit->waitSemaphoreCount];
-      struct drm_msm_gem_submit_syncobj out_syncobjs[submit->signalSemaphoreCount];
+      struct drm_msm_gem_submit_syncobj out_syncobjs[out_syncobjs_size];
       uint32_t nr_in_syncobjs = 0, nr_out_syncobjs = 0;
 
       for (uint32_t i = 0; i < submit->waitSemaphoreCount; i++) {
@@ -681,6 +685,13 @@ tu_QueueSubmit(VkQueue _queue,
          };
       }
 
+      if (last_submit && fence) {
+         out_syncobjs[nr_out_syncobjs++] = (struct drm_msm_gem_submit_syncobj) {
+            .handle = fence->syncobj,
+            .flags = 0,
+         };
+      }
+
       uint32_t entry_count = 0;
       for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
          TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
@@ -713,7 +724,6 @@ tu_QueueSubmit(VkQueue _queue,
       if (nr_out_syncobjs) {
          flags |= MSM_SUBMIT_SYNCOBJ_OUT;
       }
-
       if (last_submit) {
          flags |= MSM_SUBMIT_FENCE_FD_OUT;
       }
@@ -744,17 +754,184 @@ tu_QueueSubmit(VkQueue _queue,
       tu_semaphores_remove_temp(queue->device, pSubmits[i].pWaitSemaphores,
                                 pSubmits[i].waitSemaphoreCount);
       if (last_submit) {
-         /* no need to merge fences as queue execution is serialized */
-         tu_fence_update_fd(&queue->submit_fence, req.fence_fd);
-      } else if (last_submit) {
-         close(req.fence_fd);
+         if (queue->fence >= 0)
+            close(queue->fence);
+         queue->fence = req.fence_fd;
       }
    }
 
-   if (_fence != VK_NULL_HANDLE) {
-      TU_FROM_HANDLE(tu_fence, fence, _fence);
-      tu_fence_copy(fence, &queue->submit_fence);
+   if (!submitCount && fence) {
+      /* signal fence imemediately since we don't have a submit to do it */
+      ioctl(queue->device->fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &(struct drm_syncobj_array) {
+         .handles = (uintptr_t) &fence->syncobj,
+         .count_handles = 1,
+      });
    }
 
    return VK_SUCCESS;
 }
+
+VkResult
+tu_CreateFence(VkDevice _device,
+               const VkFenceCreateInfo *pCreateInfo,
+               const VkAllocationCallbacks *pAllocator,
+               VkFence *pFence)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+   int ret;
+
+   struct tu_fence *fence =
+         vk_object_alloc(&device->vk, pAllocator, sizeof(*fence),
+                         VK_OBJECT_TYPE_FENCE);
+   if (!fence)
+      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   struct drm_syncobj_create create = {
+      .flags = COND(pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT,
+                    DRM_SYNCOBJ_CREATE_SIGNALED)
+   };
+   ret = ioctl(device->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
+   if (ret) {
+      vk_free2(&device->vk.alloc, pAllocator, fence);
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
+
+   fence->syncobj = create.handle;
+
+   *pFence = tu_fence_to_handle(fence);
+
+   return VK_SUCCESS;
+}
+
+void
+tu_DestroyFence(VkDevice _device, VkFence _fence, const VkAllocationCallbacks *pAllocator)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+   TU_FROM_HANDLE(tu_fence, fence, _fence);
+
+   if (!fence)
+      return;
+
+   ioctl(device->fd, DRM_IOCTL_SYNCOBJ_DESTROY,
+         &(struct drm_syncobj_destroy) { .handle = fence->syncobj });
+
+   vk_object_free(&device->vk, pAllocator, fence);
+}
+
+VkResult
+tu_ImportFenceFdKHR(VkDevice _device,
+                    const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
+{
+   tu_stub();
+
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_GetFenceFdKHR(VkDevice _device,
+                 const VkFenceGetFdInfoKHR *pGetFdInfo,
+                 int *pFd)
+{
+   tu_stub();
+
+   return VK_SUCCESS;
+}
+
+static VkResult
+drm_syncobj_wait(struct tu_device *device,
+                 const uint32_t *handles, uint32_t count_handles,
+                 int64_t timeout_nsec, bool wait_all)
+{
+   int ret = ioctl(device->fd, DRM_IOCTL_SYNCOBJ_WAIT, &(struct drm_syncobj_wait) {
+      .handles = (uint64_t) (uintptr_t) handles,
+      .count_handles = count_handles,
+      .timeout_nsec = timeout_nsec,
+      .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+               COND(wait_all, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL)
+   });
+   if (ret) {
+      if (errno == ETIME)
+         return VK_TIMEOUT;
+
+      assert(0);
+      return VK_ERROR_DEVICE_LOST; /* TODO */
+   }
+   return VK_SUCCESS;
+}
+
+static uint64_t
+gettime_ns(void)
+{
+   struct timespec current;
+   clock_gettime(CLOCK_MONOTONIC, &current);
+   return (uint64_t)current.tv_sec * 1000000000 + current.tv_nsec;
+}
+
+/* and the kernel converts it right back to relative timeout - very smart UAPI */
+static uint64_t
+absolute_timeout(uint64_t timeout)
+{
+   if (timeout == 0)
+      return 0;
+   uint64_t current_time = gettime_ns();
+   uint64_t max_timeout = (uint64_t) INT64_MAX - current_time;
+
+   timeout = MIN2(max_timeout, timeout);
+
+   return (current_time + timeout);
+}
+
+VkResult
+tu_WaitForFences(VkDevice _device,
+                 uint32_t fenceCount,
+                 const VkFence *pFences,
+                 VkBool32 waitAll,
+                 uint64_t timeout)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+
+   if (tu_device_is_lost(device))
+      return VK_ERROR_DEVICE_LOST;
+
+   uint32_t handles[fenceCount];
+   for (unsigned i = 0; i < fenceCount; ++i) {
+      TU_FROM_HANDLE(tu_fence, fence, pFences[i]);
+      handles[i] = fence->syncobj;
+   }
+
+   return drm_syncobj_wait(device, handles, fenceCount, absolute_timeout(timeout), waitAll);
+}
+
+VkResult
+tu_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+   int ret;
+
+   uint32_t handles[fenceCount];
+   for (unsigned i = 0; i < fenceCount; ++i) {
+      TU_FROM_HANDLE(tu_fence, fence, pFences[i]);
+      handles[i] = fence->syncobj;
+   }
+
+   ret = ioctl(device->fd, DRM_IOCTL_SYNCOBJ_RESET, &(struct drm_syncobj_array) {
+      .handles = (uint64_t) (uintptr_t) handles,
+      .count_handles = fenceCount,
+   });
+   assert(!ret);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_GetFenceStatus(VkDevice _device, VkFence _fence)
+{
+   TU_FROM_HANDLE(tu_device, device, _device);
+   TU_FROM_HANDLE(tu_fence, fence, _fence);
+   VkResult result;
+
+   result = drm_syncobj_wait(device, &fence->syncobj, 1, 0, false);
+   if (result == VK_TIMEOUT)
+      result = VK_NOT_READY;
+   return result;
+}
diff --git a/src/freedreno/vulkan/tu_fence.c b/src/freedreno/vulkan/tu_fence.c
deleted file mode 100644
index 11c93cab80f..00000000000
--- a/src/freedreno/vulkan/tu_fence.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright © 2019 Google LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "tu_private.h"
-
-#include <fcntl.h>
-#include <libsync.h>
-#include <unistd.h>
-
-#include "util/os_file.h"
-#include "util/os_time.h"
-
-/**
- * Internally, a fence can be in one of these states.
- */
-enum tu_fence_state
-{
-   TU_FENCE_STATE_RESET,
-   TU_FENCE_STATE_PENDING,
-   TU_FENCE_STATE_SIGNALED,
-};
-
-static enum tu_fence_state
-tu_fence_get_state(const struct tu_fence *fence)
-{
-   if (fence->signaled)
-      assert(fence->fd < 0);
-
-   if (fence->signaled)
-      return TU_FENCE_STATE_SIGNALED;
-   else if (fence->fd >= 0)
-      return TU_FENCE_STATE_PENDING;
-   else
-      return TU_FENCE_STATE_RESET;
-}
-
-static void
-tu_fence_set_state(struct tu_fence *fence, enum tu_fence_state state, int fd)
-{
-   if (fence->fd >= 0)
-      close(fence->fd);
-
-   switch (state) {
-   case TU_FENCE_STATE_RESET:
-      assert(fd < 0);
-      fence->signaled = false;
-      fence->fd = -1;
-      break;
-   case TU_FENCE_STATE_PENDING:
-      assert(fd >= 0);
-      fence->signaled = false;
-      fence->fd = fd;
-      break;
-   case TU_FENCE_STATE_SIGNALED:
-      assert(fd < 0);
-      fence->signaled = true;
-      fence->fd = -1;
-      break;
-   default:
-      unreachable("unknown fence state");
-      break;
-   }
-}
-
-void
-tu_fence_init(struct tu_fence *fence, bool signaled)
-{
-   fence->signaled = signaled;
-   fence->fd = -1;
-   fence->fence_wsi = NULL;
-}
-
-void
-tu_fence_finish(struct tu_fence *fence)
-{
-   if (fence->fd >= 0)
-      close(fence->fd);
-   if (fence->fence_wsi)
-      fence->fence_wsi->destroy(fence->fence_wsi);
-}
-
-/**
- * Update the associated fd of a fence.  Ownership of \a fd is transferred to
- * \a fence.
- *
- * This function does not block.  \a fence can also be in any state when this
- * function is called.  To be able to do that, the caller must make sure that,
- * when both the currently associated fd and the new fd are valid, they are on
- * the same timeline with the new fd being later on the timeline.
- */
-void
-tu_fence_update_fd(struct tu_fence *fence, int fd)
-{
-   const enum tu_fence_state state =
-      fd >= 0 ? TU_FENCE_STATE_PENDING : TU_FENCE_STATE_SIGNALED;
-   tu_fence_set_state(fence, state, fd);
-}
-
-/**
- * Make a fence a copy of another fence.  \a fence must be in the reset state.
- */
-void
-tu_fence_copy(struct tu_fence *fence, const struct tu_fence *src)
-{
-   assert(tu_fence_get_state(fence) == TU_FENCE_STATE_RESET);
-
-   /* dup src->fd */
-   int fd = -1;
-   if (src->fd >= 0) {
-      fd = os_dupfd_cloexec(src->fd);
-      if (fd < 0) {
-         tu_loge("failed to dup fd %d for fence", src->fd);
-         sync_wait(src->fd, -1);
-      }
-   }
-
-   tu_fence_update_fd(fence, fd);
-}
-
-/**
- * Wait until a fence is idle (i.e., not pending).
- */
-void
-tu_fence_wait_idle(struct tu_fence *fence)
-{
-   if (fence->fd >= 0) {
-      if (sync_wait(fence->fd, -1))
-         tu_loge("sync_wait on fence fd %d failed", fence->fd);
-
-      tu_fence_set_state(fence, TU_FENCE_STATE_SIGNALED, -1);
-   }
-}
-
-VkResult
-tu_CreateFence(VkDevice _device,
-               const VkFenceCreateInfo *pCreateInfo,
-               const VkAllocationCallbacks *pAllocator,
-               VkFence *pFence)
-{
-   TU_FROM_HANDLE(tu_device, device, _device);
-
-   struct tu_fence *fence =
-         vk_object_alloc(&device->vk, pAllocator, sizeof(*fence),
-                         VK_OBJECT_TYPE_FENCE);
-   if (!fence)
-      return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   tu_fence_init(fence, pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT);
-
-   *pFence = tu_fence_to_handle(fence);
-
-   return VK_SUCCESS;
-}
-
-void
-tu_DestroyFence(VkDevice _device,
-                VkFence _fence,
-                const VkAllocationCallbacks *pAllocator)
-{
-   TU_FROM_HANDLE(tu_device, device, _device);
-   TU_FROM_HANDLE(tu_fence, fence, _fence);
-
-   if (!fence)
-      return;
-
-   tu_fence_finish(fence);
-
-   vk_object_free(&device->vk, pAllocator, fence);
-}
-
-/**
- * Initialize a pollfd array from fences.
- */
-static nfds_t
-tu_fence_init_poll_fds(uint32_t fence_count,
-                       const VkFence *fences,
-                       bool wait_all,
-                       struct pollfd *fds)
-{
-   nfds_t nfds = 0;
-   for (uint32_t i = 0; i < fence_count; i++) {
-      TU_FROM_HANDLE(tu_fence, fence, fences[i]);
-
-      /* skip wsi fences */
-      if (fence->fence_wsi)
-            continue;
-
-      if (fence->signaled) {
-         if (wait_all) {
-            /* skip signaled fences */
-            continue;
-         } else {
-            /* no need to poll any fd */
-            nfds = 0;
-            break;
-         }
-      }
-
-      /* negative fds are never ready, which is the desired behavior */
-      fds[nfds].fd = fence->fd;
-      fds[nfds].events = POLLIN;
-      fds[nfds].revents = 0;
-      nfds++;
-   }
-
-   return nfds;
-}
-
-/**
- * Translate timeout from nanoseconds to milliseconds for poll().
- */
-static int
-tu_fence_get_poll_timeout(uint64_t timeout_ns)
-{
-   const uint64_t ns_per_ms = 1000 * 1000;
-   uint64_t timeout_ms = timeout_ns / ns_per_ms;
-
-   /* round up if needed */
-   if (timeout_ns - timeout_ms * ns_per_ms >= ns_per_ms / 2)
-      timeout_ms++;
-
-   return timeout_ms < INT_MAX ? timeout_ms : INT_MAX;
-}
-
-/**
- * Poll a pollfd array.
- */
-static VkResult
-tu_fence_poll_fds(struct pollfd *fds, nfds_t nfds, uint64_t *timeout_ns)
-{
-   while (true) {
-      /* poll */
-      uint64_t duration = os_time_get_nano();
-      int ret = poll(fds, nfds, tu_fence_get_poll_timeout(*timeout_ns));
-      duration = os_time_get_nano() - duration;
-
-      /* update timeout_ns */
-      if (*timeout_ns > duration)
-         *timeout_ns -= duration;
-      else
-         *timeout_ns = 0;
-
-      if (ret > 0) {
-         return VK_SUCCESS;
-      } else if (ret == 0) {
-         if (!*timeout_ns)
-            return VK_TIMEOUT;
-      } else if (errno != EINTR && errno != EAGAIN) {
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
-      }
-   }
-}
-
-/**
- * Update a pollfd array and the fence states.  This should be called after a
- * successful call to tu_fence_poll_fds.
- */
-static nfds_t
-tu_fence_update_fences_and_poll_fds(uint32_t fence_count,
-                                    const VkFence *fences,
-                                    bool wait_all,
-                                    struct pollfd *fds)
-{
-   uint32_t nfds = 0;
-   uint32_t fds_idx = 0;
-   for (uint32_t i = 0; i < fence_count; i++) {
-      TU_FROM_HANDLE(tu_fence, fence, fences[i]);
-
-      /* skip wsi fences */
-      if (fence->fence_wsi)
-            continue;
-
-      /* no signaled fence in fds */
-      if (fence->signaled)
-         continue;
-
-      /* fds[fds_idx] corresponds to fences[i] */
-      assert(fence->fd == fds[fds_idx].fd);
-
-      assert(nfds <= fds_idx && fds_idx <= i);
-
-      /* fd is ready (errors are treated as ready) */
-      if (fds[fds_idx].revents) {
-         tu_fence_set_state(fence, TU_FENCE_STATE_SIGNALED, -1);
-      } else if (wait_all) {
-         /* add to fds again for another poll */
-         fds[nfds].fd = fence->fd;
-         fds[nfds].events = POLLIN;
-         fds[nfds].revents = 0;
-         nfds++;
-      }
-
-      fds_idx++;
-   }
-
-   return nfds;
-}
-
-VkResult
-tu_WaitForFences(VkDevice _device,
-                 uint32_t fenceCount,
-                 const VkFence *pFences,
-                 VkBool32 waitAll,
-                 uint64_t timeout)
-{
-   TU_FROM_HANDLE(tu_device, device, _device);
-
-   if (tu_device_is_lost(device))
-      return VK_ERROR_DEVICE_LOST;
-
-   /* add a simpler path for when fenceCount == 1? */
-
-   struct pollfd stack_fds[8];
-   struct pollfd *fds = stack_fds;
-   if (fenceCount > ARRAY_SIZE(stack_fds)) {
-      fds = vk_alloc(&device->vk.alloc, sizeof(*fds) * fenceCount, 8,
-                     VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
-      if (!fds)
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
-   }
-
-   /* set up pollfd array and start polling */
-   nfds_t nfds = tu_fence_init_poll_fds(fenceCount, pFences, waitAll, fds);
-   VkResult result = VK_SUCCESS;
-   while (nfds) {
-      result = tu_fence_poll_fds(fds, nfds, &timeout);
-      if (result != VK_SUCCESS)
-         break;
-      nfds = tu_fence_update_fences_and_poll_fds(fenceCount, pFences, waitAll,
-                                                 fds);
-   }
-
-   if (fds != stack_fds)
-      vk_free(&device->vk.alloc, fds);
-
-   if (result != VK_SUCCESS)
-      return result;
-
-   for (uint32_t i = 0; i < fenceCount; ++i) {
-      TU_FROM_HANDLE(tu_fence, fence, pFences[i]);
-      if (fence->fence_wsi) {
-         VkResult result = fence->fence_wsi->wait(fence->fence_wsi, timeout);
-         if (result != VK_SUCCESS)
-            return result;
-      }
-   }
-
-   return result;
-}
-
-VkResult
-tu_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences)
-{
-   for (unsigned i = 0; i < fenceCount; ++i) {
-      TU_FROM_HANDLE(tu_fence, fence, pFences[i]);
-      assert(tu_fence_get_state(fence) != TU_FENCE_STATE_PENDING);
-      tu_fence_set_state(fence, TU_FENCE_STATE_RESET, -1);
-   }
-
-   return VK_SUCCESS;
-}
-
-VkResult
-tu_GetFenceStatus(VkDevice _device, VkFence _fence)
-{
-   TU_FROM_HANDLE(tu_fence, fence, _fence);
-
-   if (fence->fd >= 0) {
-      int err = sync_wait(fence->fd, 0);
-      if (!err)
-         tu_fence_set_state(fence, TU_FENCE_STATE_SIGNALED, -1);
-      else if (err && errno != ETIME)
-         return VK_ERROR_OUT_OF_HOST_MEMORY;
-   }
-   if (fence->fence_wsi) {
-      VkResult result = fence->fence_wsi->wait(fence->fence_wsi, 0);
-
-      if (result != VK_SUCCESS) {
-         if (result == VK_TIMEOUT)
-            return VK_NOT_READY;
-         return result;
-      }
-   }
-
-   return fence->signaled ? VK_SUCCESS : VK_NOT_READY;
-}
diff --git a/src/freedreno/vulkan/tu_kgsl.c b/src/freedreno/vulkan/tu_kgsl.c
index f31a33a7cca..db83430611b 100644
--- a/src/freedreno/vulkan/tu_kgsl.c
+++ b/src/freedreno/vulkan/tu_kgsl.c
@@ -297,17 +297,14 @@ tu_QueueSubmit(VkQueue _queue,
             goto fail;
          }
 
-         tu_fence_update_fd(&queue->submit_fence, fd);
+         if (queue->fence >= 0)
+            close(queue->fence);
+         queue->fence = fd;
       }
    }
 fail:
    vk_free(&queue->device->vk.alloc, cmds);
 
-   if (_fence != VK_NULL_HANDLE) {
-      TU_FROM_HANDLE(tu_fence, fence, _fence);
-      tu_fence_copy(fence, &queue->submit_fence);
-   }
-
    return result;
 }
 
@@ -345,3 +342,63 @@ tu_DestroySemaphore(VkDevice _device,
 {
    tu_finishme("DestroySemaphore");
 }
+
+VkResult
+tu_ImportFenceFdKHR(VkDevice _device,
+                    const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
+{
+   tu_stub();
+
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_GetFenceFdKHR(VkDevice _device,
+                 const VkFenceGetFdInfoKHR *pGetFdInfo,
+                 int *pFd)
+{
+   tu_stub();
+
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_CreateFence(VkDevice _device,
+               const VkFenceCreateInfo *pCreateInfo,
+               const VkAllocationCallbacks *pAllocator,
+               VkFence *pFence)
+{
+   tu_finishme("CreateFence");
+   return VK_SUCCESS;
+}
+
+void
+tu_DestroyFence(VkDevice _device, VkFence _fence, const VkAllocationCallbacks *pAllocator)
+{
+   tu_finishme("DestroyFence");
+}
+
+VkResult
+tu_WaitForFences(VkDevice _device,
+                 uint32_t fenceCount,
+                 const VkFence *pFences,
+                 VkBool32 waitAll,
+                 uint64_t timeout)
+{
+   tu_finishme("WaitForFences");
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences)
+{
+   tu_finishme("ResetFences");
+   return VK_SUCCESS;
+}
+
+VkResult
+tu_GetFenceStatus(VkDevice _device, VkFence _fence)
+{
+   tu_finishme("GetFenceStatus");
+   return VK_SUCCESS;
+}
diff --git a/src/freedreno/vulkan/tu_private.h b/src/freedreno/vulkan/tu_private.h
index d4c2db27feb..61da0ee33ae 100644
--- a/src/freedreno/vulkan/tu_private.h
+++ b/src/freedreno/vulkan/tu_private.h
@@ -291,22 +291,9 @@ struct tu_pipeline_key
 struct tu_fence
 {
    struct vk_object_base base;
-   struct wsi_fence *fence_wsi;
-   bool signaled;
-   int fd;
+   uint32_t syncobj;
 };
 
-void
-tu_fence_init(struct tu_fence *fence, bool signaled);
-void
-tu_fence_finish(struct tu_fence *fence);
-void
-tu_fence_update_fd(struct tu_fence *fence, int fd);
-void
-tu_fence_copy(struct tu_fence *fence, const struct tu_fence *src);
-void
-tu_fence_wait_idle(struct tu_fence *fence);
-
 struct tu_queue
 {
    struct vk_object_base base;
@@ -317,7 +304,7 @@ struct tu_queue
    VkDeviceQueueCreateFlags flags;
 
    uint32_t msm_queue_id;
-   struct tu_fence submit_fence;
+   int fence;
 };
 
 struct tu_bo
diff --git a/src/freedreno/vulkan/tu_wsi_display.c b/src/freedreno/vulkan/tu_wsi_display.c
index 65c383bb8fa..f742ada7924 100644
--- a/src/freedreno/vulkan/tu_wsi_display.c
+++ b/src/freedreno/vulkan/tu_wsi_display.c
@@ -24,13 +24,12 @@
 #include <string.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/ioctl.h>
 #include "tu_private.h"
 #include "tu_cs.h"
 #include "util/disk_cache.h"
 #include "util/strtod.h"
 #include "vk_util.h"
-#include <xf86drm.h>
-#include <xf86drmMode.h>
 #include "vk_format.h"
 #include "util/debug.h"
 #include "wsi_common_display.h"
@@ -260,6 +259,19 @@ tu_DisplayPowerControlEXT(VkDevice                    _device,
                                     display_power_info);
 }
 
+static int
+import_syncobj(int fd, uint32_t syncobj)
+{
+   struct drm_syncobj_handle handle = { .handle = syncobj };
+   int ret;
+
+   ret = ioctl(fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &handle);
+   if (ret)
+      return 0;
+
+   return ret ? -1 : handle.fd;
+}
+
 VkResult
 tu_RegisterDeviceEventEXT(VkDevice                    _device,
                           const VkDeviceEventInfoEXT  *device_event_info,
@@ -267,26 +279,31 @@ tu_RegisterDeviceEventEXT(VkDevice                    _device,
                           VkFence                     *_fence)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
-   struct tu_fence            *fence;
-   VkResult                     ret;
-
-   fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
-                     8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (!fence)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
-
-   tu_fence_init(fence, false);
-
-   ret = wsi_register_device_event(_device,
-                                   &device->physical_device->wsi_device,
-                                   device_event_info,
-                                   allocator,
-                                   &fence->fence_wsi,
-                                   -1);
-   if (ret == VK_SUCCESS)
-      *_fence = tu_fence_to_handle(fence);
-   else
-      vk_free2(&device->instance->alloc, allocator, fence);
+   VkResult ret;
+
+   ret = tu_CreateFence(_device, &(VkFenceCreateInfo) {}, allocator, _fence);
+   if (ret != VK_SUCCESS)
+      return ret;
+
+   TU_FROM_HANDLE(tu_fence, fence, *_fence);
+
+   int sync_fd = import_syncobj(device->fd, fence->syncobj);
+   if (sync_fd >= 0) {
+      ret = wsi_register_device_event(_device,
+                                      &device->physical_device->wsi_device,
+                                      device_event_info,
+                                      allocator,
+                                      NULL,
+                                      sync_fd);
+   } else {
+      ret = VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
+
+   close(sync_fd);
+
+   if (ret != VK_SUCCESS)
+      tu_DestroyFence(_device, *_fence, allocator);
+
    return ret;
 }
 
@@ -298,29 +315,32 @@ tu_RegisterDisplayEventEXT(VkDevice                           _device,
                            VkFence                            *_fence)
 {
    TU_FROM_HANDLE(tu_device, device, _device);
+   VkResult ret;
 
-   struct tu_fence            *fence;
-   VkResult                     ret;
+   ret = tu_CreateFence(_device, &(VkFenceCreateInfo) {}, allocator, _fence);
+   if (ret != VK_SUCCESS)
+      return ret;
 
-   fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
-                     8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
-   if (!fence)
-      return VK_ERROR_OUT_OF_HOST_MEMORY;
+   TU_FROM_HANDLE(tu_fence, fence, *_fence);
 
-   tu_fence_init(fence, false);
+   int sync_fd = import_syncobj(device->fd, fence->syncobj);
+   if (sync_fd >= 0) {
+      ret = wsi_register_display_event(_device,
+                                       &device->physical_device->wsi_device,
+                                       display,
+                                       display_event_info,
+                                       allocator,
+                                       NULL,
+                                       sync_fd);
+   } else {
+      ret = VK_ERROR_OUT_OF_HOST_MEMORY;
+   }
 
-   ret = wsi_register_display_event(_device,
-                                    &device->physical_device->wsi_device,
-                                    display,
-                                    display_event_info,
-                                    allocator,
-                                    &fence->fence_wsi,
-                                    -1);
+   close(sync_fd);
+
+   if (ret != VK_SUCCESS)
+      tu_DestroyFence(_device, *_fence, allocator);
 
-   if (ret == VK_SUCCESS)
-      *_fence = tu_fence_to_handle(fence);
-   else
-      vk_free2(&device->instance->alloc, allocator, fence);
    return ret;
 }
 



More information about the mesa-commit mailing list