[PATCH 4/4] server, ntdll: Allow storage of API data inside of GPU Resource objects.

Derek Lesho dlesho at codeweavers.com
Wed Oct 30 11:46:50 CDT 2019


This is necessary when Graphics API Layers are emulating APIs that
support sharing resources with more details than just the underlying
memory.

Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
 dlls/ntdll/gpu_resource.c | 30 +++++++++++++++++++++---
 dlls/ntdll/ntdll.spec     |  3 ++-
 dlls/winevulkan/vulkan.c  |  4 ++--
 server/gpu_resource.c     | 49 +++++++++++++++++++++++++++++++++++----
 server/protocol.def       |  9 ++++++-
 5 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/gpu_resource.c b/dlls/ntdll/gpu_resource.c
index 63488016b1..00d07cd4fd 100644
--- a/dlls/ntdll/gpu_resource.c
+++ b/dlls/ntdll/gpu_resource.c
@@ -87,16 +87,40 @@ NTSTATUS CDECL __wine_get_gpu_resource_fd(HANDLE handle, int *fd, int *needs_clo
     return ret;
 }
 
-/* gets KMT handle */
-NTSTATUS CDECL __wine_get_gpu_resource_info(HANDLE handle, HANDLE *kmt_handle)
+/* gets KMT handle and userdata */
+NTSTATUS CDECL __wine_get_gpu_resource_info(HANDLE handle, HANDLE *kmt_handle, void *user_data_buf, unsigned int *user_data_len)
 {
     NTSTATUS ret;
+    BOOL get_user_data = user_data_buf && user_data_len;
 
     SERVER_START_REQ(query_gpu_resource)
     {
         req->handle = wine_server_obj_handle( handle );
+        if (get_user_data)
+            wine_server_set_reply(req, user_data_buf, *user_data_len);
         if (!(ret = wine_server_call(req)))
-            *kmt_handle = wine_server_ptr_handle( reply->kmt_handle );
+        {
+            if (kmt_handle)
+                *kmt_handle = wine_server_ptr_handle( reply->kmt_handle );
+            if (user_data_len)
+                *user_data_len = wine_server_reply_size(reply);
+        }
+    }
+    SERVER_END_REQ;
+
+    return ret;
+}
+
+/* Updates the userdata of the GPU resource */
+NTSTATUS CDECL __wine_set_gpu_resource_userdata(HANDLE handle, void *user_data, unsigned int user_data_len)
+{
+    NTSTATUS ret;
+
+    SERVER_START_REQ(set_userdata_gpu_resource)
+    {
+        req->handle = wine_server_obj_handle(handle);
+        wine_server_add_data(req, user_data, user_data_len);
+        ret = wine_server_call( req );
     }
     SERVER_END_REQ;
 
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 4cc03469f9..e80b28f14f 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -1574,4 +1574,5 @@
 @ cdecl __wine_create_gpu_resource(ptr ptr long ptr long)
 @ cdecl __wine_open_gpu_resource(ptr ptr long ptr)
 @ cdecl __wine_get_gpu_resource_fd(ptr ptr ptr)
-@ cdecl __wine_get_gpu_resource_info(ptr ptr)
\ No newline at end of file
+@ cdecl __wine_get_gpu_resource_info(ptr ptr ptr ptr)
+@ cdecl __wine_set_gpu_resource_userdata(ptr ptr long)
\ No newline at end of file
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 01cab11e21..36da6e2326 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -1169,7 +1169,7 @@ void WINAPI wine_vkDestroyCommandPool(VkDevice device, VkCommandPool handle,
 extern NTSTATUS CDECL __wine_create_gpu_resource(PHANDLE handle, PHANDLE kmt_handle, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, int fd );
 extern NTSTATUS CDECL __wine_open_gpu_resource(HANDLE kmt_handle, OBJECT_ATTRIBUTES *attr, DWORD access, PHANDLE handle );
 extern NTSTATUS CDECL __wine_get_gpu_resource_fd(HANDLE handle, int *fd, int *needs_close);
-extern NTSTATUS CDECL __wine_get_gpu_resource_info(HANDLE handle, HANDLE *kmt_handle);
+extern NTSTATUS CDECL __wine_get_gpu_resource_info(HANDLE handle, HANDLE *kmt_handle, void *user_data_buf, unsigned int *user_data_len);
 
 static NTSTATUS server_create_dxgi_resource( PHANDLE handle, PHANDLE kmt_handle, int fd, DWORD access, SECURITY_ATTRIBUTES *sa, LPCWSTR name )
 {
@@ -1318,7 +1318,7 @@ VkResult WINAPI wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInf
             {
                 /* occurs if the caller imports *and* exports the memory */
                 if (handle_types & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT && object->kmt_handle == INVALID_HANDLE_VALUE)
-                    __wine_get_gpu_resource_info(object->handle, &object->kmt_handle);
+                    __wine_get_gpu_resource_info(object->handle, &object->kmt_handle, NULL, NULL);
             } else {
                 int fd;
                 VkMemoryGetFdInfoKHR host_fd_info;
diff --git a/server/gpu_resource.c b/server/gpu_resource.c
index bc083a2f42..e9fd493ab5 100644
--- a/server/gpu_resource.c
+++ b/server/gpu_resource.c
@@ -22,6 +22,10 @@ struct gpu_resource
     struct list         kernel_object;
     struct fd          *fd;
     obj_handle_t        kmt_handle; /* more like an ID */
+
+    /* used by API layers to store extra information about a resource */
+    void               *user_data;
+    data_size_t         user_data_len;
 };
 
 /* gpu_resource functions */
@@ -216,6 +220,7 @@ struct gpu_resource *create_gpu_resource(struct object *root, const struct unico
                 return NULL;
             }
             resource->kmt_handle = alloc_kmt_handle( resource );
+            resource->user_data = 0;
             allow_fd_caching( resource->fd );
         }
     }
@@ -287,12 +292,48 @@ struct gpu_resource *get_resource_obj( struct process *process, obj_handle_t han
     return (struct gpu_resource *)get_handle_obj( process, handle, access, &gpu_resource_ops );
 }
 
-/* Query KMT handle of GPU Resource */
+/* Query KMT handle and user data of GPU Resource */
 DECL_HANDLER(query_gpu_resource)
 {
     struct gpu_resource *resource;
+    data_size_t reply_size = get_reply_max_size();
+
+    if ((resource = get_resource_obj( current->process, req->handle, 0 )))
+    {
+        reply->kmt_handle = resource->kmt_handle;
+
+        if (reply_size)
+        {
+            if (reply_size >= resource->user_data_len)
+                set_reply_data(resource->user_data, resource->user_data_len);
+            else
+                set_error(STATUS_BUFFER_TOO_SMALL);
+        }
 
-    if (!(resource = get_resource_obj( current->process, req->handle, 0 ))) return;
-    reply->kmt_handle = resource->kmt_handle;
-    release_object(resource);
+        release_object(resource);
+    }
 }
+
+/* Sets the user data of the GPU resource */
+DECL_HANDLER(set_userdata_gpu_resource)
+{
+    struct gpu_resource *resource;
+    data_size_t len = get_req_data_size();
+
+    if ((resource = get_resource_obj( current->process, req->handle, 0 )))
+    {
+        free(resource->user_data);
+        resource->user_data = mem_alloc(len);
+        if (resource->user_data)
+        {
+            memcpy(resource->user_data, get_req_data(), len);
+            resource->user_data_len = len;
+        }
+        else
+        {
+            set_error(STATUS_NO_MEMORY);
+        }
+        
+        release_object(resource);
+    }
+}
\ No newline at end of file
diff --git a/server/protocol.def b/server/protocol.def
index a4bc550544..33d0287b37 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -3960,11 +3960,18 @@ struct handle_info
 @END
 
 
-/* Query KMT Handle of GPU Resource */
+/* Query KMT Handle and user data of GPU Resource */
 @REQ(query_gpu_resource)
     obj_handle_t handle;
 @REPLY
     obj_handle_t kmt_handle;
+    VARARG(userdata,bytes);
+ at END
+
+/* Sets the userdata of the GPU resource */
+ at REQ(set_userdata_gpu_resource)
+    obj_handle_t handle;
+    VARARG(userdata,bytes);
 @END
 
 
-- 
2.23.0




More information about the wine-devel mailing list