Revert "virglrenderer: carry a patch for venus global fencing"
This reverts commit 74b18b51d4d4a2aa36e9f29dcea7c79065c65d4d.
Reason for revert: https://bugs.chromium.org/p/chromium/issues/detail?id=1223459
Original change's description:
> virglrenderer: carry a patch for venus global fencing
>
> BUG=b:178105513
> BUG=b:176196438
> TEST=vulkan and gl apps run without sync issues
>
> Change-Id: If34021a05fa03d263e6b07ad40eb75c7ded40cb8
> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/2961265
> Reviewed-by: Yiwei Zhang <zzyiwei@google.com>
> Tested-by: Yiwei Zhang <zzyiwei@google.com>
> Commit-Queue: Yiwei Zhang <zzyiwei@google.com>
Bug: b:178105513
Bug: b:176196438
Change-Id: Ia57bb9a298400eca5e65866e610d79a00e65c62e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/overlays/chromiumos-overlay/+/2987699
Auto-Submit: Yiwei Zhang <zzyiwei@chromium.org>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Yiwei Zhang <zzyiwei@google.com>
diff --git a/media-libs/virglrenderer/files/0001-vkr-add-support-for-globalFencing.patch b/media-libs/virglrenderer/files/0001-vkr-add-support-for-globalFencing.patch
deleted file mode 100644
index cb31239..0000000
--- a/media-libs/virglrenderer/files/0001-vkr-add-support-for-globalFencing.patch
+++ /dev/null
@@ -1,780 +0,0 @@
-From 85ea7a915c837265bb1a61515ccd37295aa580eb Mon Sep 17 00:00:00 2001
-From: Chia-I Wu <olvaffe@gmail.com>
-Date: Fri, 4 Jun 2021 12:24:02 -0700
-Subject: [PATCH] vkr: add support for globalFencing
-
-Squashed commit of the following:
-
-commit 86e345c53b4cca905b769a1e33ec973db61a6390 (HEAD)
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Tue Jun 15 23:54:47 2021 -0700
-
- vkr: allow multiple logical devices in some cases
-
- When a logical device does not use external memory/fence/semaphore, we
- know the guest driver does not need queue id 0 to work. Allow such a
- logical device to be created.
-
- This fixes vulkaninfo.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit e4f7534699f0fb3fd76145aefe9531889ecaec1a
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Tue Jun 8 12:39:00 2021 -0700
-
- vkr: advertise globalFencing
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit 0506e4a0b08a5aefae747a80951bda75a4ccc7f1
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Tue Mar 16 16:22:18 2021 -0700
-
- virgl: put virgl and venus on the same fence timeline
-
- In other words, these functions
-
- virgl_renderer_create_fence
- virgl_renderer_poll
- virgl_renderer_export_fence
- (but not virgl_renderer_get_poll_fd)
-
- now work with venus.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit 1384fa12467de52b43fd82bb0539afe5089f5e18
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Tue Mar 16 16:50:02 2021 -0700
-
- vkr: add support for queue_id 0
-
- Becase we advertise only a single VkQueue per-context, we can treat
- queue id 0 as the single VkQueue. When the queue hasn't been created,
- all fences are treated as cpu fences.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit 74a2502aeccec88bc864eeddd3aff20ecd0f1f67
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Fri Jun 11 14:33:44 2021 -0700
-
- vkr: implement virgl_context::export_fence
-
- This assumes there is only a single VkQueue, which can be relaxed if we
- choose to.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit bfff6a49c1cb369b5354b0b0eb53d91e8c702407
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Fri Jun 11 14:41:52 2021 -0700
-
- vkr: restrict to a single VkQueue per-context
-
- This simplifies things when venus joins global fencing.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit d23eba4c95b4e954975c64c5c94e72ad92077481
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Tue Mar 16 16:21:35 2021 -0700
-
- virgl: pass fence flags in fence retire callbacks
-
- This allows us to set internal flags and check for them in the
- retire callbacks.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
-
-commit b3cb1942e49dd16cdf4ce37a3e6a2f67dcc52b4b
-Author: Chia-I Wu <olvaffe@gmail.com>
-Date: Fri Jun 4 12:24:02 2021 -0700
-
- virgl: add virgl_context::export_fence
-
- This is needed when we get per-context version of
- virgl_renderer_export_fence.
-
- Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
- Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
----
- src/virgl_context.h | 6 ++
- src/virglrenderer.c | 191 +++++++++++++++++++++++++++++++++++++++++--
- src/vkr_renderer.c | 165 ++++++++++++++++++++++++++++++++++++-
- src/vrend_decode.c | 6 +-
- src/vrend_renderer.c | 2 +-
- src/vrend_renderer.h | 3 +-
- 6 files changed, 360 insertions(+), 13 deletions(-)
-
-diff --git a/src/virgl_context.h b/src/virgl_context.h
-index ea86b31..871a148 100644
---- a/src/virgl_context.h
-+++ b/src/virgl_context.h
-@@ -51,6 +51,7 @@ struct virgl_context_blob {
- struct virgl_context;
-
- typedef void (*virgl_context_fence_retire)(struct virgl_context *ctx,
-+ uint32_t flags,
- uint64_t queue_id,
- void *fence_cookie);
-
-@@ -120,6 +121,11 @@ struct virgl_context {
- uint32_t flags,
- uint64_t queue_id,
- void *fence_cookie);
-+
-+ /* export the fence identified by fence_cookie as a sync fd */
-+ int (*export_fence)(struct virgl_context *ctx,
-+ void *fence_cookie,
-+ int *out_fd);
- };
-
- struct virgl_context_foreach_args {
-diff --git a/src/virglrenderer.c b/src/virglrenderer.c
-index f05eb30..3fd8411 100644
---- a/src/virglrenderer.c
-+++ b/src/virglrenderer.c
-@@ -33,6 +33,7 @@
- #include <unistd.h>
-
- #include "pipe/p_state.h"
-+#include "util/u_double_list.h"
- #include "util/u_format.h"
- #include "util/u_math.h"
- #include "vkr_renderer.h"
-@@ -46,6 +47,18 @@
- #include "virgl_resource.h"
- #include "virgl_util.h"
-
-+#define VIRGL_RENDERER_FENCE_FLAG_TIMELINE (1u << 31)
-+
-+struct timeline_point {
-+ uint32_t fence_id;
-+
-+ bool signaled;
-+ /* can be NULL if has signaled or is using ctx0 fencing */
-+ struct virgl_context *context;
-+
-+ struct list_head head;
-+};
-+
- struct global_state {
- bool client_initialized;
- void *cookie;
-@@ -57,6 +70,10 @@ struct global_state {
- bool winsys_initialized;
- bool vrend_initialized;
- bool vkr_initialized;
-+
-+ struct list_head timeline;
-+ uint32_t ctx0_retired_fence_id;
-+ struct list_head free_points;
- };
-
- static struct global_state state;
-@@ -175,10 +192,59 @@ void virgl_renderer_fill_caps(uint32_t set, uint32_t version,
- }
- }
-
-+static struct timeline_point *timeline_point_alloc(uint32_t fence_id,
-+ struct virgl_context *ctx)
-+{
-+ struct timeline_point *point;
-+ if (LIST_IS_EMPTY(&state.free_points)) {
-+ point = malloc(sizeof(*point));
-+ if (!point)
-+ return NULL;
-+ } else {
-+ point = LIST_ENTRY(struct timeline_point, state.free_points.next, head);
-+ list_del(&point->head);
-+ }
-+
-+ point->fence_id = fence_id;
-+ point->signaled = false;
-+ point->context = ctx;
-+
-+ return point;
-+}
-+
-+static void timeline_point_free(struct timeline_point *point)
-+{
-+ list_add(&point->head, &state.free_points);
-+}
-+
-+static bool timeline_point_match_context(const struct timeline_point *point,
-+ uint32_t ctx_id)
-+{
-+ return point->context && point->context->ctx_id == ctx_id;
-+}
-+
-+static void timeline_point_set_signaled(struct timeline_point *point)
-+{
-+ point->signaled = true;
-+ point->context = NULL;
-+}
-+
-+static bool timeline_point_is_signaled(const struct timeline_point *point)
-+{
-+ return point->signaled ||
-+ (!point->context && point->fence_id <= state.ctx0_retired_fence_id);
-+}
-+
- static void per_context_fence_retire(struct virgl_context *ctx,
-+ uint32_t flags,
- uint64_t queue_id,
- void *fence_cookie)
- {
-+ if (flags & VIRGL_RENDERER_FENCE_FLAG_TIMELINE) {
-+ timeline_point_set_signaled(fence_cookie);
-+ return;
-+ }
-+
- state.cbs->write_context_fence(state.cookie,
- ctx->ctx_id,
- queue_id,
-@@ -253,6 +319,13 @@ int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char *na
- void virgl_renderer_context_destroy(uint32_t handle)
- {
- TRACE_FUNC();
-+
-+ struct timeline_point *point;
-+ LIST_FOR_EACH_ENTRY(point, &state.timeline, head) {
-+ if (timeline_point_match_context(point, handle))
-+ timeline_point_set_signaled(point);
-+ }
-+
- virgl_context_remove(handle);
- }
-
-@@ -379,13 +452,45 @@ void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, in
- virgl_resource_detach_iov(res);
- }
-
--int virgl_renderer_create_fence(int client_fence_id, UNUSED uint32_t ctx_id)
-+int virgl_renderer_create_fence(int client_fence_id, uint32_t ctx_id)
- {
- TRACE_FUNC();
- const uint32_t fence_id = (uint32_t)client_fence_id;
-- if (state.vrend_initialized)
-- return vrend_renderer_create_ctx0_fence(fence_id);
-- return EINVAL;
-+
-+ struct virgl_context *ctx;
-+ struct timeline_point *point;
-+ int ret;
-+
-+ /* this only works with crosvm because qemu passes garbage for ctx_id */
-+ if (ctx_id) {
-+ ctx = virgl_context_lookup(ctx_id);
-+ if (!ctx)
-+ return -EINVAL;
-+ /* use per-context fencing only for venus */
-+ if (ctx->capset_id != VIRGL_RENDERER_CAPSET_VENUS)
-+ ctx = NULL;
-+ } else {
-+ ctx = NULL;
-+ }
-+
-+ point = timeline_point_alloc(fence_id, ctx);
-+ if (!point)
-+ return -ENOMEM;
-+
-+ if (ctx) {
-+ ret = ctx->submit_fence(ctx, VIRGL_RENDERER_FENCE_FLAG_TIMELINE, 0, point);
-+ } else {
-+ ret = state.vrend_initialized ?
-+ vrend_renderer_create_ctx0_fence(fence_id) : EINVAL;
-+ }
-+ if (ret) {
-+ timeline_point_free(point);
-+ return ret;
-+ }
-+
-+ list_addtail(&point->head, &state.timeline);
-+
-+ return 0;
- }
-
- int virgl_renderer_context_create_fence(uint32_t ctx_id,
-@@ -505,11 +610,14 @@ void virgl_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int nu
- }
-
-
--static void ctx0_fence_retire(void *fence_cookie,
-+static void ctx0_fence_retire(UNUSED uint32_t flags,
-+ void *fence_cookie,
- UNUSED void *retire_data)
- {
- const uint32_t fence_id = (uint32_t)(uintptr_t)fence_cookie;
-- state.cbs->write_fence(state.cookie, fence_id);
-+
-+ /* defer marking timeline_point signaled */
-+ state.ctx0_retired_fence_id = fence_id;
- }
-
- static virgl_renderer_gl_context create_gl_context(int scanout_idx, struct virgl_gl_ctx_param *param)
-@@ -563,11 +671,38 @@ void *virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t *width, uint
- height);
- }
-
-+static bool timeline_poll(struct virgl_context *ctx, UNUSED void *data)
-+{
-+ /* we use per-context fencing only for venus */
-+ if (ctx->capset_id == VIRGL_RENDERER_CAPSET_VENUS)
-+ ctx->retire_fences(ctx);
-+ return true;
-+}
-+
- void virgl_renderer_poll(void)
- {
- TRACE_FUNC();
- if (state.vrend_initialized)
- vrend_renderer_check_fences();
-+
-+ struct virgl_context_foreach_args args;
-+ args.callback = timeline_poll;
-+ args.data = NULL;
-+ virgl_context_foreach(&args);
-+
-+ uint32_t write_fence_id = 0;
-+ struct timeline_point *point, *tmp;
-+ LIST_FOR_EACH_ENTRY_SAFE(point, tmp, &state.timeline, head) {
-+ if (!timeline_point_is_signaled(point))
-+ break;
-+
-+ write_fence_id = point->fence_id;
-+ list_del(&point->head);
-+ timeline_point_free(point);
-+ }
-+
-+ if (write_fence_id)
-+ state.cbs->write_fence(state.cookie, write_fence_id);
- }
-
- void virgl_renderer_cleanup(UNUSED void *cookie)
-@@ -687,6 +822,9 @@ int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks
- state.vkr_initialized = true;
- }
-
-+ list_inithead(&state.timeline);
-+ list_inithead(&state.free_points);
-+
- return 0;
-
- fail:
-@@ -961,9 +1099,48 @@ virgl_renderer_resource_export_blob(uint32_t res_id, uint32_t *fd_type, int *fd)
- return 0;
- }
-
-+static int
-+export_signaled_fence(int *fd)
-+{
-+#ifdef HAVE_EPOXY_EGL_H
-+ if (virgl_egl_supports_fences(egl))
-+ return virgl_egl_export_signaled_fence(egl, fd);
-+#endif
-+ return -1;
-+}
-+
- int
- virgl_renderer_export_fence(uint32_t client_fence_id, int *fd)
- {
- TRACE_FUNC();
-- return vrend_renderer_export_ctx0_fence(client_fence_id, fd);
-+
-+ int ret;
-+ if (LIST_IS_EMPTY(&state.timeline)) {
-+ ret = 0;
-+ *fd = -1;
-+ } else {
-+ struct timeline_point *point;
-+
-+ ret = -EINVAL;
-+ LIST_FOR_EACH_ENTRY(point, &state.timeline, head) {
-+ if (point->fence_id != client_fence_id)
-+ continue;
-+
-+ if (timeline_point_is_signaled(point)) {
-+ ret = 0;
-+ *fd = -1;
-+ } else if (point->context) {
-+ ret = point->context->export_fence(point->context, point, fd);
-+ } else {
-+ ret = vrend_renderer_export_ctx0_fence(client_fence_id, fd);
-+ }
-+ break;
-+ }
-+ }
-+
-+ /* required by crosvm */
-+ if (!ret && *fd == -1)
-+ ret = export_signaled_fence(fd);
-+
-+ return ret;
- }
-diff --git a/src/vkr_renderer.c b/src/vkr_renderer.c
-index a7f4726..2831970 100644
---- a/src/vkr_renderer.c
-+++ b/src/vkr_renderer.c
-@@ -112,6 +112,8 @@ struct vkr_physical_device {
- bool EXT_external_memory_dma_buf;
-
- bool KHR_external_fence_fd;
-+
-+ struct vkr_device *queue_id_0_device;
- };
-
- struct vkr_queue_sync {
-@@ -335,6 +337,9 @@ struct vkr_context {
- int fence_eventfd;
- struct list_head busy_queues;
-
-+ struct vkr_queue *queue_id_0_queue;
-+ struct list_head cpu_syncs;
-+
- struct vkr_instance *instance;
- };
-
-@@ -923,6 +928,9 @@ vkr_instance_enumerate_physical_devices(struct vkr_instance *instance)
- if (result != VK_SUCCESS)
- return result;
-
-+ /* enumerate at most 1 physical device */
-+ count = 1;
-+
- VkPhysicalDevice *handles = calloc(count, sizeof(*handles));
- struct vkr_physical_device **physical_devs = calloc(count, sizeof(*physical_devs));
- if (!handles || !physical_devs) {
-@@ -932,6 +940,8 @@ vkr_instance_enumerate_physical_devices(struct vkr_instance *instance)
- }
-
- result = vkEnumeratePhysicalDevices(instance->base.handle.instance, &count, handles);
-+ if (result == VK_INCOMPLETE)
-+ result = VK_SUCCESS;
- if (result != VK_SUCCESS) {
- free(physical_devs);
- free(handles);
-@@ -1245,6 +1255,12 @@ vkr_dispatch_vkGetPhysicalDeviceQueueFamilyProperties(
- vkGetPhysicalDeviceQueueFamilyProperties(args->physicalDevice,
- args->pQueueFamilyPropertyCount,
- args->pQueueFamilyProperties);
-+
-+ if (*args->pQueueFamilyPropertyCount) {
-+ *args->pQueueFamilyPropertyCount = 1;
-+ if (args->pQueueFamilyProperties)
-+ args->pQueueFamilyProperties->queueCount = 1;
-+ }
- }
-
- static void
-@@ -1372,6 +1388,12 @@ vkr_dispatch_vkGetPhysicalDeviceQueueFamilyProperties2(
- vkGetPhysicalDeviceQueueFamilyProperties2(args->physicalDevice,
- args->pQueueFamilyPropertyCount,
- args->pQueueFamilyProperties);
-+
-+ if (*args->pQueueFamilyPropertyCount) {
-+ *args->pQueueFamilyPropertyCount = 1;
-+ if (args->pQueueFamilyProperties)
-+ args->pQueueFamilyProperties->queueFamilyProperties.queueCount = 1;
-+ }
- }
-
- static void
-@@ -1555,6 +1577,8 @@ vkr_queue_destroy(struct vkr_context *ctx, struct vkr_queue *queue)
-
- list_del(&queue->head);
- list_del(&queue->busy_head);
-+ if (ctx->queue_id_0_queue == queue)
-+ ctx->queue_id_0_queue = NULL;
-
- util_hash_table_remove_u64(ctx->object_table, queue->base.id);
- }
-@@ -1617,6 +1641,8 @@ vkr_queue_create(struct vkr_context *ctx,
-
- list_addtail(&queue->head, &dev->queues);
- list_inithead(&queue->busy_head);
-+ if (dev->physical_device->queue_id_0_device == dev)
-+ ctx->queue_id_0_queue = queue;
-
- util_hash_table_set_u64(ctx->object_table, queue->base.id, queue);
-
-@@ -1636,6 +1662,25 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch,
- return;
- }
-
-+ /* when external memory/fence/semaphore is enabled, the guest driver
-+ * expects queue id 0 to be the queue of this device
-+ */
-+ bool use_queue_id_0 = false;
-+ for (uint32_t i = 0; i < args->pCreateInfo->enabledExtensionCount; i++) {
-+ if (!strcmp(args->pCreateInfo->ppEnabledExtensionNames[i],
-+ VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME) ||
-+ !strcmp(args->pCreateInfo->ppEnabledExtensionNames[i],
-+ VK_KHR_EXTERNAL_FENCE_FD_EXTENSION_NAME) ||
-+ !strcmp(args->pCreateInfo->ppEnabledExtensionNames[i],
-+ VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME))
-+ use_queue_id_0 = true;
-+ }
-+
-+ if (use_queue_id_0 && physical_dev->queue_id_0_device) {
-+ args->ret = VK_ERROR_TOO_MANY_OBJECTS;
-+ return;
-+ }
-+
- /* append extensions for our own use */
- const char **exts = NULL;
- uint32_t ext_count = args->pCreateInfo->enabledExtensionCount;
-@@ -1777,6 +1822,9 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch,
- list_inithead(&dev->free_syncs);
-
- util_hash_table_set_u64(ctx->object_table, dev->base.id, dev);
-+
-+ if (use_queue_id_0)
-+ physical_dev->queue_id_0_device = dev;
- }
-
- static void
-@@ -1806,6 +1854,9 @@ vkr_dispatch_vkDestroyDevice(struct vn_dispatch_context *dispatch,
- vn_replace_vkDestroyDevice_args_handle(args);
- vkDestroyDevice(args->device, NULL);
-
-+ if (dev->physical_device->queue_id_0_device == dev)
-+ dev->physical_device->queue_id_0_device = NULL;
-+
- util_hash_table_remove_u64(ctx->object_table, dev->base.id);
- }
-
-@@ -3910,6 +3961,7 @@ vkr_dispatch_vkGetVenusExperimentalFeatureData100000MESA(
- {
- const VkVenusExperimentalFeatures100000MESA features = {
- .memoryResourceAllocationSize = VK_TRUE,
-+ .globalFencing = VK_TRUE,
- };
-
- vn_replace_vkGetVenusExperimentalFeatureData100000MESA_args_handle(args);
-@@ -4236,7 +4288,26 @@ vkr_context_submit_fence_locked(struct virgl_context *base,
- struct vkr_queue *queue;
- VkResult result;
-
-- queue = util_hash_table_get_u64(ctx->object_table, queue_id);
-+ if (queue_id) {
-+ queue = util_hash_table_get_u64(ctx->object_table, queue_id);
-+ } else if (ctx->queue_id_0_queue) {
-+ queue = ctx->queue_id_0_queue;
-+ } else {
-+ struct vkr_queue_sync *sync = malloc(sizeof(*sync));
-+ if (!sync)
-+ return -ENOMEM;
-+
-+ sync->fence = VK_NULL_HANDLE;
-+ sync->flags = flags;
-+ sync->fence_cookie = fence_cookie;
-+ list_addtail(&sync->head, &ctx->cpu_syncs);
-+
-+ if (ctx->fence_eventfd >= 0)
-+ write_eventfd(ctx->fence_eventfd, 1);
-+
-+ return 0;
-+ }
-+
- if (!queue)
- return -EINVAL;
- struct vkr_device *dev = queue->device;
-@@ -4305,6 +4376,82 @@ vkr_context_submit_fence(struct virgl_context *base,
- return ret;
- }
-
-+static struct vkr_queue_sync *
-+find_sync(const struct list_head *syncs, void *fence_cookie)
-+{
-+ struct vkr_queue_sync *sync;
-+ LIST_FOR_EACH_ENTRY (sync, syncs, head) {
-+ if (sync->fence_cookie == fence_cookie)
-+ return sync;
-+ }
-+ return NULL;
-+}
-+
-+static int
-+vkr_context_export_fence_locked(struct virgl_context *base,
-+ void *fence_cookie,
-+ int *out_fd)
-+{
-+ struct vkr_context *ctx = (struct vkr_context *)base;
-+
-+ struct vkr_queue_sync *sync = NULL;
-+ bool sync_pending = false;
-+ if (ctx->queue_id_0_queue) {
-+ struct vkr_queue *queue = ctx->queue_id_0_queue;
-+
-+ if (queue->has_thread) {
-+ mtx_lock(&queue->mutex);
-+ sync = find_sync(&queue->signaled_syncs, fence_cookie);
-+ }
-+
-+ if (!sync) {
-+ sync = find_sync(&queue->pending_syncs, fence_cookie);
-+ if (sync)
-+ sync_pending = true;
-+ }
-+
-+ if (queue->has_thread)
-+ mtx_unlock(&queue->mutex);
-+ }
-+
-+ if (!sync)
-+ sync = find_sync(&ctx->cpu_syncs, fence_cookie);
-+
-+ if (!sync)
-+ return -EINVAL;
-+
-+ if (!sync_pending) {
-+ *out_fd = -1;
-+ return 0;
-+ }
-+
-+ struct vkr_device *dev = ctx->queue_id_0_queue->device;
-+ if (!dev->physical_device->KHR_external_fence_fd)
-+ return -1;
-+
-+ const VkFenceGetFdInfoKHR get_fd_info = {
-+ .sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR,
-+ .fence = sync->fence,
-+ .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT,
-+ };
-+ VkResult result =
-+ ctx->instance->get_fence_fd(dev->base.handle.device, &get_fd_info, out_fd);
-+
-+ return result == VK_SUCCESS ? 0 : -1;
-+}
-+
-+static int
-+vkr_context_export_fence(struct virgl_context *base, void *fence_cookie, int *out_fd)
-+{
-+ struct vkr_context *ctx = (struct vkr_context *)base;
-+ int ret;
-+
-+ mtx_lock(&ctx->mutex);
-+ ret = vkr_context_export_fence_locked(base, fence_cookie, out_fd);
-+ mtx_unlock(&ctx->mutex);
-+ return ret;
-+}
-+
- static void
- vkr_context_retire_fences_locked(UNUSED struct virgl_context *base)
- {
-@@ -4312,6 +4459,12 @@ vkr_context_retire_fences_locked(UNUSED struct virgl_context *base)
- struct vkr_queue_sync *sync, *sync_tmp;
- struct vkr_queue *queue, *queue_tmp;
-
-+ LIST_FOR_EACH_ENTRY_SAFE (sync, sync_tmp, &ctx->cpu_syncs, head) {
-+ ctx->base.fence_retire(&ctx->base, sync->flags, 0, sync->fence_cookie);
-+ list_del(&sync->head);
-+ free(sync);
-+ }
-+
- /* flush first and once because the per-queue sync threads might write to
- * it any time
- */
-@@ -4326,7 +4479,8 @@ vkr_context_retire_fences_locked(UNUSED struct virgl_context *base)
- vkr_queue_retire_syncs(queue, &retired_syncs, &queue_empty);
-
- LIST_FOR_EACH_ENTRY_SAFE (sync, sync_tmp, &retired_syncs, head) {
-- ctx->base.fence_retire(&ctx->base, queue->base.id, sync->fence_cookie);
-+ ctx->base.fence_retire(&ctx->base, sync->flags, queue->base.id,
-+ sync->fence_cookie);
- list_addtail(&sync->head, &dev->free_syncs);
- }
-
-@@ -4659,6 +4813,10 @@ vkr_context_destroy(struct virgl_context *base)
- util_hash_table_destroy(ctx->resource_table);
- util_hash_table_destroy_u64(ctx->object_table);
-
-+ struct vkr_queue_sync *sync, *tmp;
-+ LIST_FOR_EACH_ENTRY_SAFE (sync, tmp, &ctx->cpu_syncs, head)
-+ free(sync);
-+
- if (ctx->fence_eventfd >= 0)
- close(ctx->fence_eventfd);
-
-@@ -4683,6 +4841,7 @@ vkr_context_init_base(struct vkr_context *ctx)
- ctx->base.get_fencing_fd = vkr_context_get_fencing_fd;
- ctx->base.retire_fences = vkr_context_retire_fences;
- ctx->base.submit_fence = vkr_context_submit_fence;
-+ ctx->base.export_fence = vkr_context_export_fence;
- }
-
- static void
-@@ -4759,6 +4918,8 @@ vkr_context_create(size_t debug_len, const char *debug_name)
-
- list_inithead(&ctx->busy_queues);
-
-+ list_inithead(&ctx->cpu_syncs);
-+
- return &ctx->base;
-
- fail:
-diff --git a/src/vrend_decode.c b/src/vrend_decode.c
-index 35ccc23..177fd0a 100644
---- a/src/vrend_decode.c
-+++ b/src/vrend_decode.c
-@@ -1478,11 +1478,12 @@ static int vrend_decode_pipe_resource_set_type(struct vrend_context *ctx, const
- static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
- uint32_t ctx_id);
-
--static void vrend_decode_ctx_fence_retire(void *fence_cookie,
-+static void vrend_decode_ctx_fence_retire(uint32_t flags,
-+ void *fence_cookie,
- void *retire_data)
- {
- struct vrend_decode_ctx *dctx = retire_data;
-- dctx->base.fence_retire(&dctx->base, 0, fence_cookie);
-+ dctx->base.fence_retire(&dctx->base, flags, 0, fence_cookie);
- }
-
- struct virgl_context *vrend_renderer_context_create(uint32_t handle,
-@@ -1758,4 +1759,5 @@ static void vrend_decode_ctx_init_base(struct vrend_decode_ctx *dctx,
- ctx->get_fencing_fd = vrend_decode_ctx_get_fencing_fd;
- ctx->retire_fences = vrend_decode_ctx_retire_fences;
- ctx->submit_fence = vrend_decode_ctx_submit_fence;
-+ ctx->export_fence = NULL;
- }
-diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
-index 1c115ce..6807d5a 100644
---- a/src/vrend_renderer.c
-+++ b/src/vrend_renderer.c
-@@ -9401,7 +9401,7 @@ void vrend_renderer_check_fences(void)
-
- LIST_FOR_EACH_ENTRY_SAFE(fence, stor, &retired_fences, fences) {
- struct vrend_context *ctx = fence->ctx;
-- ctx->fence_retire(fence->fence_cookie, ctx->fence_retire_data);
-+ ctx->fence_retire(fence->flags, fence->fence_cookie, ctx->fence_retire_data);
-
- free_fence_locked(fence);
- }
-diff --git a/src/vrend_renderer.h b/src/vrend_renderer.h
-index b132384..37982ff 100644
---- a/src/vrend_renderer.h
-+++ b/src/vrend_renderer.h
-@@ -111,7 +111,8 @@ struct vrend_format_table {
- uint32_t flags;
- };
-
--typedef void (*vrend_context_fence_retire)(void *fence_cookie,
-+typedef void (*vrend_context_fence_retire)(uint32_t flags,
-+ void *fence_cookie,
- void *retire_data);
-
- struct vrend_if_cbs {
---
-2.31.0
-
diff --git a/media-libs/virglrenderer/virglrenderer-9999.ebuild b/media-libs/virglrenderer/virglrenderer-9999.ebuild
index 7d0dae6..15143bc 100644
--- a/media-libs/virglrenderer/virglrenderer-9999.ebuild
+++ b/media-libs/virglrenderer/virglrenderer-9999.ebuild
@@ -37,10 +37,6 @@
vulkan? ( dev-util/vulkan-headers )
"
-PATCHES=(
- "${FILESDIR}"/0001-vkr-add-support-for-globalFencing.patch
-)
-
src_prepare() {
default
}