[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 */