This MR implements memory mapping for wow64 using VK_EXT_external_memory_host. This has some problems (more below), but overall, it looks promising as a stopgap. It passes D3D tests and works fine in general.
For proper solution, we'd need a new Vulkan extension. I experimented with a prototype extension https://github.com/KhronosGroup/Vulkan-Docs/pull/1906 and it looks like we can make it work, my WIP implementation is here https://gitlab.winehq.org/jacek/wine/-/tree/vulkan-map-placed. However, it would be nice to have a fallback working on existing drivers as well.
The main problem of this MR is that it breaks Vulkan spec. The main rule it breaks is that according to spec, we should explicitly specify that we plan to use external memory when creating VkBuffer or VkImage. The problem is that we don't know if we will until we bind memory to the buffer. I tried some workarounds for that (delaying actual buffer creation, recreating buffer when needed). I got it mostly working and passing tests without validation errors, but it was more invasive than I'd like and still had other problems. I'd rather avoid that if possible.
After looking at Mesa sources, I think that the way this MR breaks the spec should be harmless for its drivers. I don't have the hardware to test with Nvidia. If it works there, I'm tempted to ignore spec violation for now, given that the right path forward is VK_EXT_map_memory_placed anyway.
Performance-wise, this MR is sub-optimal because we're limited in what memory types we can use. However, I ran Unigine benchmarks on radv and the difference was marginal. In case of Heaven, it was even slightly faster on wow64, which could be explained by 64-bit Vulkan driver being generally slightly faster, but the difference is too small to draw any conclusion.
The last patch is not meant for (eventual) merge, but it's nice for testing the concept. It makes it possible to force using external memory in any kind of Wine build to experiment with its effects without need for wow64. To test that, just set `WINEVULKAN_EXTERNAL_MEMORY` environment variable.
-- v4: winevulkan: Introduce debugging environment variables. winevulkan: Use VK_EXT_external_memory_host extension to map memory on wow64.
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 22 +++++++++++++++------- dlls/winevulkan/vulkan_thunks.c | 12 ++++++------ 2 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 6d07423a5ed..d3131c3c41f 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -1452,10 +1452,13 @@ class VkMember(VkVariable): # Nothing needed this yet. LOGGER.warn("TODO: implement copying of static array for {0}.{1}".format(self.type, self.name)) elif self.is_handle() and self.needs_unwrapping(): + handle = self.type_info["data"] if direction == Direction.OUTPUT: LOGGER.err("OUTPUT parameter {0}.{1} cannot be unwrapped".format(self.type, self.name)) + elif self.optional: + return "{0}{1} = {2} ? {3} : 0;\n".format(output, self.name, + self.value(input, conv), handle.driver_handle(self.value(input, conv))) else: - handle = self.type_info["data"] return "{0}{1} = {2};\n".format(output, self.name, handle.driver_handle(self.value(input, conv))) elif self.is_generic_handle(): if direction == Direction.OUTPUT: @@ -1841,14 +1844,19 @@ class VkParam(VkVariable): p = self.value(params_prefix, conv)
if unwrap: + unwrap_handle = None if self.object_type != None and self.type == "uint64_t": - return "wine_vk_unwrap_handle({0}{1}, {0}{2})".format(params_prefix, self.object_type, self.name) + unwrap_handle = "wine_vk_unwrap_handle({0}{1}, {0}{2})".format( + params_prefix, self.object_type, self.name)
- # We need to pass the native handle to the native Vulkan calls and - # the wine driver's handle to calls which are wrapped by the driver. - driver_handle = self.handle.driver_handle(p) if self.is_handle() else None - if driver_handle: - return driver_handle + elif self.is_handle(): + # We need to pass the native handle to the native Vulkan calls and + # the wine driver's handle to calls which are wrapped by the driver. + unwrap_handle = self.handle.driver_handle(p) + if unwrap_handle: + if self.optional: + unwrap_handle = "{0}{1} ? {2} : 0".format(params_prefix, self.name, unwrap_handle) + return unwrap_handle
return p
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 2181daf678a..ca5f209eaec 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -23444,7 +23444,7 @@ static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win64_to_host(const V
out->sType = in->sType; out->pNext = in->pNext; - out->surface = wine_surface_from_handle(in->surface)->driver_surface; + out->surface = in->surface ? wine_surface_from_handle(in->surface)->driver_surface : 0; } #endif /* _WIN64 */
@@ -23454,7 +23454,7 @@ static inline void convert_VkPhysicalDeviceSurfaceInfo2KHR_win32_to_host(const V
out->sType = in->sType; out->pNext = NULL; - out->surface = wine_surface_from_handle(in->surface)->driver_surface; + out->surface = in->surface ? wine_surface_from_handle(in->surface)->driver_surface : 0; if (in->pNext) FIXME("Unexpected pNext\n"); } @@ -38342,7 +38342,7 @@ static NTSTATUS thunk64_vkGetPhysicalDeviceSurfaceFormatsKHR(void *args)
TRACE("%p, 0x%s, %p, %p\n", params->physicalDevice, wine_dbgstr_longlong(params->surface), params->pSurfaceFormatCount, params->pSurfaceFormats);
- params->result = wine_phys_dev_from_handle(params->physicalDevice)->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormatsKHR(wine_phys_dev_from_handle(params->physicalDevice)->phys_dev, wine_surface_from_handle(params->surface)->driver_surface, params->pSurfaceFormatCount, params->pSurfaceFormats); + params->result = wine_phys_dev_from_handle(params->physicalDevice)->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormatsKHR(wine_phys_dev_from_handle(params->physicalDevice)->phys_dev, params->surface ? wine_surface_from_handle(params->surface)->driver_surface : 0, params->pSurfaceFormatCount, params->pSurfaceFormats); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -38360,7 +38360,7 @@ static NTSTATUS thunk32_vkGetPhysicalDeviceSurfaceFormatsKHR(void *args)
TRACE("%#x, 0x%s, %#x, %#x\n", params->physicalDevice, wine_dbgstr_longlong(params->surface), params->pSurfaceFormatCount, params->pSurfaceFormats);
- params->result = wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormatsKHR(wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->phys_dev, wine_surface_from_handle(params->surface)->driver_surface, (uint32_t *)UlongToPtr(params->pSurfaceFormatCount), (VkSurfaceFormatKHR *)UlongToPtr(params->pSurfaceFormats)); + params->result = wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->instance->funcs.p_vkGetPhysicalDeviceSurfaceFormatsKHR(wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->phys_dev, params->surface ? wine_surface_from_handle(params->surface)->driver_surface : 0, (uint32_t *)UlongToPtr(params->pSurfaceFormatCount), (VkSurfaceFormatKHR *)UlongToPtr(params->pSurfaceFormats)); return STATUS_SUCCESS; }
@@ -38371,7 +38371,7 @@ static NTSTATUS thunk64_vkGetPhysicalDeviceSurfacePresentModesKHR(void *args)
TRACE("%p, 0x%s, %p, %p\n", params->physicalDevice, wine_dbgstr_longlong(params->surface), params->pPresentModeCount, params->pPresentModes);
- params->result = wine_phys_dev_from_handle(params->physicalDevice)->instance->funcs.p_vkGetPhysicalDeviceSurfacePresentModesKHR(wine_phys_dev_from_handle(params->physicalDevice)->phys_dev, wine_surface_from_handle(params->surface)->driver_surface, params->pPresentModeCount, params->pPresentModes); + params->result = wine_phys_dev_from_handle(params->physicalDevice)->instance->funcs.p_vkGetPhysicalDeviceSurfacePresentModesKHR(wine_phys_dev_from_handle(params->physicalDevice)->phys_dev, params->surface ? wine_surface_from_handle(params->surface)->driver_surface : 0, params->pPresentModeCount, params->pPresentModes); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -38389,7 +38389,7 @@ static NTSTATUS thunk32_vkGetPhysicalDeviceSurfacePresentModesKHR(void *args)
TRACE("%#x, 0x%s, %#x, %#x\n", params->physicalDevice, wine_dbgstr_longlong(params->surface), params->pPresentModeCount, params->pPresentModes);
- params->result = wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->instance->funcs.p_vkGetPhysicalDeviceSurfacePresentModesKHR(wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->phys_dev, wine_surface_from_handle(params->surface)->driver_surface, (uint32_t *)UlongToPtr(params->pPresentModeCount), (VkPresentModeKHR *)UlongToPtr(params->pPresentModes)); + params->result = wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->instance->funcs.p_vkGetPhysicalDeviceSurfacePresentModesKHR(wine_phys_dev_from_handle((VkPhysicalDevice)UlongToPtr(params->physicalDevice))->phys_dev, params->surface ? wine_surface_from_handle(params->surface)->driver_surface : 0, (uint32_t *)UlongToPtr(params->pPresentModeCount), (VkPresentModeKHR *)UlongToPtr(params->pPresentModes)); return STATUS_SUCCESS; }
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/make_vulkan | 5 + dlls/winevulkan/vulkan.c | 49 +++- dlls/winevulkan/vulkan_private.h | 10 + dlls/winevulkan/vulkan_thunks.c | 434 ++++++++++++++++++++++++++++--- dlls/winevulkan/vulkan_thunks.h | 3 + 5 files changed, 467 insertions(+), 34 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index d3131c3c41f..26b11c23043 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -209,7 +209,10 @@ FUNCTION_OVERRIDES = { "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}, + "vkAllocateMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, + "vkFreeMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, "vkMapMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, + "vkUnmapMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE},
# VK_KHR_surface "vkDestroySurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.NONE}, @@ -1079,6 +1082,8 @@ class VkHandle(object): return "wine_device_from_handle({0})->device".format(name) if self.name == "VkInstance": return "wine_instance_from_handle({0})->instance".format(name) + if self.name == "VkDeviceMemory": + return "wine_device_memory_from_handle({0})->memory".format(name) if self.name == "VkPhysicalDevice": return "wine_phys_dev_from_handle({0})->phys_dev".format(name) if self.name == "VkQueue": diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index bd02edde4b6..b092756fd4e 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -1441,19 +1441,54 @@ void wine_vkDestroySurfaceKHR(VkInstance handle, VkSurfaceKHR surface, free(object); }
-VkResult wine_vkMapMemory(VkDevice handle, VkDeviceMemory memory, VkDeviceSize offset, +VkResult wine_vkAllocateMemory(VkDevice handle, const VkMemoryAllocateInfo *alloc_info, + const VkAllocationCallbacks *allocator, VkDeviceMemory *ret) +{ + struct wine_device *device = wine_device_from_handle(handle); + struct wine_device_memory *memory; + VkResult result; + + if (!(memory = malloc(sizeof(*memory)))) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + result = device->funcs.p_vkAllocateMemory(device->device, alloc_info, NULL, &memory->memory); + if (result != VK_SUCCESS) + { + free(memory); + return result; + } + + *ret = (VkDeviceMemory)(uintptr_t)memory; + return VK_SUCCESS; +} + +void wine_vkFreeMemory(VkDevice handle, VkDeviceMemory memory_handle, const VkAllocationCallbacks *allocator) +{ + struct wine_device *device = wine_device_from_handle(handle); + struct wine_device_memory *memory; + + if (!memory_handle) + return; + memory = wine_device_memory_from_handle(memory_handle); + + device->funcs.p_vkFreeMemory(device->device, memory->memory, NULL); + free(memory); +} + +VkResult wine_vkMapMemory(VkDevice handle, VkDeviceMemory memory_handle, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **data) { struct wine_device *device = wine_device_from_handle(handle); + struct wine_device_memory *memory = wine_device_memory_from_handle(memory_handle); VkResult result;
- result = device->funcs.p_vkMapMemory(device->device, memory, offset, size, flags, data); + result = device->funcs.p_vkMapMemory(device->device, memory->memory, offset, size, flags, data);
#ifdef _WIN64 if (NtCurrentTeb()->WowTebOffset && result == VK_SUCCESS && (UINT_PTR)*data >> 32) { FIXME("returned mapping %p does not fit 32-bit pointer\n", *data); - device->funcs.p_vkUnmapMemory(device->device, memory); + device->funcs.p_vkUnmapMemory(device->device, memory->memory); *data = NULL; result = VK_ERROR_OUT_OF_HOST_MEMORY; } @@ -1462,6 +1497,14 @@ VkResult wine_vkMapMemory(VkDevice handle, VkDeviceMemory memory, VkDeviceSize o return result; }
+void wine_vkUnmapMemory(VkDevice handle, VkDeviceMemory memory_handle) +{ + struct wine_device *device = wine_device_from_handle(handle); + struct wine_device_memory *memory = wine_device_memory_from_handle(memory_handle); + + device->funcs.p_vkUnmapMemory(device->device, memory->memory); +} + static inline void adjust_max_image_count(struct wine_phys_dev *phys_dev, VkSurfaceCapabilitiesKHR* capabilities) { /* Many Windows games, for example Strange Brigade, No Man's Sky, Path of Exile diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index a895b848156..8055b2380fd 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -169,6 +169,16 @@ static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool hand return (struct wine_cmd_pool *)(uintptr_t)client_ptr->unix_handle; }
+struct wine_device_memory +{ + VkDeviceMemory memory; +}; + +static inline struct wine_device_memory *wine_device_memory_from_handle(VkDeviceMemory handle) +{ + return (struct wine_device_memory *)(uintptr_t)handle; +} + struct wine_debug_utils_messenger { struct wine_instance *instance; /* parent */ diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index ca5f209eaec..d0db55f2596 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -6036,6 +6036,8 @@ static uint64_t wine_vk_unwrap_handle(uint32_t type, uint64_t handle) return (uint64_t) wine_debug_utils_messenger_from_handle(handle)->debug_messenger; case VK_OBJECT_TYPE_DEVICE: return (uint64_t) (uintptr_t) wine_device_from_handle(((VkDevice) (uintptr_t) handle))->device; + case VK_OBJECT_TYPE_DEVICE_MEMORY: + return (uint64_t) wine_device_memory_from_handle(handle)->memory; case VK_OBJECT_TYPE_INSTANCE: return (uint64_t) (uintptr_t) wine_instance_from_handle(((VkInstance) (uintptr_t) handle))->instance; case VK_OBJECT_TYPE_PHYSICAL_DEVICE: @@ -6437,6 +6439,21 @@ static inline void convert_VkCommandBufferBeginInfo_win32_to_host(struct convers } }
+#ifdef _WIN64 +static inline void convert_VkBindAccelerationStructureMemoryInfoNV_win64_to_host(const VkBindAccelerationStructureMemoryInfoNV *in, VkBindAccelerationStructureMemoryInfoNV *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->accelerationStructure = in->accelerationStructure; + out->memory = wine_device_memory_from_handle(in->memory)->memory; + out->memoryOffset = in->memoryOffset; + out->deviceIndexCount = in->deviceIndexCount; + out->pDeviceIndices = in->pDeviceIndices; +} +#endif /* _WIN64 */ + static inline void convert_VkBindAccelerationStructureMemoryInfoNV_win32_to_host(const VkBindAccelerationStructureMemoryInfoNV32 *in, VkBindAccelerationStructureMemoryInfoNV *out) { if (!in) return; @@ -6444,7 +6461,7 @@ static inline void convert_VkBindAccelerationStructureMemoryInfoNV_win32_to_host out->sType = in->sType; out->pNext = NULL; out->accelerationStructure = in->accelerationStructure; - out->memory = in->memory; + out->memory = wine_device_memory_from_handle(in->memory)->memory; out->memoryOffset = in->memoryOffset; out->deviceIndexCount = in->deviceIndexCount; out->pDeviceIndices = (const uint32_t *)UlongToPtr(in->pDeviceIndices); @@ -6452,6 +6469,24 @@ static inline void convert_VkBindAccelerationStructureMemoryInfoNV_win32_to_host FIXME("Unexpected pNext\n"); }
+#ifdef _WIN64 +static inline const VkBindAccelerationStructureMemoryInfoNV *convert_VkBindAccelerationStructureMemoryInfoNV_array_win64_to_host(struct conversion_context *ctx, const VkBindAccelerationStructureMemoryInfoNV *in, uint32_t count) +{ + VkBindAccelerationStructureMemoryInfoNV *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkBindAccelerationStructureMemoryInfoNV_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkBindAccelerationStructureMemoryInfoNV *convert_VkBindAccelerationStructureMemoryInfoNV_array_win32_to_host(struct conversion_context *ctx, const VkBindAccelerationStructureMemoryInfoNV32 *in, uint32_t count) { VkBindAccelerationStructureMemoryInfoNV *out; @@ -6468,6 +6503,19 @@ static inline const VkBindAccelerationStructureMemoryInfoNV *convert_VkBindAccel return out; }
+#ifdef _WIN64 +static inline void convert_VkBindBufferMemoryInfo_win64_to_host(const VkBindBufferMemoryInfo *in, VkBindBufferMemoryInfo *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->buffer = in->buffer; + out->memory = wine_device_memory_from_handle(in->memory)->memory; + out->memoryOffset = in->memoryOffset; +} +#endif /* _WIN64 */ + static inline void convert_VkBindBufferMemoryInfo_win32_to_host(struct conversion_context *ctx, const VkBindBufferMemoryInfo32 *in, VkBindBufferMemoryInfo *out) { const VkBaseInStructure32 *in_header; @@ -6478,7 +6526,7 @@ static inline void convert_VkBindBufferMemoryInfo_win32_to_host(struct conversio out->sType = in->sType; out->pNext = NULL; out->buffer = in->buffer; - out->memory = in->memory; + out->memory = wine_device_memory_from_handle(in->memory)->memory; out->memoryOffset = in->memoryOffset;
for (in_header = UlongToPtr(in->pNext); in_header; in_header = UlongToPtr(in_header->pNext)) @@ -6504,6 +6552,24 @@ static inline void convert_VkBindBufferMemoryInfo_win32_to_host(struct conversio } }
+#ifdef _WIN64 +static inline const VkBindBufferMemoryInfo *convert_VkBindBufferMemoryInfo_array_win64_to_host(struct conversion_context *ctx, const VkBindBufferMemoryInfo *in, uint32_t count) +{ + VkBindBufferMemoryInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkBindBufferMemoryInfo_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkBindBufferMemoryInfo *convert_VkBindBufferMemoryInfo_array_win32_to_host(struct conversion_context *ctx, const VkBindBufferMemoryInfo32 *in, uint32_t count) { VkBindBufferMemoryInfo *out; @@ -6520,6 +6586,19 @@ static inline const VkBindBufferMemoryInfo *convert_VkBindBufferMemoryInfo_array return out; }
+#ifdef _WIN64 +static inline void convert_VkBindImageMemoryInfo_win64_to_host(const VkBindImageMemoryInfo *in, VkBindImageMemoryInfo *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->image = in->image; + out->memory = wine_device_memory_from_handle(in->memory)->memory; + out->memoryOffset = in->memoryOffset; +} +#endif /* _WIN64 */ + static inline void convert_VkBindImageMemoryInfo_win32_to_host(struct conversion_context *ctx, const VkBindImageMemoryInfo32 *in, VkBindImageMemoryInfo *out) { const VkBaseInStructure32 *in_header; @@ -6530,7 +6609,7 @@ static inline void convert_VkBindImageMemoryInfo_win32_to_host(struct conversion out->sType = in->sType; out->pNext = NULL; out->image = in->image; - out->memory = in->memory; + out->memory = wine_device_memory_from_handle(in->memory)->memory; out->memoryOffset = in->memoryOffset;
for (in_header = UlongToPtr(in->pNext); in_header; in_header = UlongToPtr(in_header->pNext)) @@ -6581,6 +6660,24 @@ static inline void convert_VkBindImageMemoryInfo_win32_to_host(struct conversion } }
+#ifdef _WIN64 +static inline const VkBindImageMemoryInfo *convert_VkBindImageMemoryInfo_array_win64_to_host(struct conversion_context *ctx, const VkBindImageMemoryInfo *in, uint32_t count) +{ + VkBindImageMemoryInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkBindImageMemoryInfo_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkBindImageMemoryInfo *convert_VkBindImageMemoryInfo_array_win32_to_host(struct conversion_context *ctx, const VkBindImageMemoryInfo32 *in, uint32_t count) { VkBindImageMemoryInfo *out; @@ -16401,19 +16498,50 @@ static inline void convert_VkPerformanceCounterDescriptionKHR_array_host_to_win3 } }
+#ifdef _WIN64 +static inline void convert_VkMappedMemoryRange_win64_to_host(const VkMappedMemoryRange *in, VkMappedMemoryRange *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->memory = wine_device_memory_from_handle(in->memory)->memory; + out->offset = in->offset; + out->size = in->size; +} +#endif /* _WIN64 */ + static inline void convert_VkMappedMemoryRange_win32_to_host(const VkMappedMemoryRange32 *in, VkMappedMemoryRange *out) { if (!in) return;
out->sType = in->sType; out->pNext = NULL; - out->memory = in->memory; + out->memory = wine_device_memory_from_handle(in->memory)->memory; out->offset = in->offset; out->size = in->size; if (in->pNext) FIXME("Unexpected pNext\n"); }
+#ifdef _WIN64 +static inline const VkMappedMemoryRange *convert_VkMappedMemoryRange_array_win64_to_host(struct conversion_context *ctx, const VkMappedMemoryRange *in, uint32_t count) +{ + VkMappedMemoryRange *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkMappedMemoryRange_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkMappedMemoryRange *convert_VkMappedMemoryRange_array_win32_to_host(struct conversion_context *ctx, const VkMappedMemoryRange32 *in, uint32_t count) { VkMappedMemoryRange *out; @@ -17067,13 +17195,24 @@ static inline void convert_VkSparseImageMemoryRequirements2_array_host_to_win32( } }
+#ifdef _WIN64 +static inline void convert_VkDeviceMemoryOpaqueCaptureAddressInfo_win64_to_host(const VkDeviceMemoryOpaqueCaptureAddressInfo *in, VkDeviceMemoryOpaqueCaptureAddressInfo *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->memory = wine_device_memory_from_handle(in->memory)->memory; +} +#endif /* _WIN64 */ + static inline void convert_VkDeviceMemoryOpaqueCaptureAddressInfo_win32_to_host(const VkDeviceMemoryOpaqueCaptureAddressInfo32 *in, VkDeviceMemoryOpaqueCaptureAddressInfo *out) { if (!in) return;
out->sType = in->sType; out->pNext = NULL; - out->memory = in->memory; + out->memory = wine_device_memory_from_handle(in->memory)->memory; if (in->pNext) FIXME("Unexpected pNext\n"); } @@ -23920,17 +24059,48 @@ static inline void convert_VkInitializePerformanceApiInfoINTEL_win32_to_host(con FIXME("Unexpected pNext\n"); }
+#ifdef _WIN64 +static inline void convert_VkSparseMemoryBind_win64_to_host(const VkSparseMemoryBind *in, VkSparseMemoryBind *out) +{ + if (!in) return; + + out->resourceOffset = in->resourceOffset; + out->size = in->size; + out->memory = in->memory ? wine_device_memory_from_handle(in->memory)->memory : 0; + out->memoryOffset = in->memoryOffset; + out->flags = in->flags; +} +#endif /* _WIN64 */ + static inline void convert_VkSparseMemoryBind_win32_to_host(const VkSparseMemoryBind32 *in, VkSparseMemoryBind *out) { if (!in) return;
out->resourceOffset = in->resourceOffset; out->size = in->size; - out->memory = in->memory; + out->memory = in->memory ? wine_device_memory_from_handle(in->memory)->memory : 0; out->memoryOffset = in->memoryOffset; out->flags = in->flags; }
+#ifdef _WIN64 +static inline const VkSparseMemoryBind *convert_VkSparseMemoryBind_array_win64_to_host(struct conversion_context *ctx, const VkSparseMemoryBind *in, uint32_t count) +{ + VkSparseMemoryBind *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkSparseMemoryBind_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkSparseMemoryBind *convert_VkSparseMemoryBind_array_win32_to_host(struct conversion_context *ctx, const VkSparseMemoryBind32 *in, uint32_t count) { VkSparseMemoryBind *out; @@ -23947,6 +24117,17 @@ static inline const VkSparseMemoryBind *convert_VkSparseMemoryBind_array_win32_t return out; }
+#ifdef _WIN64 +static inline void convert_VkSparseBufferMemoryBindInfo_win64_to_host(struct conversion_context *ctx, const VkSparseBufferMemoryBindInfo *in, VkSparseBufferMemoryBindInfo *out) +{ + if (!in) return; + + out->buffer = in->buffer; + out->bindCount = in->bindCount; + out->pBinds = convert_VkSparseMemoryBind_array_win64_to_host(ctx, in->pBinds, in->bindCount); +} +#endif /* _WIN64 */ + static inline void convert_VkSparseBufferMemoryBindInfo_win32_to_host(struct conversion_context *ctx, const VkSparseBufferMemoryBindInfo32 *in, VkSparseBufferMemoryBindInfo *out) { if (!in) return; @@ -23956,6 +24137,24 @@ static inline void convert_VkSparseBufferMemoryBindInfo_win32_to_host(struct con out->pBinds = convert_VkSparseMemoryBind_array_win32_to_host(ctx, (const VkSparseMemoryBind32 *)UlongToPtr(in->pBinds), in->bindCount); }
+#ifdef _WIN64 +static inline const VkSparseBufferMemoryBindInfo *convert_VkSparseBufferMemoryBindInfo_array_win64_to_host(struct conversion_context *ctx, const VkSparseBufferMemoryBindInfo *in, uint32_t count) +{ + VkSparseBufferMemoryBindInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkSparseBufferMemoryBindInfo_win64_to_host(ctx, &in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkSparseBufferMemoryBindInfo *convert_VkSparseBufferMemoryBindInfo_array_win32_to_host(struct conversion_context *ctx, const VkSparseBufferMemoryBindInfo32 *in, uint32_t count) { VkSparseBufferMemoryBindInfo *out; @@ -23972,6 +24171,17 @@ static inline const VkSparseBufferMemoryBindInfo *convert_VkSparseBufferMemoryBi return out; }
+#ifdef _WIN64 +static inline void convert_VkSparseImageOpaqueMemoryBindInfo_win64_to_host(struct conversion_context *ctx, const VkSparseImageOpaqueMemoryBindInfo *in, VkSparseImageOpaqueMemoryBindInfo *out) +{ + if (!in) return; + + out->image = in->image; + out->bindCount = in->bindCount; + out->pBinds = convert_VkSparseMemoryBind_array_win64_to_host(ctx, in->pBinds, in->bindCount); +} +#endif /* _WIN64 */ + static inline void convert_VkSparseImageOpaqueMemoryBindInfo_win32_to_host(struct conversion_context *ctx, const VkSparseImageOpaqueMemoryBindInfo32 *in, VkSparseImageOpaqueMemoryBindInfo *out) { if (!in) return; @@ -23981,6 +24191,24 @@ static inline void convert_VkSparseImageOpaqueMemoryBindInfo_win32_to_host(struc out->pBinds = convert_VkSparseMemoryBind_array_win32_to_host(ctx, (const VkSparseMemoryBind32 *)UlongToPtr(in->pBinds), in->bindCount); }
+#ifdef _WIN64 +static inline const VkSparseImageOpaqueMemoryBindInfo *convert_VkSparseImageOpaqueMemoryBindInfo_array_win64_to_host(struct conversion_context *ctx, const VkSparseImageOpaqueMemoryBindInfo *in, uint32_t count) +{ + VkSparseImageOpaqueMemoryBindInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkSparseImageOpaqueMemoryBindInfo_win64_to_host(ctx, &in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkSparseImageOpaqueMemoryBindInfo *convert_VkSparseImageOpaqueMemoryBindInfo_array_win32_to_host(struct conversion_context *ctx, const VkSparseImageOpaqueMemoryBindInfo32 *in, uint32_t count) { VkSparseImageOpaqueMemoryBindInfo *out; @@ -23997,6 +24225,20 @@ static inline const VkSparseImageOpaqueMemoryBindInfo *convert_VkSparseImageOpaq return out; }
+#ifdef _WIN64 +static inline void convert_VkSparseImageMemoryBind_win64_to_host(const VkSparseImageMemoryBind *in, VkSparseImageMemoryBind *out) +{ + if (!in) return; + + out->subresource = in->subresource; + out->offset = in->offset; + out->extent = in->extent; + out->memory = in->memory ? wine_device_memory_from_handle(in->memory)->memory : 0; + out->memoryOffset = in->memoryOffset; + out->flags = in->flags; +} +#endif /* _WIN64 */ + static inline void convert_VkSparseImageMemoryBind_win32_to_host(const VkSparseImageMemoryBind32 *in, VkSparseImageMemoryBind *out) { if (!in) return; @@ -24004,11 +24246,29 @@ static inline void convert_VkSparseImageMemoryBind_win32_to_host(const VkSparseI out->subresource = in->subresource; out->offset = in->offset; out->extent = in->extent; - out->memory = in->memory; + out->memory = in->memory ? wine_device_memory_from_handle(in->memory)->memory : 0; out->memoryOffset = in->memoryOffset; out->flags = in->flags; }
+#ifdef _WIN64 +static inline const VkSparseImageMemoryBind *convert_VkSparseImageMemoryBind_array_win64_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBind *in, uint32_t count) +{ + VkSparseImageMemoryBind *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkSparseImageMemoryBind_win64_to_host(&in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkSparseImageMemoryBind *convert_VkSparseImageMemoryBind_array_win32_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBind32 *in, uint32_t count) { VkSparseImageMemoryBind *out; @@ -24025,6 +24285,17 @@ static inline const VkSparseImageMemoryBind *convert_VkSparseImageMemoryBind_arr return out; }
+#ifdef _WIN64 +static inline void convert_VkSparseImageMemoryBindInfo_win64_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBindInfo *in, VkSparseImageMemoryBindInfo *out) +{ + if (!in) return; + + out->image = in->image; + out->bindCount = in->bindCount; + out->pBinds = convert_VkSparseImageMemoryBind_array_win64_to_host(ctx, in->pBinds, in->bindCount); +} +#endif /* _WIN64 */ + static inline void convert_VkSparseImageMemoryBindInfo_win32_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBindInfo32 *in, VkSparseImageMemoryBindInfo *out) { if (!in) return; @@ -24034,6 +24305,24 @@ static inline void convert_VkSparseImageMemoryBindInfo_win32_to_host(struct conv out->pBinds = convert_VkSparseImageMemoryBind_array_win32_to_host(ctx, (const VkSparseImageMemoryBind32 *)UlongToPtr(in->pBinds), in->bindCount); }
+#ifdef _WIN64 +static inline const VkSparseImageMemoryBindInfo *convert_VkSparseImageMemoryBindInfo_array_win64_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBindInfo *in, uint32_t count) +{ + VkSparseImageMemoryBindInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkSparseImageMemoryBindInfo_win64_to_host(ctx, &in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkSparseImageMemoryBindInfo *convert_VkSparseImageMemoryBindInfo_array_win32_to_host(struct conversion_context *ctx, const VkSparseImageMemoryBindInfo32 *in, uint32_t count) { VkSparseImageMemoryBindInfo *out; @@ -24050,6 +24339,26 @@ static inline const VkSparseImageMemoryBindInfo *convert_VkSparseImageMemoryBind return out; }
+#ifdef _WIN64 +static inline void convert_VkBindSparseInfo_win64_to_host(struct conversion_context *ctx, const VkBindSparseInfo *in, VkBindSparseInfo *out) +{ + if (!in) return; + + out->sType = in->sType; + out->pNext = in->pNext; + out->waitSemaphoreCount = in->waitSemaphoreCount; + out->pWaitSemaphores = in->pWaitSemaphores; + out->bufferBindCount = in->bufferBindCount; + out->pBufferBinds = convert_VkSparseBufferMemoryBindInfo_array_win64_to_host(ctx, in->pBufferBinds, in->bufferBindCount); + out->imageOpaqueBindCount = in->imageOpaqueBindCount; + out->pImageOpaqueBinds = convert_VkSparseImageOpaqueMemoryBindInfo_array_win64_to_host(ctx, in->pImageOpaqueBinds, in->imageOpaqueBindCount); + out->imageBindCount = in->imageBindCount; + out->pImageBinds = convert_VkSparseImageMemoryBindInfo_array_win64_to_host(ctx, in->pImageBinds, in->imageBindCount); + out->signalSemaphoreCount = in->signalSemaphoreCount; + out->pSignalSemaphores = in->pSignalSemaphores; +} +#endif /* _WIN64 */ + static inline void convert_VkBindSparseInfo_win32_to_host(struct conversion_context *ctx, const VkBindSparseInfo32 *in, VkBindSparseInfo *out) { const VkBaseInStructure32 *in_header; @@ -24107,6 +24416,24 @@ static inline void convert_VkBindSparseInfo_win32_to_host(struct conversion_cont } }
+#ifdef _WIN64 +static inline const VkBindSparseInfo *convert_VkBindSparseInfo_array_win64_to_host(struct conversion_context *ctx, const VkBindSparseInfo *in, uint32_t count) +{ + VkBindSparseInfo *out; + unsigned int i; + + if (!in || !count) return NULL; + + out = conversion_context_alloc(ctx, count * sizeof(*out)); + for (i = 0; i < count; i++) + { + convert_VkBindSparseInfo_win64_to_host(ctx, &in[i], &out[i]); + } + + return out; +} +#endif /* _WIN64 */ + static inline const VkBindSparseInfo *convert_VkBindSparseInfo_array_win32_to_host(struct conversion_context *ctx, const VkBindSparseInfo32 *in, uint32_t count) { VkBindSparseInfo *out; @@ -24945,7 +25272,7 @@ static NTSTATUS thunk64_vkAllocateMemory(void *args)
TRACE("%p, %p, %p, %p\n", params->device, params->pAllocateInfo, params->pAllocator, params->pMemory);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkAllocateMemory(wine_device_from_handle(params->device)->device, params->pAllocateInfo, NULL, params->pMemory); + params->result = wine_vkAllocateMemory(params->device, params->pAllocateInfo, params->pAllocator, params->pMemory); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -24967,7 +25294,7 @@ static NTSTATUS thunk32_vkAllocateMemory(void *args)
init_conversion_context(&ctx); convert_VkMemoryAllocateInfo_win32_to_host(&ctx, (const VkMemoryAllocateInfo32 *)UlongToPtr(params->pAllocateInfo), &pAllocateInfo_host); - params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkAllocateMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, &pAllocateInfo_host, NULL, (VkDeviceMemory *)UlongToPtr(params->pMemory)); + params->result = wine_vkAllocateMemory((VkDevice)UlongToPtr(params->device), &pAllocateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), (VkDeviceMemory *)UlongToPtr(params->pMemory)); free_conversion_context(&ctx); return STATUS_SUCCESS; } @@ -25008,10 +25335,15 @@ static NTSTATUS thunk32_vkBeginCommandBuffer(void *args) static NTSTATUS thunk64_vkBindAccelerationStructureMemoryNV(void *args) { struct vkBindAccelerationStructureMemoryNV_params *params = args; + const VkBindAccelerationStructureMemoryInfoNV *pBindInfos_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->bindInfoCount, params->pBindInfos);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindAccelerationStructureMemoryNV(wine_device_from_handle(params->device)->device, params->bindInfoCount, params->pBindInfos); + init_conversion_context(&ctx); + pBindInfos_host = convert_VkBindAccelerationStructureMemoryInfoNV_array_win64_to_host(&ctx, params->pBindInfos, params->bindInfoCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindAccelerationStructureMemoryNV(wine_device_from_handle(params->device)->device, params->bindInfoCount, pBindInfos_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25044,7 +25376,7 @@ static NTSTATUS thunk64_vkBindBufferMemory(void *args)
TRACE("%p, 0x%s, 0x%s, 0x%s\n", params->device, wine_dbgstr_longlong(params->buffer), wine_dbgstr_longlong(params->memory), wine_dbgstr_longlong(params->memoryOffset));
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory(wine_device_from_handle(params->device)->device, params->buffer, params->memory, params->memoryOffset); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory(wine_device_from_handle(params->device)->device, params->buffer, wine_device_memory_from_handle(params->memory)->memory, params->memoryOffset); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25062,7 +25394,7 @@ static NTSTATUS thunk32_vkBindBufferMemory(void *args)
TRACE("%#x, 0x%s, 0x%s, 0x%s\n", params->device, wine_dbgstr_longlong(params->buffer), wine_dbgstr_longlong(params->memory), wine_dbgstr_longlong(params->memoryOffset));
- params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkBindBufferMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->buffer, params->memory, params->memoryOffset); + params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkBindBufferMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->buffer, wine_device_memory_from_handle(params->memory)->memory, params->memoryOffset); return STATUS_SUCCESS; }
@@ -25070,10 +25402,15 @@ static NTSTATUS thunk32_vkBindBufferMemory(void *args) static NTSTATUS thunk64_vkBindBufferMemory2(void *args) { struct vkBindBufferMemory2_params *params = args; + const VkBindBufferMemoryInfo *pBindInfos_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->bindInfoCount, params->pBindInfos);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory2(wine_device_from_handle(params->device)->device, params->bindInfoCount, params->pBindInfos); + init_conversion_context(&ctx); + pBindInfos_host = convert_VkBindBufferMemoryInfo_array_win64_to_host(&ctx, params->pBindInfos, params->bindInfoCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory2(wine_device_from_handle(params->device)->device, params->bindInfoCount, pBindInfos_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25103,10 +25440,15 @@ static NTSTATUS thunk32_vkBindBufferMemory2(void *args) static NTSTATUS thunk64_vkBindBufferMemory2KHR(void *args) { struct vkBindBufferMemory2KHR_params *params = args; + const VkBindBufferMemoryInfo *pBindInfos_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->bindInfoCount, params->pBindInfos);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory2KHR(wine_device_from_handle(params->device)->device, params->bindInfoCount, params->pBindInfos); + init_conversion_context(&ctx); + pBindInfos_host = convert_VkBindBufferMemoryInfo_array_win64_to_host(&ctx, params->pBindInfos, params->bindInfoCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindBufferMemory2KHR(wine_device_from_handle(params->device)->device, params->bindInfoCount, pBindInfos_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25139,7 +25481,7 @@ static NTSTATUS thunk64_vkBindImageMemory(void *args)
TRACE("%p, 0x%s, 0x%s, 0x%s\n", params->device, wine_dbgstr_longlong(params->image), wine_dbgstr_longlong(params->memory), wine_dbgstr_longlong(params->memoryOffset));
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory(wine_device_from_handle(params->device)->device, params->image, params->memory, params->memoryOffset); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory(wine_device_from_handle(params->device)->device, params->image, wine_device_memory_from_handle(params->memory)->memory, params->memoryOffset); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25157,7 +25499,7 @@ static NTSTATUS thunk32_vkBindImageMemory(void *args)
TRACE("%#x, 0x%s, 0x%s, 0x%s\n", params->device, wine_dbgstr_longlong(params->image), wine_dbgstr_longlong(params->memory), wine_dbgstr_longlong(params->memoryOffset));
- params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkBindImageMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->image, params->memory, params->memoryOffset); + params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkBindImageMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->image, wine_device_memory_from_handle(params->memory)->memory, params->memoryOffset); return STATUS_SUCCESS; }
@@ -25165,10 +25507,15 @@ static NTSTATUS thunk32_vkBindImageMemory(void *args) static NTSTATUS thunk64_vkBindImageMemory2(void *args) { struct vkBindImageMemory2_params *params = args; + const VkBindImageMemoryInfo *pBindInfos_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->bindInfoCount, params->pBindInfos);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory2(wine_device_from_handle(params->device)->device, params->bindInfoCount, params->pBindInfos); + init_conversion_context(&ctx); + pBindInfos_host = convert_VkBindImageMemoryInfo_array_win64_to_host(&ctx, params->pBindInfos, params->bindInfoCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory2(wine_device_from_handle(params->device)->device, params->bindInfoCount, pBindInfos_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -25198,10 +25545,15 @@ static NTSTATUS thunk32_vkBindImageMemory2(void *args) static NTSTATUS thunk64_vkBindImageMemory2KHR(void *args) { struct vkBindImageMemory2KHR_params *params = args; + const VkBindImageMemoryInfo *pBindInfos_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->bindInfoCount, params->pBindInfos);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory2KHR(wine_device_from_handle(params->device)->device, params->bindInfoCount, params->pBindInfos); + init_conversion_context(&ctx); + pBindInfos_host = convert_VkBindImageMemoryInfo_array_win64_to_host(&ctx, params->pBindInfos, params->bindInfoCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkBindImageMemory2KHR(wine_device_from_handle(params->device)->device, params->bindInfoCount, pBindInfos_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -35002,10 +35354,15 @@ static NTSTATUS thunk32_vkEnumeratePhysicalDevices(void *args) static NTSTATUS thunk64_vkFlushMappedMemoryRanges(void *args) { struct vkFlushMappedMemoryRanges_params *params = args; + const VkMappedMemoryRange *pMemoryRanges_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->memoryRangeCount, params->pMemoryRanges);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkFlushMappedMemoryRanges(wine_device_from_handle(params->device)->device, params->memoryRangeCount, params->pMemoryRanges); + init_conversion_context(&ctx); + pMemoryRanges_host = convert_VkMappedMemoryRange_array_win64_to_host(&ctx, params->pMemoryRanges, params->memoryRangeCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkFlushMappedMemoryRanges(wine_device_from_handle(params->device)->device, params->memoryRangeCount, pMemoryRanges_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -35100,7 +35457,7 @@ static NTSTATUS thunk64_vkFreeMemory(void *args)
TRACE("%p, 0x%s, %p\n", params->device, wine_dbgstr_longlong(params->memory), params->pAllocator);
- wine_device_from_handle(params->device)->funcs.p_vkFreeMemory(wine_device_from_handle(params->device)->device, params->memory, NULL); + wine_vkFreeMemory(params->device, params->memory, params->pAllocator); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -35116,7 +35473,7 @@ static NTSTATUS thunk32_vkFreeMemory(void *args)
TRACE("%#x, 0x%s, %#x\n", params->device, wine_dbgstr_longlong(params->memory), params->pAllocator);
- wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkFreeMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->memory, NULL); + wine_vkFreeMemory((VkDevice)UlongToPtr(params->device), params->memory, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator)); return STATUS_SUCCESS; }
@@ -36262,7 +36619,7 @@ static NTSTATUS thunk64_vkGetDeviceMemoryCommitment(void *args)
TRACE("%p, 0x%s, %p\n", params->device, wine_dbgstr_longlong(params->memory), params->pCommittedMemoryInBytes);
- wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryCommitment(wine_device_from_handle(params->device)->device, params->memory, params->pCommittedMemoryInBytes); + wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryCommitment(wine_device_from_handle(params->device)->device, wine_device_memory_from_handle(params->memory)->memory, params->pCommittedMemoryInBytes); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -36278,7 +36635,7 @@ static NTSTATUS thunk32_vkGetDeviceMemoryCommitment(void *args)
TRACE("%#x, 0x%s, %#x\n", params->device, wine_dbgstr_longlong(params->memory), params->pCommittedMemoryInBytes);
- wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkGetDeviceMemoryCommitment(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->memory, (VkDeviceSize *)UlongToPtr(params->pCommittedMemoryInBytes)); + wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkGetDeviceMemoryCommitment(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, wine_device_memory_from_handle(params->memory)->memory, (VkDeviceSize *)UlongToPtr(params->pCommittedMemoryInBytes)); return STATUS_SUCCESS; }
@@ -36286,10 +36643,12 @@ static NTSTATUS thunk32_vkGetDeviceMemoryCommitment(void *args) static NTSTATUS thunk64_vkGetDeviceMemoryOpaqueCaptureAddress(void *args) { struct vkGetDeviceMemoryOpaqueCaptureAddress_params *params = args; + VkDeviceMemoryOpaqueCaptureAddressInfo pInfo_host;
TRACE("%p, %p\n", params->device, params->pInfo);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryOpaqueCaptureAddress(wine_device_from_handle(params->device)->device, params->pInfo); + convert_VkDeviceMemoryOpaqueCaptureAddressInfo_win64_to_host(params->pInfo, &pInfo_host); + params->result = wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryOpaqueCaptureAddress(wine_device_from_handle(params->device)->device, &pInfo_host); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -36315,10 +36674,12 @@ static NTSTATUS thunk32_vkGetDeviceMemoryOpaqueCaptureAddress(void *args) static NTSTATUS thunk64_vkGetDeviceMemoryOpaqueCaptureAddressKHR(void *args) { struct vkGetDeviceMemoryOpaqueCaptureAddressKHR_params *params = args; + VkDeviceMemoryOpaqueCaptureAddressInfo pInfo_host;
TRACE("%p, %p\n", params->device, params->pInfo);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryOpaqueCaptureAddressKHR(wine_device_from_handle(params->device)->device, params->pInfo); + convert_VkDeviceMemoryOpaqueCaptureAddressInfo_win64_to_host(params->pInfo, &pInfo_host); + params->result = wine_device_from_handle(params->device)->funcs.p_vkGetDeviceMemoryOpaqueCaptureAddressKHR(wine_device_from_handle(params->device)->device, &pInfo_host); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -39275,10 +39636,15 @@ static NTSTATUS thunk32_vkInitializePerformanceApiINTEL(void *args) static NTSTATUS thunk64_vkInvalidateMappedMemoryRanges(void *args) { struct vkInvalidateMappedMemoryRanges_params *params = args; + const VkMappedMemoryRange *pMemoryRanges_host; + struct conversion_context ctx;
TRACE("%p, %u, %p\n", params->device, params->memoryRangeCount, params->pMemoryRanges);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkInvalidateMappedMemoryRanges(wine_device_from_handle(params->device)->device, params->memoryRangeCount, params->pMemoryRanges); + init_conversion_context(&ctx); + pMemoryRanges_host = convert_VkMappedMemoryRange_array_win64_to_host(&ctx, params->pMemoryRanges, params->memoryRangeCount); + params->result = wine_device_from_handle(params->device)->funcs.p_vkInvalidateMappedMemoryRanges(wine_device_from_handle(params->device)->device, params->memoryRangeCount, pMemoryRanges_host); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -39425,10 +39791,15 @@ static NTSTATUS thunk32_vkQueueBeginDebugUtilsLabelEXT(void *args) static NTSTATUS thunk64_vkQueueBindSparse(void *args) { struct vkQueueBindSparse_params *params = args; + const VkBindSparseInfo *pBindInfo_host; + struct conversion_context ctx;
TRACE("%p, %u, %p, 0x%s\n", params->queue, params->bindInfoCount, params->pBindInfo, wine_dbgstr_longlong(params->fence));
- params->result = wine_queue_from_handle(params->queue)->device->funcs.p_vkQueueBindSparse(wine_queue_from_handle(params->queue)->queue, params->bindInfoCount, params->pBindInfo, params->fence); + init_conversion_context(&ctx); + pBindInfo_host = convert_VkBindSparseInfo_array_win64_to_host(&ctx, params->pBindInfo, params->bindInfoCount); + params->result = wine_queue_from_handle(params->queue)->device->funcs.p_vkQueueBindSparse(wine_queue_from_handle(params->queue)->queue, params->bindInfoCount, pBindInfo_host, params->fence); + free_conversion_context(&ctx); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -40025,7 +40396,7 @@ static NTSTATUS thunk64_vkSetDeviceMemoryPriorityEXT(void *args)
TRACE("%p, 0x%s, %f\n", params->device, wine_dbgstr_longlong(params->memory), params->priority);
- wine_device_from_handle(params->device)->funcs.p_vkSetDeviceMemoryPriorityEXT(wine_device_from_handle(params->device)->device, params->memory, params->priority); + wine_device_from_handle(params->device)->funcs.p_vkSetDeviceMemoryPriorityEXT(wine_device_from_handle(params->device)->device, wine_device_memory_from_handle(params->memory)->memory, params->priority); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -40041,7 +40412,7 @@ static NTSTATUS thunk32_vkSetDeviceMemoryPriorityEXT(void *args)
TRACE("%#x, 0x%s, %f\n", params->device, wine_dbgstr_longlong(params->memory), params->priority);
- wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkSetDeviceMemoryPriorityEXT(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->memory, params->priority); + wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkSetDeviceMemoryPriorityEXT(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, wine_device_memory_from_handle(params->memory)->memory, params->priority); return STATUS_SUCCESS; }
@@ -40314,7 +40685,7 @@ static NTSTATUS thunk64_vkUnmapMemory(void *args)
TRACE("%p, 0x%s\n", params->device, wine_dbgstr_longlong(params->memory));
- wine_device_from_handle(params->device)->funcs.p_vkUnmapMemory(wine_device_from_handle(params->device)->device, params->memory); + wine_vkUnmapMemory(params->device, params->memory); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -40329,7 +40700,7 @@ static NTSTATUS thunk32_vkUnmapMemory(void *args)
TRACE("%#x, 0x%s\n", params->device, wine_dbgstr_longlong(params->memory));
- wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkUnmapMemory(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, params->memory); + wine_vkUnmapMemory((VkDevice)UlongToPtr(params->device), params->memory); return STATUS_SUCCESS; }
@@ -40895,6 +41266,7 @@ BOOL wine_vk_is_type_wrapped(VkObjectType type) type == VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT || type == VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT || type == VK_OBJECT_TYPE_DEVICE || + type == VK_OBJECT_TYPE_DEVICE_MEMORY || type == VK_OBJECT_TYPE_INSTANCE || type == VK_OBJECT_TYPE_PHYSICAL_DEVICE || type == VK_OBJECT_TYPE_QUEUE || diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 89f741ad062..b893f15a9f3 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -16,6 +16,7 @@
/* Functions for which we have custom implementations outside of the thunks. */ VkResult wine_vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) DECLSPEC_HIDDEN; +VkResult wine_vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) DECLSPEC_HIDDEN; VkResult wine_vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool, void *client_ptr) DECLSPEC_HIDDEN; VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) DECLSPEC_HIDDEN; VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) DECLSPEC_HIDDEN; @@ -36,6 +37,7 @@ VkResult wine_vkEnumeratePhysicalDeviceGroups(VkInstance instance, uint32_t *pPh VkResult wine_vkEnumeratePhysicalDeviceGroupsKHR(VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) DECLSPEC_HIDDEN; VkResult wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN; void wine_vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) DECLSPEC_HIDDEN; +void wine_vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; VkResult wine_vkGetCalibratedTimestampsEXT(VkDevice device, uint32_t timestampCount, const VkCalibratedTimestampInfoEXT *pTimestampInfos, uint64_t *pTimestamps, uint64_t *pMaxDeviation) DECLSPEC_HIDDEN; void wine_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) DECLSPEC_HIDDEN; void wine_vkGetDeviceQueue2(VkDevice device, const VkDeviceQueueInfo2 *pQueueInfo, VkQueue *pQueue) DECLSPEC_HIDDEN; @@ -51,6 +53,7 @@ VkResult wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice phys VkResult wine_vkGetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo, VkSurfaceCapabilities2KHR *pSurfaceCapabilities) DECLSPEC_HIDDEN; VkResult wine_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) DECLSPEC_HIDDEN; VkResult wine_vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) DECLSPEC_HIDDEN; +void wine_vkUnmapMemory(VkDevice device, VkDeviceMemory memory) DECLSPEC_HIDDEN;
/* For use by vkDevice and children */ struct vulkan_device_funcs
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/vulkan.c | 161 +++++++++++++++++++++++++++++-- dlls/winevulkan/vulkan_private.h | 4 + 2 files changed, 158 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index b092756fd4e..ccd2669dad1 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -31,6 +31,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
+static BOOL is_wow64(void) +{ + return sizeof(void *) == sizeof(UINT64) && NtCurrentTeb()->WowTebOffset; +} + +static BOOL use_external_memory(void) +{ + return is_wow64(); +} + +static ULONG_PTR zero_bits(void) +{ + return is_wow64() ? 0x7fffffff : 0; +} + #define wine_vk_count_struct(s, t) wine_vk_count_struct_((void *)s, VK_STRUCTURE_TYPE_##t) static uint32_t wine_vk_count_struct_(void *s, VkStructureType t) { @@ -227,6 +242,8 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance handle->base.unix_handle = (uintptr_t)object; WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, handle, phys_dev, object);
+ instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(phys_dev, &object->memory_properties); + res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev, NULL, &num_host_properties, NULL); if (res != VK_SUCCESS) @@ -264,6 +281,23 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance { TRACE("Skipping extension '%s', no implementation found in winevulkan.\n", host_properties[i].extensionName); } + if (use_external_memory() && !strcmp(host_properties[i].extensionName, "VK_EXT_external_memory_host")) + { + VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT, + }; + VkPhysicalDeviceProperties2 props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &host_mem_props, + }; + instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(phys_dev, &props); + object->external_memory_align = host_mem_props.minImportedHostPointerAlignment; + if (object->external_memory_align) + TRACE("Using eVK_EXT_external_memory_host for memory mapping with alignment: %u\n", + object->external_memory_align); + } }
TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties, num_properties); @@ -353,7 +387,8 @@ static void wine_vk_device_get_queues(struct wine_device *device, } }
-static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src, VkDeviceCreateInfo *dst) +static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_dev, + struct conversion_context *ctx, const VkDeviceCreateInfo *src, VkDeviceCreateInfo *dst) { unsigned int i;
@@ -375,6 +410,19 @@ static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src } }
+ if (phys_dev->external_memory_align) + { + const char **new_extensions; + + new_extensions = conversion_context_alloc(ctx, (dst->enabledExtensionCount + 2) * + sizeof(*dst->ppEnabledExtensionNames)); + memcpy(new_extensions, src->ppEnabledExtensionNames, + dst->enabledExtensionCount * sizeof(*dst->ppEnabledExtensionNames)); + new_extensions[dst->enabledExtensionCount++] = "VK_KHR_external_memory"; + new_extensions[dst->enabledExtensionCount++] = "VK_EXT_external_memory_host"; + dst->ppEnabledExtensionNames = new_extensions; + } + return VK_SUCCESS; }
@@ -447,8 +495,8 @@ NTSTATUS init_vulkan32(void *args) * This function takes care of extensions handled at winevulkan layer, a Wine graphics * driver is responsible for handling e.g. surface extensions. */ -static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo *src, - VkInstanceCreateInfo *dst, struct wine_instance *object) +static VkResult wine_vk_instance_convert_create_info(struct conversion_context *ctx, + const VkInstanceCreateInfo *src, VkInstanceCreateInfo *dst, struct wine_instance *object) { VkDebugUtilsMessengerCreateInfoEXT *debug_utils_messenger; VkDebugReportCallbackCreateInfoEXT *debug_report_callback; @@ -516,6 +564,19 @@ static VkResult wine_vk_instance_convert_create_info(const VkInstanceCreateInfo } }
+ if (use_external_memory()) + { + const char **new_extensions; + + new_extensions = conversion_context_alloc(ctx, (dst->enabledExtensionCount + 2) * + sizeof(*dst->ppEnabledExtensionNames)); + memcpy(new_extensions, src->ppEnabledExtensionNames, + dst->enabledExtensionCount * sizeof(*dst->ppEnabledExtensionNames)); + new_extensions[dst->enabledExtensionCount++] = "VK_KHR_get_physical_device_properties2"; + new_extensions[dst->enabledExtensionCount++] = "VK_KHR_external_memory_capabilities"; + dst->ppEnabledExtensionNames = new_extensions; + } + return VK_SUCCESS; }
@@ -689,6 +750,7 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre VkDeviceCreateInfo create_info_host; struct VkQueue_T *queue_handles; struct wine_queue *next_queue; + struct conversion_context ctx; struct wine_device *object; unsigned int i; VkResult res; @@ -712,10 +774,12 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre
object->phys_dev = phys_dev;
- res = wine_vk_device_convert_create_info(create_info, &create_info_host); + init_conversion_context(&ctx); + res = wine_vk_device_convert_create_info(phys_dev, &ctx, create_info, &create_info_host); if (res == VK_SUCCESS) res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev, &create_info_host, NULL /* allocator */, &object->device); + free_conversion_context(&ctx); WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev->instance, device_handle, object->device, object); if (res != VK_SUCCESS) { @@ -780,6 +844,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, VkInstance client_instance = client_ptr; VkInstanceCreateInfo create_info_host; const VkApplicationInfo *app_info; + struct conversion_context ctx; struct wine_instance *object; VkResult res;
@@ -794,9 +859,11 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, list_init(&object->wrappers); pthread_rwlock_init(&object->wrapper_lock, NULL);
- res = wine_vk_instance_convert_create_info(create_info, &create_info_host, object); + init_conversion_context(&ctx); + res = wine_vk_instance_convert_create_info(&ctx, create_info, &create_info_host, object); if (res == VK_SUCCESS) res = vk_funcs->p_vkCreateInstance(&create_info_host, NULL /* allocator */, &object->instance); + free_conversion_context(&ctx); if (res != VK_SUCCESS) { ERR("Failed to create instance, res=%d\n", res); @@ -1446,18 +1513,83 @@ VkResult wine_vkAllocateMemory(VkDevice handle, const VkMemoryAllocateInfo *allo { struct wine_device *device = wine_device_from_handle(handle); struct wine_device_memory *memory; + VkMemoryAllocateInfo info = *alloc_info; + VkImportMemoryHostPointerInfoEXT host_pointer_info; + uint32_t mem_flags; + void *mapping = NULL; VkResult result;
+ mem_flags = device->phys_dev->memory_properties.memoryTypes[alloc_info->memoryTypeIndex].propertyFlags; + if (device->phys_dev->external_memory_align && (mem_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && + !find_next_struct(alloc_info->pNext, VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT)) + { + VkMemoryHostPointerPropertiesEXT props = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT, + }; + uint32_t i, align = device->phys_dev->external_memory_align - 1; + SIZE_T alloc_size = info.allocationSize; + + if (NtAllocateVirtualMemory(GetCurrentProcess(), &mapping, zero_bits(), &alloc_size, + MEM_COMMIT, PAGE_READWRITE)) + { + ERR("NtAllocateVirtualMemory failed\n"); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + result = device->funcs.p_vkGetMemoryHostPointerPropertiesEXT(device->device, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT, mapping, &props); + if (result != VK_SUCCESS) + { + ERR("vkGetMemoryHostPointerPropertiesEXT failed: %d\n", result); + return result; + } + + if (!(props.memoryTypeBits & (1u << info.memoryTypeIndex))) + { + uint32_t mask = mem_flags & ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; + for (i = 0; i < device->phys_dev->memory_properties.memoryTypeCount; i++) + { + if (!(props.memoryTypeBits & (1u << i))) + continue; + if ((device->phys_dev->memory_properties.memoryTypes[i].propertyFlags & mask) != mask) + continue; + + TRACE("Memory type not compatible with host memory, using %u instead\n", i); + info.memoryTypeIndex = i; + break; + } + if (i == device->phys_dev->memory_properties.memoryTypeCount) + { + FIXME("Not found memory type compatible with requested memory type\n"); + alloc_size = 0; + NtFreeVirtualMemory(GetCurrentProcess(), &mapping, &alloc_size, MEM_RELEASE); + } + } + + if (props.memoryTypeBits & (1u << info.memoryTypeIndex)) + { + host_pointer_info.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT; + host_pointer_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + host_pointer_info.pHostPointer = mapping; + host_pointer_info.pNext = info.pNext; + info.pNext = &host_pointer_info; + + info.allocationSize = (info.allocationSize + align) & ~align; + } + } + if (!(memory = malloc(sizeof(*memory)))) return VK_ERROR_OUT_OF_HOST_MEMORY;
- result = device->funcs.p_vkAllocateMemory(device->device, alloc_info, NULL, &memory->memory); + result = device->funcs.p_vkAllocateMemory(device->device, &info, NULL, &memory->memory); if (result != VK_SUCCESS) { free(memory); return result; }
+ memory->mapping = mapping; *ret = (VkDeviceMemory)(uintptr_t)memory; return VK_SUCCESS; } @@ -1472,6 +1604,13 @@ void wine_vkFreeMemory(VkDevice handle, VkDeviceMemory memory_handle, const VkAl memory = wine_device_memory_from_handle(memory_handle);
device->funcs.p_vkFreeMemory(device->device, memory->memory, NULL); + + if (memory->mapping) + { + SIZE_T alloc_size = 0; + NtFreeVirtualMemory(GetCurrentProcess(), &memory->mapping, &alloc_size, MEM_RELEASE); + } + free(memory); }
@@ -1482,6 +1621,13 @@ VkResult wine_vkMapMemory(VkDevice handle, VkDeviceMemory memory_handle, VkDevic struct wine_device_memory *memory = wine_device_memory_from_handle(memory_handle); VkResult result;
+ if (memory->mapping) + { + *data = (char *)memory->mapping + offset; + TRACE("returning %p\n", *data); + return VK_SUCCESS; + } + result = device->funcs.p_vkMapMemory(device->device, memory->memory, offset, size, flags, data);
#ifdef _WIN64 @@ -1502,7 +1648,8 @@ void wine_vkUnmapMemory(VkDevice handle, VkDeviceMemory memory_handle) struct wine_device *device = wine_device_from_handle(handle); struct wine_device_memory *memory = wine_device_memory_from_handle(memory_handle);
- device->funcs.p_vkUnmapMemory(device->device, memory->memory); + if (!memory->mapping) + device->funcs.p_vkUnmapMemory(device->device, memory->memory); }
static inline void adjust_max_image_count(struct wine_phys_dev *phys_dev, VkSurfaceCapabilitiesKHR* capabilities) diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 8055b2380fd..92504bffb41 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -125,9 +125,12 @@ struct wine_phys_dev VkPhysicalDevice handle; /* client physical device */ VkPhysicalDevice phys_dev; /* native physical device */
+ VkPhysicalDeviceMemoryProperties memory_properties; VkExtensionProperties *extensions; uint32_t extension_count;
+ uint32_t external_memory_align; + struct wine_vk_mapping mapping; };
@@ -172,6 +175,7 @@ static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool hand struct wine_device_memory { VkDeviceMemory memory; + void *mapping; };
static inline struct wine_device_memory *wine_device_memory_from_handle(VkDeviceMemory handle)
From: Jacek Caban jacek@codeweavers.com
--- dlls/winevulkan/vulkan.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index ccd2669dad1..fc56620184d 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -38,7 +38,32 @@ static BOOL is_wow64(void)
static BOOL use_external_memory(void) { - return is_wow64(); + static int ret = -1; + + if (ret == -1) + { + const char *env; + if ((env = getenv("WINEVULKAN_EXTERNAL_MEMORY"))) + ret = *env && *env != '0'; + else ret = is_wow64(); + } + + return ret; +} + +static BOOL use_direct_unix_calls(void) +{ + static int ret = -1; + + if (ret == -1) + { + const char *env; + if ((env = getenv("WINEVULKAN_DIRECT_UNIX_CALLS"))) + ret = *env && *env != '0'; + else ret = !is_wow64(); + } + + return ret; }
static ULONG_PTR zero_bits(void) @@ -470,7 +495,8 @@ NTSTATUS init_vulkan(void *args) }
- *(void **)args = vk_direct_unix_call; + if (use_direct_unix_calls()) + *(void **)args = vk_direct_unix_call; return STATUS_SUCCESS; }
@@ -486,7 +512,8 @@ NTSTATUS init_vulkan32(void *args) }
#ifndef _WIN64 - *(void **)args = vk_direct_unix_call; + if (use_direct_unix_calls()) + *(void **)args = vk_direct_unix_call; #endif return STATUS_SUCCESS; }
The main problem of this MR is that it breaks Vulkan spec. The main rule it breaks is that according to spec, we should explicitly specify that we plan to use external memory when creating VkBuffer or VkImage. The problem is that we don't know if we will until we bind memory to the buffer. I tried some workarounds for that (delaying actual buffer creation, recreating buffer when needed). I got it mostly working and passing tests without validation errors, but it was more invasive than I'd like and still had other problems. I'd rather avoid that if possible.
For what it's worth, I think it's a bad idea to intentionally violate the Vulkan specification.
What makes the aforementioned workarounds ugly or difficult?
If this isn't going to expose optimal performance anyway (I at least think two games are not really enough to accurately measure a difference), I would assert that we should do something slow yet completely safe, like copy the whole buffer, as with GL.
Failing that, I'd just say it's not worth merging this. But then again, I suppose I also don't understand the rush to merge WoW64 upstream at any cost of performance or correctness, without first addressing those costs.