Signed-off-by: Derek Lesho <dlesho(a)codeweavers.com>
---
v8: Remove unnecessary cast mentioned in review of v5 (I forgot to address the comment earlier).
---
dlls/vulkan-1/tests/vulkan.c | 1 +
dlls/winevulkan/make_vulkan | 20 +-
dlls/winevulkan/vulkan.c | 351 ++++++++++++++++++++++++++++++-
dlls/winevulkan/vulkan_private.h | 24 +++
4 files changed, 389 insertions(+), 7 deletions(-)
diff --git a/dlls/vulkan-1/tests/vulkan.c b/dlls/vulkan-1/tests/vulkan.c
index 64dcead3476..935ded0c3bf 100644
--- a/dlls/vulkan-1/tests/vulkan.c
+++ b/dlls/vulkan-1/tests/vulkan.c
@@ -696,6 +696,7 @@ static void test_external_memory(VkInstance vk_instance, VkPhysicalDevice vk_phy
import_handle_info.name = L"wine_test_buffer_export_name";
vr = vkAllocateMemory(vk_device, &alloc_info, NULL, &vk_memory_import);
+ todo_wine
ok(vr == VK_SUCCESS, "vkAllocateMemory failed, VkResult %d.\n", vr);
if (vr == VK_SUCCESS)
{
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 31219ad0469..618ce121862 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -108,7 +108,6 @@ UNSUPPORTED_EXTENSIONS = [
"VK_EXT_external_memory_dma_buf",
"VK_EXT_image_drm_format_modifier",
"VK_KHR_external_fence_fd",
- "VK_KHR_external_memory_fd",
"VK_KHR_external_semaphore_fd",
# Extensions which require callback handling
@@ -123,7 +122,7 @@ UNSUPPORTED_EXTENSIONS = [
# winevulkan may nonetheless use, or extensions we want to generate headers for
# but not expose to applications (useful for test commits)
UNEXPOSED_EXTENSIONS = {
- "VK_KHR_external_memory_win32",
+ "VK_KHR_external_memory_fd",
}
# The Vulkan loader provides entry-points for core functionality and important
@@ -182,7 +181,7 @@ FUNCTION_OVERRIDES = {
"vkEnumerateDeviceLayerProperties": {"dispatch": True, "driver": False, "thunk": ThunkType.NONE},
"vkEnumeratePhysicalDeviceGroups" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
- "vkGetPhysicalDeviceExternalBufferProperties" : {"dispatch" : False, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkGetPhysicalDeviceExternalBufferProperties" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetPhysicalDeviceExternalFenceProperties" : {"dispatch" : False, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetPhysicalDeviceExternalSemaphoreProperties" : {"dispatch" : False, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetPhysicalDeviceImageFormatProperties2" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE},
@@ -191,10 +190,13 @@ FUNCTION_OVERRIDES = {
# Device functions
"vkAllocateCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkAllocateMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkCreateBuffer" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkCreateCommandPool" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
"vkDestroyCommandPool" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
"vkDestroyDevice" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkFreeCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkFreeMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetDeviceProcAddr" : {"dispatch" : False, "driver" : True, "thunk" : ThunkType.NONE, "loader_thunk" : ThunkType.NONE},
"vkGetDeviceQueue" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetDeviceQueue2" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
@@ -224,7 +226,7 @@ FUNCTION_OVERRIDES = {
"vkGetPhysicalDeviceExternalFencePropertiesKHR" : {"dispatch" : False, "driver" : False, "thunk" : ThunkType.NONE},
# VK_KHR_external_memory_capabilities
- "vkGetPhysicalDeviceExternalBufferPropertiesKHR" : {"dispatch" : False, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkGetPhysicalDeviceExternalBufferPropertiesKHR" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetPhysicalDeviceImageFormatProperties2KHR" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE},
# VK_KHR_external_semaphore_capabilities
@@ -260,12 +262,20 @@ FUNCTION_OVERRIDES = {
# VK_EXT_debug_marker
"vkDebugMarkerSetObjectNameEXT" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.PRIVATE},
"vkDebugMarkerSetObjectTagEXT" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.PRIVATE},
+
+ # VK_KHR_external_memory_win32
+ "vkGetMemoryWin32HandleKHR" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
+ "vkGetMemoryWin32HandlePropertiesKHR" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
}
STRUCT_CHAIN_CONVERSIONS = {
# Ignore to not confuse host loader.
"VkDeviceCreateInfo": ["VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO"],
"VkInstanceCreateInfo": ["VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO"],
+
+ # Structs which require pNext chain modification
+ "VkBufferCreateInfo": [],
+ "VkMemoryAllocateInfo": ["VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR", "VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR"],
}
@@ -1056,6 +1066,8 @@ class VkHandle(object):
return "wine_debug_report_callback_from_handle({0})->debug_callback".format(name)
if self.name == "VkSurfaceKHR":
return "wine_surface_from_handle({0})->surface".format(name)
+ if self.name == "VkDeviceMemory":
+ return "wine_dev_mem_from_handle({0})->dev_mem".format(name)
native_handle_name = None
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 9f181d92bc5..b7b24818cac 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -25,6 +25,7 @@
#include <time.h>
#include <stdarg.h>
#include <stdlib.h>
+#include <unistd.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -34,6 +35,8 @@
#include "winuser.h"
#include "winternl.h"
+#include "wine/server.h"
+
#include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
@@ -263,6 +266,15 @@ static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstanc
*/
for (i = 0; i < num_host_properties; i++)
{
+ if (!strcmp(host_properties[i].extensionName, "VK_KHR_external_memory_fd"))
+ {
+ TRACE("Substituting VK_KHR_external_memory_fd for VK_KHR_external_memory_win32\n");
+
+ snprintf(host_properties[i].extensionName, sizeof(host_properties[i].extensionName),
+ VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
+ host_properties[i].specVersion = VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION;
+ }
+
if (wine_vk_device_extension_supported(host_properties[i].extensionName))
{
TRACE("Enabling extension '%s' for physical device %p\n", host_properties[i].extensionName, object);
@@ -361,11 +373,15 @@ static void wine_vk_device_get_queues(struct VkDevice_T *device,
static void wine_vk_device_free_create_info(VkDeviceCreateInfo *create_info)
{
free_VkDeviceCreateInfo_struct_chain(create_info);
+
+ if (create_info->enabledExtensionCount)
+ free((void *)create_info->ppEnabledExtensionNames);
}
static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src,
VkDeviceCreateInfo *dst)
{
+ const char **enabled_extensions;
unsigned int i;
VkResult res;
@@ -389,11 +405,34 @@ static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src
if (!wine_vk_device_extension_supported(extension_name))
{
WARN("Extension %s is not supported.\n", debugstr_a(extension_name));
- wine_vk_device_free_create_info(dst);
+ free_VkDeviceCreateInfo_struct_chain(dst);
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
}
+ if (src->enabledExtensionCount > 0)
+ {
+ enabled_extensions = calloc(src->enabledExtensionCount, sizeof(*src->ppEnabledExtensionNames));
+ if (!enabled_extensions)
+ {
+ free_VkDeviceCreateInfo_struct_chain(dst);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ for (i = 0; i < src->enabledExtensionCount; i++)
+ {
+ if (!strcmp(src->ppEnabledExtensionNames[i], "VK_KHR_external_memory_win32"))
+ {
+ enabled_extensions[i] = "VK_KHR_external_memory_fd";
+ }
+ else
+ {
+ enabled_extensions[i] = src->ppEnabledExtensionNames[i];
+ }
+ }
+ dst->ppEnabledExtensionNames = enabled_extensions;
+ }
+
return VK_SUCCESS;
}
@@ -1187,18 +1226,71 @@ void WINAPI wine_vkGetPhysicalDeviceExternalFencePropertiesKHR(VkPhysicalDevice
properties->externalFenceFeatures = 0;
}
+static inline void wine_vk_normalize_handle_types_win(VkExternalMemoryHandleTypeFlags *types)
+{
+ *types &=
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT;
+}
+
+static inline void wine_vk_normalize_handle_types_host(VkExternalMemoryHandleTypeFlags *types)
+{
+ *types &=
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT |
+/* predicated on VK_KHR_external_memory_dma_buf
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT | */
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT;
+}
+
+static void wine_vk_get_physical_device_external_buffer_properties(VkPhysicalDevice phys_dev,
+ void (*p_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice, const VkPhysicalDeviceExternalBufferInfo *, VkExternalBufferProperties *),
+ const VkPhysicalDeviceExternalBufferInfo *buffer_info, VkExternalBufferProperties *properties)
+{
+ VkPhysicalDeviceExternalBufferInfo buffer_info_dup = *buffer_info;
+
+ wine_vk_normalize_handle_types_win(&buffer_info_dup.handleType);
+ if (buffer_info_dup.handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)
+ buffer_info_dup.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+ wine_vk_normalize_handle_types_host(&buffer_info_dup.handleType);
+
+ if (buffer_info->handleType && !buffer_info_dup.handleType)
+ {
+ memset(&properties->externalMemoryProperties, 0, sizeof(properties->externalMemoryProperties));
+ return;
+ }
+
+ p_vkGetPhysicalDeviceExternalBufferProperties(phys_dev->phys_dev, &buffer_info_dup, properties);
+
+ if (properties->externalMemoryProperties.exportFromImportedHandleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
+ properties->externalMemoryProperties.exportFromImportedHandleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+ wine_vk_normalize_handle_types_win(&properties->externalMemoryProperties.exportFromImportedHandleTypes);
+
+ if (properties->externalMemoryProperties.compatibleHandleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
+ properties->externalMemoryProperties.compatibleHandleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
+ wine_vk_normalize_handle_types_win(&properties->externalMemoryProperties.compatibleHandleTypes);
+}
+
void WINAPI wine_vkGetPhysicalDeviceExternalBufferProperties(VkPhysicalDevice phys_dev,
const VkPhysicalDeviceExternalBufferInfo *buffer_info, VkExternalBufferProperties *properties)
{
TRACE("%p, %p, %p\n", phys_dev, buffer_info, properties);
- memset(&properties->externalMemoryProperties, 0, sizeof(properties->externalMemoryProperties));
+
+ wine_vk_get_physical_device_external_buffer_properties(phys_dev, phys_dev->instance->funcs.p_vkGetPhysicalDeviceExternalBufferProperties, buffer_info, properties);
}
void WINAPI wine_vkGetPhysicalDeviceExternalBufferPropertiesKHR(VkPhysicalDevice phys_dev,
const VkPhysicalDeviceExternalBufferInfo *buffer_info, VkExternalBufferProperties *properties)
{
TRACE("%p, %p, %p\n", phys_dev, buffer_info, properties);
- memset(&properties->externalMemoryProperties, 0, sizeof(properties->externalMemoryProperties));
+
+ wine_vk_get_physical_device_external_buffer_properties(phys_dev, phys_dev->instance->funcs.p_vkGetPhysicalDeviceExternalBufferPropertiesKHR, buffer_info, properties);
}
VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice phys_dev,
@@ -1720,3 +1812,256 @@ VkResult WINAPI wine_vkDebugMarkerSetObjectNameEXT(VkDevice device, const VkDebu
return thunk_vkDebugMarkerSetObjectNameEXT(device, &wine_name_info);
}
+
+static HANDLE create_gpu_resource(int fd, LPCWSTR name)
+{
+ HANDLE ret = INVALID_HANDLE_VALUE;
+
+ if (name)
+ FIXME("Naming gpu resources not supported.\n");
+
+ wine_server_fd_to_handle(fd, GENERIC_ALL, 0, &ret);
+
+ return ret;
+}
+
+VkResult WINAPI wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *allocate_info,
+ const VkAllocationCallbacks *allocator, VkDeviceMemory *memory)
+{
+ const VkImportMemoryWin32HandleInfoKHR *handle_import_info;
+ const VkExportMemoryWin32HandleInfoKHR *handle_export_info;
+ VkMemoryAllocateInfo allocate_info_dup = *allocate_info;
+ VkExportMemoryAllocateInfo *export_info;
+ VkImportMemoryFdInfoKHR fd_import_info;
+ struct wine_dev_mem *object;
+ VkResult res;
+ int fd;
+
+#if defined(USE_STRUCT_CONVERSION)
+ VkMemoryAllocateInfo_host allocate_info_host;
+ VkMemoryGetFdInfoKHR_host get_fd_info;
+#else
+ VkMemoryAllocateInfo allocate_info_host;
+ VkMemoryGetFdInfoKHR get_fd_info;
+#endif
+
+ TRACE("%p %p %p %p\n", device, allocate_info, allocator, memory);
+
+ if (allocator)
+ FIXME("Support for allocation callbacks not implemented yet\n");
+
+ if ((res = convert_VkMemoryAllocateInfo_struct_chain(allocate_info->pNext, &allocate_info_dup)) < 0)
+ {
+ WARN("Failed to convert VkMemoryAllocateInfo pNext chain, res=%d.\n", res);
+ return res;
+ }
+
+ if (!(object = calloc(1, sizeof(*object))))
+ {
+ free_VkMemoryAllocateInfo_struct_chain(&allocate_info_dup);
+ return VK_ERROR_OUT_OF_HOST_MEMORY;
+ }
+
+ object->dev_mem = VK_NULL_HANDLE;
+ object->handle = INVALID_HANDLE_VALUE;
+ fd_import_info.fd = -1;
+ fd_import_info.pNext = NULL;
+
+ /* find and process handle import/export info and grab it */
+ handle_import_info = wine_vk_find_struct(allocate_info, IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR);
+ handle_export_info = wine_vk_find_struct(allocate_info, EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR);
+ if (handle_export_info && handle_export_info->pAttributes && handle_export_info->pAttributes->lpSecurityDescriptor)
+ FIXME("Support for custom security descriptor not implemented.\n");
+
+ if ((export_info = wine_vk_find_struct(&allocate_info_dup, EXPORT_MEMORY_ALLOCATE_INFO)))
+ {
+ object->handle_types = export_info->handleTypes;
+ if (export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)
+ export_info->handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+ wine_vk_normalize_handle_types_host(&export_info->handleTypes);
+ }
+
+ /* Vulkan consumes imported FDs, but not imported HANDLEs */
+ if (handle_import_info)
+ {
+ fd_import_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR;
+ fd_import_info.pNext = allocate_info_dup.pNext;
+ fd_import_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+
+ switch (handle_import_info->handleType)
+ {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ if (handle_import_info->handle)
+ NtDuplicateObject( NtCurrentProcess(), handle_import_info->handle, NtCurrentProcess(), &object->handle, 0, 0, DUPLICATE_SAME_ACCESS );
+ else if (handle_import_info->name)
+ FIXME("Importing device memory by resource name not supported.\n");
+ break;
+ default:
+ WARN("Invalid handle type %08x passed in.\n", handle_import_info->handleType);
+ res = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ goto done;
+ }
+
+ if (object->handle != INVALID_HANDLE_VALUE)
+ wine_server_handle_to_fd(object->handle, FILE_READ_DATA, &fd_import_info.fd, NULL);
+
+ if (fd_import_info.fd == -1)
+ {
+ TRACE("Couldn't access resource handle or name. type=%08x handle=%p name=%s\n", handle_import_info->handleType, handle_import_info->handle,
+ handle_import_info->name ? debugstr_w(handle_import_info->name) : "");
+ res = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ goto done;
+ }
+ }
+
+ allocate_info_host.sType = allocate_info_dup.sType;
+ allocate_info_host.pNext = fd_import_info.fd == -1 ? allocate_info_dup.pNext : &fd_import_info;
+ allocate_info_host.allocationSize = allocate_info_dup.allocationSize;
+ allocate_info_host.memoryTypeIndex = allocate_info_dup.memoryTypeIndex;
+
+ if ((res = device->funcs.p_vkAllocateMemory(device->device, &allocate_info_host, NULL, &object->dev_mem)) == VK_SUCCESS)
+ {
+ if (object->handle == INVALID_HANDLE_VALUE && export_info && export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
+ {
+ get_fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
+ get_fd_info.pNext = NULL;
+ get_fd_info.memory = object->dev_mem;
+ get_fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+
+ if (device->funcs.p_vkGetMemoryFdKHR(device->device, &get_fd_info, &fd) == VK_SUCCESS)
+ {
+ object->handle = create_gpu_resource(fd, handle_export_info ? handle_export_info->name : NULL);
+ object->access = handle_export_info ? handle_export_info->dwAccess : GENERIC_ALL;
+ if (handle_export_info && handle_export_info->pAttributes)
+ object->inherit = handle_export_info->pAttributes->bInheritHandle;
+ else
+ object->inherit = FALSE;
+ close(fd);
+ }
+
+ if (object->handle == INVALID_HANDLE_VALUE)
+ {
+ res = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto done;
+ }
+ }
+
+ WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object, object->dev_mem);
+ *memory = wine_dev_mem_to_handle(object);
+ }
+
+ done:
+
+ if (res != VK_SUCCESS)
+ {
+ device->funcs.p_vkFreeMemory(device->device, object->dev_mem, NULL);
+ if (fd_import_info.fd != -1)
+ close(fd_import_info.fd);
+ if (object->handle != INVALID_HANDLE_VALUE)
+ NtClose(object->handle);
+ free(object);
+ }
+
+ free_VkMemoryAllocateInfo_struct_chain(&allocate_info_dup);
+
+ return res;
+}
+
+VkResult WINAPI wine_vkGetMemoryWin32HandleKHR(VkDevice device,
+ const VkMemoryGetWin32HandleInfoKHR *handle_info, HANDLE *handle)
+{
+ struct wine_dev_mem *dev_mem = wine_dev_mem_from_handle(handle_info->memory);
+ const VkBaseInStructure *chain;
+
+ TRACE("%p, %p %p\n", device, handle_info, handle);
+
+ if (!(dev_mem->handle_types & handle_info->handleType))
+ return VK_ERROR_UNKNOWN;
+
+ if ((chain = handle_info->pNext))
+ FIXME("Ignoring a linked structure of type %u.\n", chain->sType);
+
+ switch(handle_info->handleType)
+ {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT:
+ return !NtDuplicateObject( NtCurrentProcess(), dev_mem->handle, NtCurrentProcess(), handle, dev_mem->access, dev_mem->inherit ? OBJ_INHERIT : 0, 0) ?
+ VK_SUCCESS : VK_ERROR_OUT_OF_HOST_MEMORY;
+ default:
+ FIXME("Unable to get handle of type %x, did the application ignore the capabilities?\n", handle_info->handleType);
+ return VK_ERROR_UNKNOWN;
+ }
+}
+
+void WINAPI wine_vkFreeMemory(VkDevice device, VkDeviceMemory handle, const VkAllocationCallbacks *allocator)
+{
+ struct wine_dev_mem *dev_mem = wine_dev_mem_from_handle(handle);
+
+ TRACE("%p 0x%s, %p\n", device, wine_dbgstr_longlong(handle), allocator);
+
+ if (allocator)
+ FIXME("Support for allocation callbacks not implemented yet\n");
+
+ if (!handle)
+ return;
+
+ WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, dev_mem);
+ device->funcs.p_vkFreeMemory(device->device, dev_mem->dev_mem, NULL);
+ if (dev_mem->handle != INVALID_HANDLE_VALUE)
+ NtClose(dev_mem->handle);
+ free(dev_mem);
+}
+
+VkResult WINAPI wine_vkGetMemoryWin32HandlePropertiesKHR(VkDevice device,
+ VkExternalMemoryHandleTypeFlagBits type, HANDLE handle, VkMemoryWin32HandlePropertiesKHR *properties)
+{
+ TRACE("%p %u %p %p\n", device, type, handle, properties);
+
+ /* VUID-vkGetMemoryWin32HandlePropertiesKHR-handleType-00666
+ handleType must not be one of the handle types defined as opaque */
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+}
+
+VkResult WINAPI wine_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *create_info,
+ const VkAllocationCallbacks *allocator, VkBuffer *buffer)
+{
+ VkExternalMemoryBufferCreateInfo *external_memory_info;
+ VkResult res;
+
+#if defined(USE_STRUCT_CONVERSION)
+ VkBufferCreateInfo_host create_info_host;
+#else
+ VkBufferCreateInfo create_info_host;
+#endif
+
+ TRACE("%p %p %p %p\n", device, create_info, allocator, buffer);
+
+ if (allocator)
+ FIXME("Support for allocation callbacks not implemented yet\n");
+
+ if ((res = convert_VkBufferCreateInfo_struct_chain(create_info->pNext, (VkBufferCreateInfo *) &create_info_host)))
+ {
+ WARN("Failed to convert VkBufferCreateInfo pNext chain, res=%d.\n", res);
+ return res;
+ }
+
+ if ((external_memory_info = wine_vk_find_struct(&create_info_host, EXTERNAL_MEMORY_BUFFER_CREATE_INFO)))
+ {
+ if (external_memory_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT)
+ external_memory_info->handleTypes |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
+ wine_vk_normalize_handle_types_host(&external_memory_info->handleTypes);
+ }
+
+ create_info_host.sType = create_info->sType;
+ create_info_host.flags = create_info->flags;
+ create_info_host.size = create_info->size;
+ create_info_host.usage = create_info->usage;
+ create_info_host.sharingMode = create_info->sharingMode;
+ create_info_host.queueFamilyIndexCount = create_info->queueFamilyIndexCount;
+ create_info_host.pQueueFamilyIndices = create_info->pQueueFamilyIndices;
+
+ res = device->funcs.p_vkCreateBuffer(device->device, &create_info_host, NULL, buffer);
+
+ free_VkBufferCreateInfo_struct_chain((VkBufferCreateInfo *) &create_info_host);
+
+ return res;
+}
diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h
index 83dc90ca15e..4a20702d43b 100644
--- a/dlls/winevulkan/vulkan_private.h
+++ b/dlls/winevulkan/vulkan_private.h
@@ -204,6 +204,30 @@ static inline VkSurfaceKHR wine_surface_to_handle(struct wine_surface *surface)
return (VkSurfaceKHR)(uintptr_t)surface;
}
+struct wine_dev_mem
+{
+ VkDeviceMemory dev_mem;
+
+ VkExternalMemoryHandleTypeFlagBits handle_types;
+
+ BOOL inherit;
+ DWORD access;
+
+ HANDLE handle;
+
+ struct wine_vk_mapping mapping;
+};
+
+static inline struct wine_dev_mem *wine_dev_mem_from_handle(VkDeviceMemory handle)
+{
+ return (struct wine_dev_mem *)(uintptr_t)handle;
+}
+
+static inline VkDeviceMemory wine_dev_mem_to_handle(struct wine_dev_mem *dev_mem)
+{
+ return (VkDeviceMemory)(uintptr_t)dev_mem;
+}
+
BOOL wine_vk_device_extension_supported(const char *name) DECLSPEC_HIDDEN;
BOOL wine_vk_instance_extension_supported(const char *name) DECLSPEC_HIDDEN;
--
2.31.1