[lavapipe] Integrate semaphore logic w/ lvp_pipe_sync.

Change-Id: I3799c55ed76e4e58e1b231491096320a17fae3e3
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/mesa/+/1033839
Commit-Queue: John Rosasco <rosasco@google.com>
Reviewed-by: Craig Stout <cstout@google.com>
diff --git a/src/gallium/frontends/lavapipe/BUILD.gn b/src/gallium/frontends/lavapipe/BUILD.gn
index 85618fa..059d9fb 100644
--- a/src/gallium/frontends/lavapipe/BUILD.gn
+++ b/src/gallium/frontends/lavapipe/BUILD.gn
@@ -109,15 +109,6 @@
     "$mesa_build_root/src/vulkan/util",
   ]
 
-  if(target_os == "fuchsia") {
-    public_deps += [ "$mesa_build_root/src/vulkan/wsi:stub" ]
-    deps += [ "$mesa_build_root/src/vulkan/runtime:zircon" ]
-  } else {
-    public_deps += [ "$mesa_build_root/src/vulkan/wsi" ]
-    deps += [ "$mesa_build_root/src/vulkan/runtime" ]
-  }
-
-
   sources = [
     # target.c is not used by our sibling meson.build, but rather by
     # //mesa/src/gallium/targets/lavapipe/meson.build.  We include it here because it's not worth
@@ -144,6 +135,16 @@
     "lvp_util.c",
     "lvp_wsi.c",
   ]
+
+  if(target_os == "fuchsia") {
+    public_deps += [ "$mesa_build_root/src/vulkan/wsi:stub" ]
+    deps += [ "$mesa_build_root/src/vulkan/runtime:zircon" ]
+    sources += [ "lvp_pipe_sync_fuchsia.c" ]
+  } else {
+    public_deps += [ "$mesa_build_root/src/vulkan/wsi" ]
+    deps += [ "$mesa_build_root/src/vulkan/runtime" ]
+  }
+
 }
 
 # Implements VK_FUCHSIA_buffer_collection.
diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c
index 847ed8d..40d3218 100644
--- a/src/gallium/frontends/lavapipe/lvp_device.c
+++ b/src/gallium/frontends/lavapipe/lvp_device.c
@@ -50,7 +50,6 @@
 #include "lvp_fuchsia.h"
 #include "lvp_fuchsia_buffer_collection.h"
 #include "lvp_fuchsia_memory.h"
-#include "vulkan/runtime/vk_zircon_syncobj.h"
 #endif
 
 #if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
@@ -280,12 +279,12 @@
 
    device->sync_timeline_type = vk_sync_timeline_get_type(&lvp_pipe_sync_type);
    uint32_t st = 0;
+#if VK_USE_PLATFORM_FUCHSIA
+   device->sync_types[st++] = &lvp_pipe_sync_fuchsia_type;
+#else
    device->sync_types[st++] = &lvp_pipe_sync_type;
-   device->sync_types[st++] = &device->sync_timeline_type.sync;
-#ifdef VK_USE_PLATFORM_FUCHSIA
-   device->zircon_sync_type = vk_zircon_syncobj_get_type();
-   device->sync_types[st++] = &device->zircon_sync_type;
 #endif
+   device->sync_types[st++] = &device->sync_timeline_type.sync;
    device->sync_types[st] = NULL;
    assert(st < MAX_SYNC_TYPES);
    device->vk.supported_sync_types = device->sync_types;
@@ -1565,9 +1564,15 @@
       queue->ctx->flush(queue->ctx, &queue->last_fence, 0);
 
    for (uint32_t i = 0; i < submit->signal_count; i++) {
+#ifdef VK_USE_PLATFORM_FUCHSIA
+      struct lvp_pipe_sync_fuchsia *sync =
+         vk_sync_as_lvp_pipe_sync_fuchsia(submit->signals[i].sync);
+      lvp_pipe_sync_fuchsia_signal_with_fence(queue->device, sync, queue->last_fence);
+#else
       struct lvp_pipe_sync *sync =
          vk_sync_as_lvp_pipe_sync(submit->signals[i].sync);
       lvp_pipe_sync_signal_with_fence(queue->device, sync, queue->last_fence);
+#endif
    }
    destroy_pipelines(queue);
 
diff --git a/src/gallium/frontends/lavapipe/lvp_pipe_sync_fuchsia.c b/src/gallium/frontends/lavapipe/lvp_pipe_sync_fuchsia.c
new file mode 100644
index 0000000..317a51b
--- /dev/null
+++ b/src/gallium/frontends/lavapipe/lvp_pipe_sync_fuchsia.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright © 2024 Google, LLC
+ *
+ * based in part on lvp_pipe_sync.c which is
+ * Copyright © 2022 Collabora Ltd.
+ *
+ * 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 <zircon/errors.h>
+#include <zircon/syscalls.h>
+#include <zircon/time.h>
+#include <zircon/types.h>
+
+#include "lvp_private.h"
+#include "util/log.h"
+#include "vk_log.h"
+#include "vulkan/vulkan_core.h"
+
+#define ZX_STATUS_VK_RTN(status, device, message)                 \
+  switch (status) {                                               \
+    case ZX_OK:                                                   \
+      return VK_SUCCESS;                                          \
+    case ZX_ERR_BAD_HANDLE:                                       \
+      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,  \
+                       "%s - Bad Zircon handle: %m", message);    \
+    case ZX_ERR_TIMED_OUT:                                        \
+      return VK_TIMEOUT;                                          \
+    default:                                                      \
+      return vk_errorf(device, VK_ERROR_UNKNOWN,                  \
+                       "%s - Unknown Zircon error: %m", message); \
+  }
+
+/* No-op when status == ZX_OK. */
+#define ZX_STATUS_VK_RTN_ERR(status, device, message)             \
+  switch (status) {                                               \
+    case ZX_OK:                                                   \
+      break;                                                      \
+    case ZX_ERR_BAD_HANDLE:                                       \
+      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,  \
+                       "%s - Bad Zircon handle: %m", message);    \
+    case ZX_ERR_TIMED_OUT:                                        \
+      return VK_TIMEOUT;                                          \
+    default:                                                      \
+      return vk_errorf(device, VK_ERROR_UNKNOWN,                  \
+                       "%s - Unknown Zircon error: %m", message); \
+  }
+
+static bool is_signaled(zx_handle_t handle) {
+  zx_status_t status = zx_object_wait_one(handle, ZX_EVENT_SIGNALED, 0, NULL);
+  return (status == ZX_OK);
+}
+
+static void lvp_pipe_sync_fuchsia_validate(
+    ASSERTED struct lvp_pipe_sync_fuchsia *sync) {
+  if (is_signaled(sync->signaled)) assert(sync->fence == NULL);
+}
+
+static VkResult lvp_pipe_sync_fuchsia_init(UNUSED struct vk_device *vk_device,
+                                           struct vk_sync *vk_sync,
+                                           uint64_t initial_value) {
+  struct lvp_pipe_sync_fuchsia *sync =
+      vk_sync_as_lvp_pipe_sync_fuchsia(vk_sync);
+
+  zx_handle_t handle = (zx_handle_t)initial_value;
+
+  /* |initial_value| is overloaded to convey zx_handle_t handles. */
+  /* If it's set and not 1, it's a zx_handle_t. */
+  if (initial_value && initial_value != 1) {
+    assert((initial_value >> 32) == 0);
+    /* Close existing handle if it exists. */
+    if (sync->signaled != ZX_HANDLE_INVALID) {
+      if (zx_handle_close(sync->signaled) != ZX_OK) {
+        return vk_errorf(vk_device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+                         "Init (close): %m");
+      }
+    }
+
+    /* Duplicate and store |handle| into |sync->signaled|. */
+    zx_status_t status =
+        zx_handle_replace(handle, ZX_RIGHT_SAME_RIGHTS, &sync->signaled);
+    ZX_STATUS_VK_RTN_ERR(status, vk_device, "Init (replace)");
+  } else {
+    zx_status_t status = zx_event_create(0, &sync->signaled);
+    if (status != ZX_OK) {
+      assert(status == ZX_ERR_NO_MEMORY);
+      return vk_errorf(vk_device, VK_ERROR_OUT_OF_HOST_MEMORY,
+                       "Init (event create): %m");
+    }
+    if (initial_value == 1) {
+      zx_status_t status =
+          zx_object_signal(sync->signaled, 0u, ZX_EVENT_SIGNALED);
+      ZX_STATUS_VK_RTN(status, vk_device, "Init (signal)");
+    }
+  }
+  sync->fence = NULL;
+
+  return VK_SUCCESS;
+}
+
+static void lvp_pipe_sync_fuchsia_finish(struct vk_device *vk_device,
+                                         struct vk_sync *vk_sync) {
+  struct lvp_device *device = container_of(vk_device, struct lvp_device, vk);
+  struct lvp_pipe_sync_fuchsia *sync =
+      vk_sync_as_lvp_pipe_sync_fuchsia(vk_sync);
+
+  lvp_pipe_sync_fuchsia_validate(sync);
+  if (sync->fence)
+    device->pscreen->fence_reference(device->pscreen, &sync->fence, NULL);
+  if (sync->signaled == ZX_HANDLE_INVALID) {
+    vk_logi(VK_LOG_OBJS(device), "Finish - invalid handle\n");
+    return;
+  }
+  zx_status_t status = zx_handle_close(sync->signaled);
+  switch (status) {
+    case ZX_OK:
+      break;
+    case ZX_ERR_BAD_HANDLE:
+      vk_loge(VK_LOG_OBJS(device),
+              "Finish - attempt to close bad Zircon event handle.\n");
+      return;
+    default:
+      vk_loge(VK_LOG_OBJS(device), "Finish - Unknown error.\n");
+      return;
+  }
+  sync->signaled = ZX_HANDLE_INVALID;
+}
+
+void lvp_pipe_sync_fuchsia_signal_with_fence(struct lvp_device *device,
+                                             struct lvp_pipe_sync_fuchsia *sync,
+                                             struct pipe_fence_handle *fence) {
+  lvp_pipe_sync_fuchsia_validate(sync);
+  if (fence == NULL) {
+    if (zx_object_signal(sync->signaled, 0u, ZX_EVENT_SIGNALED) != ZX_OK) {
+      mesa_loge("Signal with fence (== NULL) failed.");
+    }
+  } else {
+    if (zx_object_signal(sync->signaled, ZX_EVENT_SIGNALED, 0u) != ZX_OK) {
+      mesa_loge("Signal with fence (!= NULL) failed.");
+    }
+  }
+  device->pscreen->fence_reference(device->pscreen, &sync->fence, fence);
+}
+
+static VkResult lvp_pipe_sync_fuchsia_signal(struct vk_device *vk_device,
+                                             struct vk_sync *vk_sync,
+                                             uint64_t value) {
+  struct lvp_device *device = container_of(vk_device, struct lvp_device, vk);
+  struct lvp_pipe_sync_fuchsia *sync =
+      vk_sync_as_lvp_pipe_sync_fuchsia(vk_sync);
+
+  lvp_pipe_sync_fuchsia_validate(sync);
+  zx_status_t status = zx_object_signal(sync->signaled, 0u, ZX_EVENT_SIGNALED);
+  if (status == ZX_OK) {
+    if (sync->fence)
+      device->pscreen->fence_reference(device->pscreen, &sync->fence, NULL);
+    return VK_SUCCESS;
+  }
+  ZX_STATUS_VK_RTN(status, vk_device, "Signal (signal)");
+}
+
+static VkResult lvp_pipe_sync_fuchsia_reset(struct vk_device *vk_device,
+                                            struct vk_sync *vk_sync) {
+  struct lvp_device *device = container_of(vk_device, struct lvp_device, vk);
+  struct lvp_pipe_sync_fuchsia *sync =
+      vk_sync_as_lvp_pipe_sync_fuchsia(vk_sync);
+
+  lvp_pipe_sync_fuchsia_validate(sync);
+  if (sync->signaled == ZX_HANDLE_INVALID) {
+    return vk_errorf(
+        device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+        "Reset - Attempt to reset invalid Zircon event handle: %m");
+  }
+
+  zx_status_t status = zx_object_signal(sync->signaled, ZX_EVENT_SIGNALED, 0u);
+  if (status == ZX_OK) {
+    if (sync->fence)
+      device->pscreen->fence_reference(device->pscreen, &sync->fence, NULL);
+  }
+  ZX_STATUS_VK_RTN(status, vk_device, "Reset (signal)");
+}
+
+static VkResult lvp_pipe_sync_fuchsia_move(struct vk_device *vk_device,
+                                           struct vk_sync *vk_dst,
+                                           struct vk_sync *vk_src) {
+  struct lvp_device *device = container_of(vk_device, struct lvp_device, vk);
+  struct lvp_pipe_sync_fuchsia *dst = vk_sync_as_lvp_pipe_sync_fuchsia(vk_dst);
+  struct lvp_pipe_sync_fuchsia *src = vk_sync_as_lvp_pipe_sync_fuchsia(vk_src);
+
+  if (src->signaled == ZX_HANDLE_INVALID) {
+    return vk_errorf(&device->vk, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+                     "Move - Unable to move invalid handle: %m");
+  }
+
+  zx_handle_t handle_out = ZX_HANDLE_INVALID;
+  zx_status_t status =
+      zx_handle_replace(src->signaled, ZX_RIGHT_SAME_RIGHTS, &handle_out);
+  ZX_STATUS_VK_RTN_ERR(status, &device->vk, "Move (replace)");
+
+  src->signaled = ZX_HANDLE_INVALID;
+  *dst = *src;
+  dst->signaled = handle_out;
+
+  return VK_SUCCESS;
+}
+
+static VkResult lvp_pipe_sync_fuchsia_wait(struct vk_device *vk_device,
+                                           struct vk_sync *vk_sync,
+                                           uint64_t wait_value,
+                                           enum vk_sync_wait_flags wait_flags,
+                                           uint64_t abs_timeout_ns) {
+  struct lvp_device *device = container_of(vk_device, struct lvp_device, vk);
+  struct lvp_pipe_sync_fuchsia *sync =
+      vk_sync_as_lvp_pipe_sync_fuchsia(vk_sync);
+
+  assert(!(wait_flags & VK_SYNC_WAIT_ANY));
+
+  lvp_pipe_sync_fuchsia_validate(sync);
+
+  zx_status_t status = ZX_OK;
+  zx_time_t now_ns = zx_clock_get_monotonic();
+  abs_timeout_ns =
+      (abs_timeout_ns > ZX_TIME_INFINITE) ? ZX_TIME_INFINITE : abs_timeout_ns;
+  while (!is_signaled(sync->signaled) && !sync->fence) {
+    if (now_ns >= abs_timeout_ns) return VK_TIMEOUT;
+    status = zx_object_wait_one(sync->signaled, ZX_EVENT_SIGNALED,
+                                (zx_time_t)abs_timeout_ns, NULL);
+    ZX_STATUS_VK_RTN_ERR(status, device, "Wait (wait one)");
+    lvp_pipe_sync_fuchsia_validate(sync);
+    now_ns = zx_clock_get_monotonic();
+  }
+
+  if (is_signaled(sync->signaled) || (wait_flags & VK_SYNC_WAIT_PENDING))
+    return VK_SUCCESS;
+
+  /* Grab a reference before we drop the lock */
+  struct pipe_fence_handle *fence = NULL;
+  device->pscreen->fence_reference(device->pscreen, &fence, sync->fence);
+
+  uint64_t rel_timeout_ns =
+      now_ns >= abs_timeout_ns ? 0 : abs_timeout_ns - now_ns;
+  bool complete = device->pscreen->fence_finish(device->pscreen, NULL, fence,
+                                                rel_timeout_ns);
+
+  device->pscreen->fence_reference(device->pscreen, &fence, NULL);
+
+  lvp_pipe_sync_fuchsia_validate(sync);
+
+  if (!complete) return VK_TIMEOUT;
+
+  if (sync->fence == fence) {
+    device->pscreen->fence_reference(device->pscreen, &sync->fence, NULL);
+    status = zx_object_signal(sync->signaled, 0u, ZX_EVENT_SIGNALED);
+    ZX_STATUS_VK_RTN_ERR(status, device, "Wait (signal)");
+  }
+
+  return VK_SUCCESS;
+}
+
+static VkResult lvp_pipe_sync_fuchsia_import_zircon_handle(
+    struct vk_device *device, struct vk_sync *sync, uint32_t handle) {
+  struct lvp_pipe_sync_fuchsia *sobj = vk_sync_as_lvp_pipe_sync_fuchsia(sync);
+  zx_handle_t semaphore = ZX_HANDLE_INVALID;
+
+  zx_status_t status =
+      zx_handle_replace(handle, ZX_RIGHT_SAME_RIGHTS, &semaphore);
+  ZX_STATUS_VK_RTN_ERR(status, device, "Import (replace)");
+  status = zx_handle_close(sobj->signaled);
+  if (status == ZX_OK) {
+    sobj->signaled = semaphore;
+    return VK_SUCCESS;
+  }
+  zx_handle_close(semaphore);
+  ZX_STATUS_VK_RTN(status, device, "Import (close - signaled)");
+}
+
+static VkResult lvp_pipe_sync_fuchsia_export_zircon_handle(
+    struct vk_device *device, struct vk_sync *sync, uint32_t *handle_out) {
+  struct lvp_pipe_sync_fuchsia *sobj = vk_sync_as_lvp_pipe_sync_fuchsia(sync);
+
+  if (sobj->signaled == ZX_HANDLE_INVALID) {
+    return vk_errorf(
+        device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+        "Export - Attempt to export invalid Zircon event handle: %m");
+  }
+
+  zx_status_t status =
+      zx_handle_duplicate(sobj->signaled, ZX_RIGHT_SAME_RIGHTS, handle_out);
+  ZX_STATUS_VK_RTN(status, device, "Export (duplicate)");
+}
+
+const struct vk_sync_type lvp_pipe_sync_fuchsia_type = {
+    .size = sizeof(struct lvp_pipe_sync_fuchsia),
+    .features = VK_SYNC_FEATURE_BINARY | VK_SYNC_FEATURE_GPU_WAIT |
+                VK_SYNC_FEATURE_GPU_MULTI_WAIT | VK_SYNC_FEATURE_CPU_WAIT |
+                VK_SYNC_FEATURE_CPU_RESET | VK_SYNC_FEATURE_CPU_SIGNAL |
+                VK_SYNC_FEATURE_WAIT_PENDING,
+    .init = lvp_pipe_sync_fuchsia_init,
+    .finish = lvp_pipe_sync_fuchsia_finish,
+    .signal = lvp_pipe_sync_fuchsia_signal,
+    .reset = lvp_pipe_sync_fuchsia_reset,
+    .move = lvp_pipe_sync_fuchsia_move,
+    .wait = lvp_pipe_sync_fuchsia_wait,
+    .import_zircon_handle = lvp_pipe_sync_fuchsia_import_zircon_handle,
+    .export_zircon_handle = lvp_pipe_sync_fuchsia_export_zircon_handle,
+};
diff --git a/src/gallium/frontends/lavapipe/lvp_private.h b/src/gallium/frontends/lavapipe/lvp_private.h
index f1f10b4..88e08af 100644
--- a/src/gallium/frontends/lavapipe/lvp_private.h
+++ b/src/gallium/frontends/lavapipe/lvp_private.h
@@ -135,9 +135,6 @@
    uint32_t max_images;
 
    struct vk_sync_timeline_type sync_timeline_type;
-#if VK_USE_PLATFORM_FUCHSIA
-   struct vk_sync_type zircon_sync_type;
-#endif
    const struct vk_sync_type *sync_types[MAX_SYNC_TYPES];
 
    VkPhysicalDeviceLimits device_limits;
@@ -221,6 +218,32 @@
    };
 };
 
+#ifdef VK_USE_PLATFORM_FUCHSIA
+struct lvp_pipe_sync_fuchsia {
+  struct vk_sync base;
+
+  /* |signaled| is a zx event handle in the Fuchsia case.
+   * The name signaled chosen to be consistent with lvp_pipe_sync
+   * |signaled| field below. */
+  zx_handle_t signaled;
+
+  struct pipe_fence_handle *fence;
+};
+
+extern const struct vk_sync_type lvp_pipe_sync_fuchsia_type;
+
+void lvp_pipe_sync_fuchsia_signal_with_fence(struct lvp_device *device,
+                                             struct lvp_pipe_sync_fuchsia *sync,
+                                             struct pipe_fence_handle *fence);
+
+static inline struct lvp_pipe_sync_fuchsia *
+vk_sync_as_lvp_pipe_sync_fuchsia(struct vk_sync *sync)
+{
+   assert(sync->type == &lvp_pipe_sync_fuchsia_type);
+   return container_of(sync, struct lvp_pipe_sync_fuchsia, base);
+}
+#endif
+
 struct lvp_pipe_sync {
    struct vk_sync base;
 
@@ -228,6 +251,7 @@
    cnd_t changed;
 
    bool signaled;
+
    struct pipe_fence_handle *fence;
 };
 
@@ -236,7 +260,6 @@
 void lvp_pipe_sync_signal_with_fence(struct lvp_device *device,
                                      struct lvp_pipe_sync *sync,
                                      struct pipe_fence_handle *fence);
-
 static inline struct lvp_pipe_sync *
 vk_sync_as_lvp_pipe_sync(struct vk_sync *sync)
 {
diff --git a/src/vulkan/runtime/BUILD.gn b/src/vulkan/runtime/BUILD.gn
index 691983c..e3af2d8 100644
--- a/src/vulkan/runtime/BUILD.gn
+++ b/src/vulkan/runtime/BUILD.gn
@@ -148,6 +148,7 @@
   configs = [ "//build/config:Wno-strict-prototypes" ]
 }
 
+
 mesa_source_set("zircon") {
   public_configs = [ ":common" ]
 
@@ -160,8 +161,6 @@
     "$target_gen_dir/vk_common_entrypoints.c",
     "$target_gen_dir/vk_dispatch_trampolines.c",
     "$target_gen_dir/vk_physical_device_features.c",
-    "vk_zircon_syncobj.c",
-    "vk_zircon_syncobj.h"
   ] + runtime_sources + runtime_headers
 
   configs = [ "//build/config:Wno-strict-prototypes" ]
diff --git a/src/vulkan/runtime/vk_zircon_syncobj.c b/src/vulkan/runtime/vk_zircon_syncobj.c
deleted file mode 100644
index 475a8a6..0000000
--- a/src/vulkan/runtime/vk_zircon_syncobj.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright © 2024 The Fuchsia Authors
- *
- * 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 "vk_zircon_syncobj.h"
-
-#include <string.h>
-#include <zircon/syscalls.h>
-#include <zircon/syscalls/port.h>
-
-#include "vk_device.h"
-#include "vk_log.h"
-#include "vk_util.h"
-
-static struct vk_zircon_syncobj *
-to_zircon_syncobj(struct vk_sync *sync)
-{
-   assert(vk_sync_type_is_zircon_syncobj(sync->type));
-   return container_of(sync, struct vk_zircon_syncobj, base);
-}
-
-static VkResult vk_zircon_syncobj_init(struct vk_device *device,
-                                       struct vk_sync *sync,
-                                       uint64_t initial_value) {
-  struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-  zx_handle_t handle = (zx_handle_t) initial_value;
-
-  assert((sync->flags & VK_SYNC_IS_TIMELINE) == 0);
-
-  /* |initial_value| is overloaded to convey zx_handle_t handles. */
-  /* If it's set and not 1, it's a zx_handle_t. */
-  if (initial_value && initial_value != 1) {
-    assert((initial_value >> 32) == 0);
-    /* Close existing handle if it exists. */
-    if (sobj->semaphore != ZX_HANDLE_INVALID) {
-      if (zx_handle_close(sobj->semaphore) != ZX_OK) {
-        return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                         "Unable to close handle: %m");
-      }
-    }
-
-    /* Duplicate and store |handle| into |sobj->semaphore|. */
-    zx_status_t status =
-      zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS,
-                          (zx_handle_t *) &sobj->semaphore);
-    if(status != ZX_OK) {
-      if(status == ZX_ERR_BAD_HANDLE)
-        return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                         "Unable to initialize, bad Zircon handle: %m");
-      else
-        return vk_errorf(device, VK_ERROR_UNKNOWN,
-                         "Unable to initialize: %m");
-    }
-
-    /* Close original |handle| to invalidate it. */
-    if (zx_handle_close(handle) != ZX_OK) {
-      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                       "Unable to close handle: %m");
-    }
-  } else {
-    zx_status_t status = zx_event_create(0, (zx_handle_t *) &sobj->semaphore);
-    if (status != ZX_OK) {
-      assert(status == ZX_ERR_NO_MEMORY);
-      return vk_errorf(device, VK_ERROR_OUT_OF_HOST_MEMORY,
-                       "Unable to create semaphore: %m");
-    }
-  }
-
-  if (initial_value == 1) {
-    zx_status_t status =
-      zx_object_signal((zx_handle_t) sobj->semaphore, 0u, ZX_EVENT_SIGNALED);
-    if(status != ZX_OK) {
-      return vk_errorf(device, VK_ERROR_UNKNOWN,
-                       "Unable to signal semaphore: %m");
-    }
-  }
-
-  return VK_SUCCESS;
-}
-
-void
-vk_zircon_syncobj_finish(struct vk_device *device,
-                         struct vk_sync *sync)
-{
-   struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-   if (sobj->semaphore == ZX_HANDLE_INVALID) {
-      vk_logi(VK_LOG_OBJS(device), "Attempt to close invalid Zircon event handle.\n");
-      return;
-   }
-   zx_status_t status = zx_handle_close(sobj->semaphore);
-   if (status == ZX_ERR_BAD_HANDLE) {
-     vk_loge(VK_LOG_OBJS(device), "Attempt to close bad Zircon event handle.\n");
-     return;
-   }
-   assert(status == ZX_OK);
-   sobj->semaphore = ZX_HANDLE_INVALID;
-}
-
-static VkResult
-vk_zircon_syncobj_signal(struct vk_device *device,
-                         struct vk_sync *sync,
-                         uint64_t value)
-{
-   struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-   if (sobj->semaphore == ZX_HANDLE_INVALID) {
-      return vk_errorf(device, VK_ERROR_UNKNOWN,
-                       "Attempt to signal invalid Zircon event handle: %m");
-   }
-
-   zx_status_t status = zx_object_signal(sobj->semaphore, 0u, ZX_EVENT_SIGNALED);
-   switch(status) {
-     case ZX_OK:
-       return VK_SUCCESS;
-     case ZX_ERR_BAD_HANDLE:
-       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                        "Unable to signal semaphore, bad Zircon handle: %m");
-     default:
-       return vk_errorf(device, VK_ERROR_UNKNOWN, "Unable to signal semaphore: %m");
-   }
-}
-
-static VkResult
-vk_zircon_syncobj_reset(struct vk_device *device,
-                        struct vk_sync *sync)
-{
-   struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-   if (sobj->semaphore == ZX_HANDLE_INVALID) {
-      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                       "Attempt to reset invalid Zircon event handle: %m");
-   }
-
-   zx_status_t status = zx_object_signal(sobj->semaphore, ZX_EVENT_SIGNALED, 0u);
-   switch(status) {
-     case ZX_OK:
-       return VK_SUCCESS;
-     case ZX_ERR_BAD_HANDLE:
-       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                        "Unable to reset semaphore, bad Zircon handle: %m");
-     default:
-       return vk_errorf(device, VK_ERROR_UNKNOWN, "Unable to reset semaphore: %m");
-   }
-}
-
-static VkResult
-vk_zircon_syncobj_wait_many(struct vk_device *device,
-                            uint32_t wait_count,
-                            const struct vk_sync_wait *waits,
-                            enum vk_sync_wait_flags wait_flags,
-                            uint64_t abs_timeout_ns)
-{
-   assert((wait_flags & VK_SYNC_WAIT_PENDING) == 0);
-   if(!wait_count) return VK_SUCCESS;
-
-   /* Syncobj timeouts are signed. */
-   abs_timeout_ns = MIN2(abs_timeout_ns, (uint64_t)ZX_TIME_INFINITE);
-
-   /* Create port on which to monitor signaled semaphores. */
-   zx_handle_t port = ZX_HANDLE_INVALID;
-   zx_status_t status = zx_port_create(0, &port);
-   if(status != ZX_OK) {
-     return vk_errorf(device, VK_ERROR_UNKNOWN, "Unable to create port: %m");
-   }
-
-   /* Enqueue all semaphores (events) on the port. */
-   for (uint32_t i = 0; i < wait_count; i++) {
-      uint64_t semaphore = to_zircon_syncobj(waits[i].sync)->semaphore;
-      status = zx_object_wait_async(semaphore, port, i /* key */, ZX_EVENT_SIGNALED,
-                                    0 /* options */);
-      if (status != ZX_OK) {
-        return vk_errorf(device, VK_ERROR_UNKNOWN, "Unable to queue semaphore on port: %m");
-      }
-   }
-
-   status = ZX_OK;
-   const bool kWaitAll = (wait_flags & VK_SYNC_WAIT_ANY) == 0;
-   zx_port_packet_t packet = {0};
-   if(kWaitAll) {
-     const size_t kMaxMasks = 16;
-     uint64_t masks[kMaxMasks];
-     uint64_t *masks_base = NULL;
-     uint64_t *masks_ptr = masks;
-     const uint32_t num_masks = ((wait_count - 1) / 64) + 1;
-     if(num_masks > kMaxMasks) {
-        masks_base = (uint64_t *) malloc(num_masks * sizeof(uint64_t));
-        if(!masks_base) {
-          return vk_errorf(device, VK_ERROR_OUT_OF_HOST_MEMORY, "Masks alloc failed: %m");
-        }
-        masks_ptr = masks_base;
-     }
-     memset(masks_ptr, 0xFF, num_masks * sizeof(uint64_t));
-
-     /* Clear all unused bits of the last mask. */
-     *(masks_ptr + num_masks - 1) >>= (64 - (wait_count % 64));
-     int cleared_masks = 0;
-     while(cleared_masks < num_masks) {
-       status = zx_port_wait(port, abs_timeout_ns, &packet);
-       const uint32_t mask_index = packet.key / 64;
-       switch(status) {
-         case ZX_OK:
-           /* Knock out the bit for the current signal. */
-           *(masks_ptr + mask_index) &= ~(1 << (packet.key % 64));
-           for(cleared_masks = 0; cleared_masks < num_masks; cleared_masks++) {
-             if(*(masks_ptr + cleared_masks)) {
-               break;
-             }
-           }
-           break;
-         default:
-           cleared_masks = num_masks;
-           break;
-       }
-     }
-     if(masks_base) free(masks_base);
-   } else {
-     /* Wait for any event signal. */
-     status = zx_port_wait(port, abs_timeout_ns, &packet);
-   }
-
-   switch(status) {
-     case ZX_OK:
-       return VK_SUCCESS;
-     case ZX_ERR_TIMED_OUT:
-       return vk_errorf(device, VK_TIMEOUT, "zx_port_wait timed out: %m");
-     default:
-       return vk_errorf(device, VK_ERROR_UNKNOWN, "zx_port_wait failed: %m");
-   }
-}
-
-static VkResult
-vk_zircon_syncobj_import_zircon_handle(struct vk_device *device,
-                                       struct vk_sync *sync,
-                                       uint32_t handle)
-{
-   struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-   zx_handle_t semaphore = ZX_HANDLE_INVALID;
-
-   zx_status_t status =
-     zx_handle_duplicate(handle, ZX_RIGHT_SAME_RIGHTS, &semaphore);
-   if(status != ZX_OK) {
-     if(status == ZX_ERR_BAD_HANDLE)
-        return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                         "Unable to import, bad Zircon handle: %m");
-     else
-        return vk_errorf(device, VK_ERROR_UNKNOWN,
-                         "Unable to import handle: %m");
-   }
-
-   if (zx_handle_close(handle) != ZX_OK) {
-     return vk_errorf(device, VK_ERROR_UNKNOWN,
-                      "Unable to import handle: %m");
-   }
-
-   status = zx_handle_close((zx_handle_t) sobj->semaphore);
-   switch(status) {
-     case ZX_OK:
-       sobj->semaphore = (uint64_t) semaphore;
-       return VK_SUCCESS;
-     case ZX_ERR_BAD_HANDLE:
-       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                        "Unable to import, bad Zircon handle: %m");
-     default:
-        return vk_errorf(device, VK_ERROR_UNKNOWN,
-                         "Unable to import handle: %m");
-   }
-}
-
-static VkResult
-vk_zircon_syncobj_export_zircon_handle(struct vk_device *device,
-                                       struct vk_sync *sync,
-                                       uint32_t* handle_out)
-{
-   struct vk_zircon_syncobj *sobj = to_zircon_syncobj(sync);
-
-   if (sobj->semaphore == ZX_HANDLE_INVALID) {
-      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                       "Attempt to export invalid Zircon event handle: %m");
-   }
-
-   zx_status_t status = zx_handle_duplicate(sobj->semaphore,
-                                            ZX_RIGHT_SAME_RIGHTS, handle_out);
-   switch(status) {
-     case ZX_OK:
-       return VK_SUCCESS;
-     case ZX_ERR_BAD_HANDLE:
-       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                        "Unable to export, bad Zircon handle: %m");
-     default:
-       return vk_errorf(device, VK_ERROR_UNKNOWN,
-                        "Unable to export handle: %m");
-   }
-}
-
-static VkResult
-vk_zircon_syncobj_move(struct vk_device *device,
-                       struct vk_sync *dst,
-                       struct vk_sync *src)
-{
-  struct vk_zircon_syncobj *dst_sobj = to_zircon_syncobj(dst);
-  struct vk_zircon_syncobj *src_sobj = to_zircon_syncobj(src);
-
-  if(src_sobj->semaphore == ZX_HANDLE_INVALID) {
-    return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                     "Unable to move invalid handle: %m");
-  }
-
-  zx_handle_t handle_out = ZX_HANDLE_INVALID;
-  zx_status_t status = zx_handle_duplicate(src_sobj->semaphore,
-                         ZX_RIGHT_SAME_RIGHTS, &handle_out);
-  if(status != ZX_OK) {
-    if(status == ZX_ERR_BAD_HANDLE)
-      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                       "Unable to move, bad Zircon handle: %m");
-    else
-      return vk_errorf(device, VK_ERROR_UNKNOWN,
-                       "Unable to move handle: %m");
-  }
-
-  if (zx_handle_close((zx_handle_t) src_sobj->semaphore) != ZX_OK) {
-    return vk_errorf(device, VK_ERROR_UNKNOWN,
-                     "Unable to close (move) src semaphore handle: %m");
-  }
-
-  src_sobj->semaphore = ZX_HANDLE_INVALID;
-
-  *dst_sobj = *src_sobj;
-  dst_sobj->semaphore = (uint64_t) handle_out;
-
-  return VK_SUCCESS;
-}
-
-struct vk_sync_type
-vk_zircon_syncobj_get_type(void)
-{
-   struct vk_sync_type type = {
-      .size = sizeof(struct vk_zircon_syncobj),
-      .features = VK_SYNC_FEATURE_BINARY |
-                  VK_SYNC_FEATURE_GPU_WAIT |
-                  VK_SYNC_FEATURE_CPU_RESET |
-                  VK_SYNC_FEATURE_CPU_SIGNAL |
-                  VK_SYNC_FEATURE_CPU_WAIT |
-                  VK_SYNC_FEATURE_WAIT_PENDING |
-                  VK_SYNC_FEATURE_WAIT_ANY,
-      .init = vk_zircon_syncobj_init,
-      .finish = vk_zircon_syncobj_finish,
-      .move = vk_zircon_syncobj_move,
-      .signal = vk_zircon_syncobj_signal,
-      .reset = vk_zircon_syncobj_reset,
-      .wait_many = vk_zircon_syncobj_wait_many,
-      .import_zircon_handle = vk_zircon_syncobj_import_zircon_handle,
-      .export_zircon_handle = vk_zircon_syncobj_export_zircon_handle,
-   };
-
-   return type;
-}
diff --git a/src/vulkan/runtime/vk_zircon_syncobj.h b/src/vulkan/runtime/vk_zircon_syncobj.h
deleted file mode 100644
index de600fb..0000000
--- a/src/vulkan/runtime/vk_zircon_syncobj.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright © 2024 The Fuchsia Authors
- *
- * 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.
- */
-#ifndef VK_ZIRCON_SYNCOBJ_H
-#define VK_ZIRCON_SYNCOBJ_H
-
-#include "vk_sync.h"
-
-#include "util/macros.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct vk_zircon_syncobj {
-   struct vk_sync base;
-   uint64_t semaphore;
-};
-
-void vk_zircon_syncobj_finish(struct vk_device *device,
-                              struct vk_sync *sync);
-
-static inline bool
-vk_sync_type_is_zircon_syncobj(const struct vk_sync_type *type)
-{
-   return type->finish == vk_zircon_syncobj_finish;
-}
-
-static inline struct vk_zircon_syncobj *
-vk_sync_as_zircon_syncobj(struct vk_sync *sync)
-{
-   if (!vk_sync_type_is_zircon_syncobj(sync->type))
-      return NULL;
-
-   return container_of(sync, struct vk_zircon_syncobj, base);
-}
-
-struct vk_sync_type vk_zircon_syncobj_get_type(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* VK_ZIRCON_SYNCOBJ_H */