Mesa (main): zink: implement win32 memory handle import

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun May 15 20:23:01 UTC 2022


Module: Mesa
Branch: main
Commit: 34e62bfa803ff4aa6a4f849c470957cdd932a9f8
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=34e62bfa803ff4aa6a4f849c470957cdd932a9f8

Author: Sidney Just <justsid at x-plane.com>
Date:   Sun May 15 11:06:23 2022 -0700

zink: implement win32 memory handle import

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15504>

---

 src/gallium/drivers/zink/zink_fence.h    |  2 +-
 src/gallium/drivers/zink/zink_resource.c | 79 +++++++++++++++++++++++++++++---
 src/gallium/drivers/zink/zink_screen.c   |  2 +-
 3 files changed, 75 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_fence.h b/src/gallium/drivers/zink/zink_fence.h
index f0693062f12..18567346826 100644
--- a/src/gallium/drivers/zink/zink_fence.h
+++ b/src/gallium/drivers/zink/zink_fence.h
@@ -80,7 +80,7 @@ zink_fence_reference(struct zink_screen *screen,
 
 void
 zink_create_fence_fd(struct pipe_context *pctx, struct pipe_fence_handle **pfence, int fd, enum pipe_fd_type type);
-#ifdef _WIN32
+#if defined(_WIN32)
 void
 zink_create_fence_win32(struct pipe_screen *screen, struct pipe_fence_handle **pfence, void *handle, enum pipe_fd_type type);
 #endif
diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c
index 92ccfa4c9a0..686f8c80b0a 100644
--- a/src/gallium/drivers/zink/zink_resource.c
+++ b/src/gallium/drivers/zink/zink_resource.c
@@ -47,11 +47,11 @@
 #include "util/os_file.h"
 #include "frontend/winsys_handle.h"
 
-#if !defined(_WIN32) && !defined(__APPLE__)
+#if !defined(__APPLE__)
 #define ZINK_USE_DMABUF
 #endif
 
-#ifdef ZINK_USE_DMABUF
+#if defined(ZINK_USE_DMABUF) && !defined(_WIN32)
 #include "drm-uapi/drm_fourcc.h"
 #else
 /* these won't actually be used */
@@ -489,7 +489,11 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
    VkMemoryPropertyFlags flags;
    bool need_dedicated = false;
    bool shared = templ->bind & PIPE_BIND_SHARED;
+#if !defined(_WIN32)
    VkExternalMemoryHandleTypeFlags export_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+#else
+   VkExternalMemoryHandleTypeFlags export_types = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+#endif
    unsigned num_planes = util_format_get_num_planes(templ->format);
    VkImageAspectFlags plane_aspects[] = {
       VK_IMAGE_ASPECT_PLANE_0_BIT,
@@ -506,7 +510,11 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
    }
    if (needs_export) {
       if (whandle && whandle->type == ZINK_EXTERNAL_MEMORY_HANDLE) {
+#if !defined(_WIN32)
          external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+#else
+         external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+#endif
       } else {
          external = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
          export_types |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
@@ -809,6 +817,8 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
    }
 
 #ifdef ZINK_USE_DMABUF
+
+#if !defined(_WIN32)
    VkImportMemoryFdInfoKHR imfi = {
       VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
       NULL,
@@ -826,6 +836,32 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
       imfi.pNext = mai.pNext;
       mai.pNext = &imfi;
    }
+#else
+   VkImportMemoryWin32HandleInfoKHR imfi = {
+      VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
+      NULL,
+   };
+
+   if (whandle) {
+      HANDLE source_target = GetCurrentProcess();
+      HANDLE out_handle;
+
+      bool result = DuplicateHandle(source_target, whandle->handle, source_target, &out_handle, 0, false, DUPLICATE_SAME_ACCESS);
+
+      if (!result || !out_handle) {
+         mesa_loge("ZINK: failed to DuplicateHandle with winerr: %08x\n", (int)GetLastError());
+         goto fail1;
+      }
+
+      imfi.pNext = NULL;
+      imfi.handleType = external;
+      imfi.handle = out_handle;
+
+      imfi.pNext = mai.pNext;
+      mai.pNext = &imfi;
+   }
+#endif
+
 #endif
 
    unsigned alignment = MAX2(reqs.alignment, 256);
@@ -1188,7 +1224,7 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx,
       if (!pscreen->resource_get_handle(pscreen, pctx, pres, &whandle, handle_usage))
          return false;
 
-      *value = whandle.handle;
+      *value = (uint64_t)whandle.handle;
       break;
 #else
       (void)whandle;
@@ -1212,6 +1248,7 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
       struct zink_screen *screen = zink_screen(pscreen);
       struct zink_resource_object *obj = res->obj;
 
+#if !defined(_WIN32)
       if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
          whandle->handle = -1;
       } else {
@@ -1239,6 +1276,18 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
          }
          whandle->handle = fd;
       }
+#else
+      VkMemoryGetWin32HandleInfoKHR handle_info = {0};
+      HANDLE handle;
+      handle_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
+      //TODO: remove for wsi
+      handle_info.memory = zink_bo_get_mem(obj->bo);
+      handle_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+      VkResult result = VKSCR(GetMemoryWin32HandleKHR)(screen->dev, &handle_info, &handle);
+      if (result != VK_SUCCESS)
+         return false;
+      whandle->handle = handle;
+#endif
       uint64_t value;
       zink_resource_get_param(pscreen, context, tex, 0, 0, 0, PIPE_RESOURCE_PARAM_MODIFIER, 0, &value);
       whandle->modifier = value;
@@ -1296,9 +1345,21 @@ zink_memobj_create_from_handle(struct pipe_screen *pscreen, struct winsys_handle
       return NULL;
    memcpy(&memobj->whandle, whandle, sizeof(struct winsys_handle));
    memobj->whandle.type = ZINK_EXTERNAL_MEMORY_HANDLE;
+
 #ifdef ZINK_USE_DMABUF
+
+#if !defined(_WIN32)
    memobj->whandle.handle = os_dupfd_cloexec(whandle->handle);
-#endif
+#else
+   HANDLE source_target = GetCurrentProcess();
+   HANDLE out_handle;
+
+   DuplicateHandle(source_target, whandle->handle, source_target, &out_handle, 0, false, DUPLICATE_SAME_ACCESS);
+   memobj->whandle.handle = out_handle;
+
+#endif /* _WIN32 */
+#endif /* ZINK_USE_DMABUF */
+
    return (struct pipe_memory_object *)memobj;
 }
 
@@ -1307,8 +1368,14 @@ zink_memobj_destroy(struct pipe_screen *pscreen, struct pipe_memory_object *pmem
 {
 #ifdef ZINK_USE_DMABUF
    struct zink_memory_object *memobj = (struct zink_memory_object *)pmemobj;
+
+#if !defined(_WIN32)
    close(memobj->whandle.handle);
-#endif
+#else
+   CloseHandle(memobj->whandle.handle);
+#endif /* _WIN32 */
+#endif /* ZINK_USE_DMABUF */
+   
    FREE(pmemobj);
 }
 
@@ -2006,7 +2073,7 @@ zink_screen_resource_init(struct pipe_screen *pscreen)
    pscreen->resource_destroy = zink_resource_destroy;
    pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, true, false, false, !screen->have_D24_UNORM_S8_UINT);
 
-   if (screen->info.have_KHR_external_memory_fd) {
+   if (screen->info.have_KHR_external_memory_fd || screen->info.have_KHR_external_memory_win32) {
       pscreen->resource_get_handle = zink_resource_get_handle;
       pscreen->resource_from_handle = zink_resource_from_handle;
    }
diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c
index fd8e9fc747a..58aae80005f 100644
--- a/src/gallium/drivers/zink/zink_screen.c
+++ b/src/gallium/drivers/zink/zink_screen.c
@@ -2183,7 +2183,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
       screen->base.is_dmabuf_modifier_supported = zink_is_dmabuf_modifier_supported;
       screen->base.get_dmabuf_modifier_planes = zink_get_dmabuf_modifier_planes;
    }
-#ifdef _WIN32
+#if defined(_WIN32)
    if (screen->info.have_KHR_external_memory_win32)
       screen->base.create_fence_win32 = zink_create_fence_win32;
 #endif



More information about the mesa-commit mailing list