From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 85474a00ec1..d916735c2ab 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1894,7 +1894,7 @@ NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local ) TRACE( "local %#x\n", local );
if (!(resource = get_d3dkmt_object( local, D3DKMT_RESOURCE ))) return STATUS_INVALID_PARAMETER; - if ((allocation = get_d3dkmt_object( resource->allocation, D3DKMT_RESOURCE ))) d3dkmt_object_free( allocation ); + if ((allocation = get_d3dkmt_object( resource->allocation, D3DKMT_ALLOCATION ))) d3dkmt_object_free( allocation ); d3dkmt_object_free( &resource->obj );
return STATUS_SUCCESS;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index d916735c2ab..78f6d56874d 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1803,15 +1803,9 @@ failed: */ NTSTATUS WINAPI NtGdiDdDDIDestroySynchronizationObject( const D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *params ) { - struct d3dkmt_object *sync; - TRACE( "params %p\n", params );
- if (!(sync = get_d3dkmt_object( params->hSyncObject, D3DKMT_SYNC ))) - return STATUS_INVALID_PARAMETER; - d3dkmt_object_free( sync ); - - return STATUS_SUCCESS; + return d3dkmt_destroy_sync( params->hSyncObject ); }
/* get a locally opened D3DKMT object host-specific fd */
From: Rémi Bernon rbernon@codeweavers.com
The calls will fail to find the objects if the handle is invalid, but it doesn't matter. --- dlls/win32u/vulkan.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-)
diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index 017b84df8c3..c6f90a7fbec 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -279,8 +279,8 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA VkImportMemoryHostPointerInfoEXT host_pointer_info, *pointer_info = NULL; VkExportMemoryWin32HandleInfoKHR export_win32 = {.dwAccess = GENERIC_ALL}; VkImportMemoryWin32HandleInfoKHR *import_win32 = NULL; + VkDeviceMemory host_device_memory = VK_NULL_HANDLE; VkExportMemoryAllocateInfo *export_info = NULL; - VkDeviceMemory host_device_memory; struct device_memory *memory; BOOL nt_shared = FALSE; uint32_t mem_flags; @@ -358,8 +358,8 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA
if ((fd_info.fd = d3dkmt_object_get_fd( memory->local )) < 0) { - free( memory ); - return VK_ERROR_INVALID_EXTERNAL_HANDLE; + res = VK_ERROR_INVALID_EXTERNAL_HANDLE; + goto failed; }
fd_info.handleType = get_host_external_memory_type(); @@ -367,12 +367,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA alloc_info->pNext = &fd_info; }
- if ((res = device->p_vkAllocateMemory( device->host.device, alloc_info, NULL, &host_device_memory ))) - { - if (memory->local) d3dkmt_destroy_resource( memory->local ); - free( memory ); - return res; - } + if ((res = device->p_vkAllocateMemory( device->host.device, alloc_info, NULL, &host_device_memory ))) goto failed;
if (export_info) { @@ -410,8 +405,8 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA
failed: WARN( "Failed to allocate memory, res %d\n", res ); - device->p_vkFreeMemory( device->host.device, host_device_memory, NULL ); - if (memory->local) d3dkmt_destroy_resource( memory->local ); + if (host_device_memory) device->p_vkFreeMemory( device->host.device, host_device_memory, NULL ); + d3dkmt_destroy_resource( memory->local ); free( memory ); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -447,7 +442,7 @@ static void win32u_vkFreeMemory( VkDevice client_device, VkDeviceMemory client_m }
if (memory->shared) NtClose( memory->shared ); - if (memory->local) d3dkmt_destroy_resource( memory->local ); + d3dkmt_destroy_resource( memory->local ); free( memory ); }
@@ -1567,7 +1562,7 @@ static VkResult win32u_vkCreateSemaphore( VkDevice client_device, const VkSemaph failed: WARN( "Failed to create semaphore, res %d\n", res ); device->p_vkDestroySemaphore( device->host.device, host_semaphore, NULL ); - if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + d3dkmt_destroy_sync( semaphore->local ); free( semaphore ); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -1586,7 +1581,7 @@ static void win32u_vkDestroySemaphore( VkDevice client_device, VkSemaphore clien instance->p_remove_object( instance, &semaphore->obj.obj );
if (semaphore->shared) NtClose( semaphore->shared ); - if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + d3dkmt_destroy_sync( semaphore->local ); free( semaphore ); }
@@ -1670,7 +1665,7 @@ static VkResult win32u_vkImportSemaphoreWin32HandleKHR( VkDevice client_device, else { if (semaphore->shared) NtClose( semaphore->shared ); - if (semaphore->local) d3dkmt_destroy_sync( semaphore->local ); + d3dkmt_destroy_sync( semaphore->local ); semaphore->shared = shared; semaphore->global = global; semaphore->local = local; @@ -1775,7 +1770,7 @@ static VkResult win32u_vkCreateFence( VkDevice client_device, const VkFenceCreat failed: WARN( "Failed to create fence, res %d\n", res ); device->p_vkDestroyFence( device->host.device, host_fence, NULL ); - if (fence->local) d3dkmt_destroy_sync( fence->local ); + d3dkmt_destroy_sync( fence->local ); free( fence ); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -1794,7 +1789,7 @@ static void win32u_vkDestroyFence( VkDevice client_device, VkFence client_fence, instance->p_remove_object( instance, &fence->obj.obj );
if (fence->shared) NtClose( fence->shared ); - if (fence->local) d3dkmt_destroy_sync( fence->local ); + d3dkmt_destroy_sync( fence->local ); free( fence ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 121 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index 78f6d56874d..ea98968029f 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -31,8 +31,117 @@ #include "win32u_private.h" #include "ntuser_private.h"
+#include <d3d9types.h> +#include <dxgi.h> +#include <d3d10.h> +#include <d3d11.h> +#include <d3d12.h> + WINE_DEFAULT_DEBUG_CHANNEL(d3dkmt);
+/* D3DKMT runtime descriptors */ + +struct d3dkmt_dxgi_desc +{ + UINT size; + UINT version; + UINT width; + UINT height; + DXGI_FORMAT format; + UINT unknown_0; + UINT unknown_1; + UINT keyed_mutex; + D3DKMT_HANDLE mutex_handle; + D3DKMT_HANDLE sync_handle; + UINT nt_shared; + UINT unknown_2; + UINT unknown_3; + UINT unknown_4; +}; + +struct d3dkmt_d3d9_desc +{ + struct d3dkmt_dxgi_desc dxgi; + D3DFORMAT format; + D3DRESOURCETYPE type; + UINT usage; + union + { + struct + { + UINT unknown_0; + UINT width; + UINT height; + UINT levels; + UINT depth; + } texture; + struct + { + UINT unknown_0; + UINT unknown_1; + UINT unknown_2; + UINT width; + UINT height; + } surface; + struct + { + UINT unknown_0; + UINT width; + UINT format; + UINT unknown_1; + UINT unknown_2; + } buffer; + }; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d9_desc) == 0x58 ); + +struct d3dkmt_d3d11_desc +{ + struct d3dkmt_dxgi_desc dxgi; + D3D11_RESOURCE_DIMENSION dimension; + union + { + D3D10_BUFFER_DESC d3d10_buf; + D3D10_TEXTURE1D_DESC d3d10_1d; + D3D10_TEXTURE2D_DESC d3d10_2d; + D3D10_TEXTURE3D_DESC d3d10_3d; + D3D11_BUFFER_DESC d3d11_buf; + D3D11_TEXTURE1D_DESC d3d11_1d; + D3D11_TEXTURE2D_DESC d3d11_2d; + D3D11_TEXTURE3D_DESC d3d11_3d; + }; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d11_desc) == 0x68 ); + +struct d3dkmt_d3d12_desc +{ + struct d3dkmt_d3d11_desc d3d11; + UINT unknown_5[4]; + UINT resource_size; + UINT unknown_6[7]; + UINT resource_align; + UINT unknown_7[9]; + union + { + D3D12_RESOURCE_DESC desc; + D3D12_RESOURCE_DESC1 desc1; + }; + UINT64 unknown_8[1]; +}; + +C_ASSERT( sizeof(struct d3dkmt_d3d12_desc) == 0x108 ); +C_ASSERT( offsetof(struct d3dkmt_d3d12_desc, unknown_5) == sizeof(struct d3dkmt_d3d11_desc) ); + +union d3dkmt_desc +{ + struct d3dkmt_dxgi_desc dxgi; + struct d3dkmt_d3d9_desc d3d9; + struct d3dkmt_d3d11_desc d3d11; + struct d3dkmt_d3d12_desc d3d12; +}; + struct d3dkmt_object { enum d3dkmt_type type; /* object type */ @@ -1858,24 +1967,32 @@ D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) { struct d3dkmt_object *allocation = NULL; struct d3dkmt_resource *resource = NULL; + void *runtime_data = NULL; + UINT runtime_size; NTSTATUS status; - UINT dummy = 0;
TRACE( "global %#x, shared %p\n", global, shared );
+ if ((status = d3dkmt_object_query( D3DKMT_RESOURCE, global, shared, &runtime_size ))) goto failed; + if (runtime_size && !(runtime_data = malloc( runtime_size ))) goto failed; + if ((status = d3dkmt_object_alloc( sizeof(*resource), D3DKMT_RESOURCE, (void **)&resource ))) goto failed; if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed; - if ((status = d3dkmt_object_open( &resource->obj, global, shared, NULL, &dummy ))) goto failed; + if ((status = d3dkmt_object_open( &resource->obj, global, shared, runtime_data, &runtime_size ))) goto failed;
if ((status = alloc_object_handle( allocation ))) goto failed; resource->allocation = allocation->local;
+ if (!runtime_data || runtime_size <= sizeof(struct d3dkmt_dxgi_desc)) WARN( "Unsupported runtime data size %#x\n", runtime_size ); + + free( runtime_data ); return resource->obj.local;
failed: WARN( "Failed to open resource, status %#x\n", status ); if (allocation) d3dkmt_object_free( allocation ); if (resource) d3dkmt_object_free( &resource->obj ); + free( runtime_data ); return 0; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/d3dkmt.c | 39 ++++++++++++++++++++++++++++++++---- dlls/win32u/vulkan.c | 11 ++++++++-- dlls/win32u/win32u_private.h | 3 ++- 3 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/dlls/win32u/d3dkmt.c b/dlls/win32u/d3dkmt.c index ea98968029f..1e731ded520 100644 --- a/dlls/win32u/d3dkmt.c +++ b/dlls/win32u/d3dkmt.c @@ -1522,7 +1522,7 @@ NTSTATUS WINAPI NtGdiDdDDICreateKeyedMutex( D3DKMT_CREATEKEYEDMUTEX *params ) return status; }
-static NTSTATUS d3dkmt_destroy_mutex( D3DKMT_HANDLE local ) +NTSTATUS d3dkmt_destroy_mutex( D3DKMT_HANDLE local ) { struct d3dkmt_mutex *mutex; BOOL owned; @@ -1917,6 +1917,18 @@ NTSTATUS WINAPI NtGdiDdDDIDestroySynchronizationObject( const D3DKMT_DESTROYSYNC return d3dkmt_destroy_sync( params->hSyncObject ); }
+static void get_resource_global_keyed_mutex( struct d3dkmt_dxgi_desc *desc, D3DKMT_HANDLE *mutex_global, D3DKMT_HANDLE *sync_global ) +{ + if ((desc->size != sizeof(struct d3dkmt_d3d9_desc) && desc->size != sizeof(struct d3dkmt_d3d11_desc)) || + (desc->version != 0 && desc->version != 1 && desc->version != 4)) + WARN( "Unsupported runtime data size %#x version %#x\n", desc->size, desc->version ); + else if (desc->keyed_mutex && !desc->nt_shared) + { + *mutex_global = desc->mutex_handle; + *sync_global = desc->sync_handle; + } +} + /* get a locally opened D3DKMT object host-specific fd */ int d3dkmt_object_get_fd( D3DKMT_HANDLE local ) { @@ -1963,12 +1975,13 @@ failed: }
/* open a D3DKMT global or shared resource */ -D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) +D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared, D3DKMT_HANDLE *mutex_local, D3DKMT_HANDLE *sync_local ) { - struct d3dkmt_object *allocation = NULL; + struct d3dkmt_object *allocation = NULL, *mutex = NULL, *sync = NULL; + UINT runtime_size, mutex_size = 0, sync_size = 0; + D3DKMT_HANDLE mutex_global = 0, sync_global = 0; struct d3dkmt_resource *resource = NULL; void *runtime_data = NULL; - UINT runtime_size; NTSTATUS status;
TRACE( "global %#x, shared %p\n", global, shared ); @@ -1976,6 +1989,8 @@ D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) if ((status = d3dkmt_object_query( D3DKMT_RESOURCE, global, shared, &runtime_size ))) goto failed; if (runtime_size && !(runtime_data = malloc( runtime_size ))) goto failed;
+ if ((status = d3dkmt_object_alloc( sizeof(*sync), D3DKMT_SYNC, (void **)&sync ))) goto failed; + if ((status = d3dkmt_object_alloc( sizeof(*mutex), D3DKMT_MUTEX, (void **)&mutex ))) goto failed; if ((status = d3dkmt_object_alloc( sizeof(*resource), D3DKMT_RESOURCE, (void **)&resource ))) goto failed; if ((status = d3dkmt_object_alloc( sizeof(*allocation), D3DKMT_ALLOCATION, (void **)&allocation ))) goto failed; if ((status = d3dkmt_object_open( &resource->obj, global, shared, runtime_data, &runtime_size ))) goto failed; @@ -1984,6 +1999,20 @@ D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ) resource->allocation = allocation->local;
if (!runtime_data || runtime_size <= sizeof(struct d3dkmt_dxgi_desc)) WARN( "Unsupported runtime data size %#x\n", runtime_size ); + else get_resource_global_keyed_mutex( runtime_data, &mutex_global, &sync_global ); + + if (!d3dkmt_object_open( mutex, mutex_global, shared, NULL, &mutex_size ) && + !d3dkmt_object_open( sync, sync_global, shared, NULL, &sync_size )) + { + *mutex_local = mutex->local; + *sync_local = sync->local; + } + else + { + d3dkmt_object_free( mutex ); + d3dkmt_object_free( sync ); + *mutex_local = *sync_local = 0; + }
free( runtime_data ); return resource->obj.local; @@ -1992,6 +2021,8 @@ failed: WARN( "Failed to open resource, status %#x\n", status ); if (allocation) d3dkmt_object_free( allocation ); if (resource) d3dkmt_object_free( &resource->obj ); + if (mutex) d3dkmt_object_free( mutex ); + if (sync) d3dkmt_object_free( sync ); free( runtime_data ); return 0; } diff --git a/dlls/win32u/vulkan.c b/dlls/win32u/vulkan.c index c6f90a7fbec..c075fad1c37 100644 --- a/dlls/win32u/vulkan.c +++ b/dlls/win32u/vulkan.c @@ -68,6 +68,9 @@ struct device_memory D3DKMT_HANDLE local; D3DKMT_HANDLE global; HANDLE shared; + + D3DKMT_HANDLE sync; + D3DKMT_HANDLE mutex; };
static inline struct device_memory *device_memory_from_handle( VkDeviceMemory handle ) @@ -338,7 +341,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT: case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT: memory->global = PtrToUlong( import_win32->handle ); - memory->local = d3dkmt_open_resource( memory->global, NULL ); + memory->local = d3dkmt_open_resource( memory->global, NULL, &memory->mutex, &memory->sync ); break; case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT: case VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT: @@ -347,7 +350,7 @@ static VkResult win32u_vkAllocateMemory( VkDevice client_device, const VkMemoryA { HANDLE shared = import_win32->handle; if (import_win32->name && !(shared = open_shared_resource_from_name( import_win32->name ))) break; - memory->local = d3dkmt_open_resource( 0, shared ); + memory->local = d3dkmt_open_resource( 0, shared, &memory->mutex, &memory->sync ); if (shared && shared != import_win32->handle) NtClose( shared ); break; } @@ -407,6 +410,8 @@ failed: WARN( "Failed to allocate memory, res %d\n", res ); if (host_device_memory) device->p_vkFreeMemory( device->host.device, host_device_memory, NULL ); d3dkmt_destroy_resource( memory->local ); + d3dkmt_destroy_mutex( memory->mutex ); + d3dkmt_destroy_sync( memory->sync ); free( memory ); return VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -443,6 +448,8 @@ static void win32u_vkFreeMemory( VkDevice client_device, VkDeviceMemory client_m
if (memory->shared) NtClose( memory->shared ); d3dkmt_destroy_resource( memory->local ); + d3dkmt_destroy_mutex( memory->mutex ); + d3dkmt_destroy_sync( memory->sync ); free( memory ); }
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 7bca9db4226..ba0a9834d9f 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -207,9 +207,10 @@ extern BOOL get_vulkan_uuid_from_luid( const LUID *luid, GUID *uuid ); extern BOOL get_luid_from_vulkan_uuid( const GUID *uuid, LUID *luid, UINT32 *node_mask );
extern int d3dkmt_object_get_fd( D3DKMT_HANDLE local ); +extern NTSTATUS d3dkmt_destroy_mutex( D3DKMT_HANDLE local );
extern D3DKMT_HANDLE d3dkmt_create_resource( int fd, D3DKMT_HANDLE *global ); -extern D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared ); +extern D3DKMT_HANDLE d3dkmt_open_resource( D3DKMT_HANDLE global, HANDLE shared, D3DKMT_HANDLE *mutex_local, D3DKMT_HANDLE *sync_local ); extern NTSTATUS d3dkmt_destroy_resource( D3DKMT_HANDLE local );
extern D3DKMT_HANDLE d3dkmt_create_sync( int fd, D3DKMT_HANDLE *global );