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;
 }

Reply via email to