Module: Mesa Branch: main Commit: 9fdfe4324069b296fe6197070fd1802e788c25e2 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=9fdfe4324069b296fe6197070fd1802e788c25e2
Author: Yiwei Zhang <[email protected]> Date: Thu Sep 8 03:17:22 2022 +0000 zink: implement fence_get_fd required by EGL android platform fence_get_fd is required for any kind of surface flush or native fence sync export on Android. The typical scenarios are: - eglDupNativeFenceFDANDROID - eglSwapBuffers* - eglMakeCurrent - glFlush/glFinish for front buffer rendering This change updates zink_flush to handle PIPE_FLUSH_FENCE_FD via a forced submit to signal an external sync_fd semaphore. fence_get_fd is implemented to export the sync file from that semaphore. Signed-off-by: Yiwei Zhang <[email protected]> Reviewed-By: Mike Blumenkrantz <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18453> --- src/gallium/drivers/zink/zink_context.c | 25 +++++++++++++++++++++++++ src/gallium/drivers/zink/zink_fence.c | 27 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index e6087346452..df277b91acb 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -3425,6 +3425,7 @@ zink_flush(struct pipe_context *pctx, struct zink_fence *fence = NULL; struct zink_screen *screen = zink_screen(ctx->base.screen); unsigned submit_count = 0; + VkSemaphore export_sem = VK_NULL_HANDLE; /* triggering clears will force has_work */ if (!deferred && ctx->clears_enabled) @@ -3437,6 +3438,29 @@ zink_flush(struct pipe_context *pctx, ctx->needs_present = NULL; } + if (flags & PIPE_FLUSH_FENCE_FD) { + assert(!deferred && pfence); + const VkExportSemaphoreCreateInfo esci = { + .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, + .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + }; + const VkSemaphoreCreateInfo sci = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &esci, + }; + VkResult result = VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &export_sem); + if (zink_screen_handle_vkresult(screen, result)) { + assert(!batch->state->signal_semaphore); + batch->state->signal_semaphore = export_sem; + batch->has_work = true; + } else { + mesa_loge("ZINK: vkCreateSemaphore failed (%s)", vk_Result_to_str(result)); + + /* let flush proceed and ensure a null sem for fence_get_fd to return -1 */ + export_sem = VK_NULL_HANDLE; + } + } + if (!batch->has_work) { if (pfence) { /* reuse last fence */ @@ -3474,6 +3498,7 @@ zink_flush(struct pipe_context *pctx, } mfence->fence = fence; + mfence->sem = export_sem; if (fence) mfence->submit_count = submit_count; diff --git a/src/gallium/drivers/zink/zink_fence.c b/src/gallium/drivers/zink/zink_fence.c index 28dfded9136..a669750e282 100644 --- a/src/gallium/drivers/zink/zink_fence.c +++ b/src/gallium/drivers/zink/zink_fence.c @@ -192,6 +192,32 @@ fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx, timeout_ns); } +static int +fence_get_fd(struct pipe_screen *pscreen, struct pipe_fence_handle *pfence) +{ + struct zink_screen *screen = zink_screen(pscreen); + if (screen->device_lost) + return -1; + + struct zink_tc_fence *mfence = (struct zink_tc_fence *)pfence; + if (!mfence->sem) + return -1; + + const VkSemaphoreGetFdInfoKHR sgfi = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, + .semaphore = mfence->sem, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + }; + int fd = -1; + VkResult result = VKSCR(GetSemaphoreFdKHR)(screen->dev, &sgfi, &fd); + if (!zink_screen_handle_vkresult(screen, result)) { + mesa_loge("ZINK: vkGetSemaphoreFdKHR failed (%s)", vk_Result_to_str(result)); + return -1; + } + + return fd; +} + void zink_fence_server_signal(struct pipe_context *pctx, struct pipe_fence_handle *pfence) { @@ -333,4 +359,5 @@ zink_screen_fence_init(struct pipe_screen *pscreen) { pscreen->fence_reference = fence_reference; pscreen->fence_finish = fence_finish; + pscreen->fence_get_fd = fence_get_fd; }
