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.
-- v5: winevulkan: Use VK_EXT_external_memory_host extension to map memory on wow64. winevulkan: Wrap VkDeviceMemory. winevulkan: Don't try to unwrap missing optional handle struct members.
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 45418e362c5..e86c510c52f 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: @@ -1845,14 +1848,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 dad8991e095..2375ffa072b 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -23416,7 +23416,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 */
@@ -23426,7 +23426,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"); } @@ -38314,7 +38314,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 */ @@ -38332,7 +38332,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; }
@@ -38343,7 +38343,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 */ @@ -38361,7 +38361,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 e86c510c52f..ac158f84ad7 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 2375ffa072b..4de13aba8b9 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -6024,6 +6024,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: @@ -6425,6 +6427,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; @@ -6432,7 +6449,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); @@ -6440,6 +6457,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; @@ -6456,6 +6491,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; @@ -6466,7 +6514,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)) @@ -6492,6 +6540,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; @@ -6508,6 +6574,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; @@ -6518,7 +6597,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)) @@ -6569,6 +6648,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; @@ -16373,19 +16470,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; @@ -17039,13 +17167,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"); } @@ -23892,17 +24031,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; @@ -23919,6 +24089,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; @@ -23928,6 +24109,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; @@ -23944,6 +24143,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; @@ -23953,6 +24163,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; @@ -23969,6 +24197,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; @@ -23976,11 +24218,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; @@ -23997,6 +24257,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; @@ -24006,6 +24277,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; @@ -24022,6 +24311,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; @@ -24079,6 +24388,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; @@ -24917,7 +25244,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 */ @@ -24939,7 +25266,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; } @@ -24980,10 +25307,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 */ @@ -25016,7 +25348,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 */ @@ -25034,7 +25366,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; }
@@ -25042,10 +25374,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 */ @@ -25075,10 +25412,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 */ @@ -25111,7 +25453,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 */ @@ -25129,7 +25471,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; }
@@ -25137,10 +25479,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 */ @@ -25170,10 +25517,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 */ @@ -34974,10 +35326,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 */ @@ -35072,7 +35429,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 */ @@ -35088,7 +35445,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; }
@@ -36234,7 +36591,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 */ @@ -36250,7 +36607,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; }
@@ -36258,10 +36615,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 */ @@ -36287,10 +36646,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 */ @@ -39247,10 +39608,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 */ @@ -39397,10 +39763,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 */ @@ -39997,7 +40368,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 */ @@ -40013,7 +40384,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; }
@@ -40286,7 +40657,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 */ @@ -40301,7 +40672,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; }
@@ -40867,6 +41238,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/make_vulkan | 2 + dlls/winevulkan/vulkan.c | 211 ++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_private.h | 4 + dlls/winevulkan/vulkan_thunks.c | 8 +- dlls/winevulkan/vulkan_thunks.h | 2 + 5 files changed, 216 insertions(+), 11 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index ac158f84ad7..c1da9a05fc5 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -213,6 +213,8 @@ FUNCTION_OVERRIDES = { "vkFreeMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, "vkMapMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, "vkUnmapMemory" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, + "vkCreateBuffer" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE}, + "vkCreateImage" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.PRIVATE},
# VK_KHR_surface "vkDestroySurfaceKHR" : {"dispatch" : True, "driver" : True, "thunk" : ThunkType.NONE}, diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index b092756fd4e..3567e2f3e24 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) { @@ -214,6 +229,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance struct wine_phys_dev *object; uint32_t num_host_properties, num_properties = 0; VkExtensionProperties *host_properties = NULL; + BOOL have_external_memory_host = FALSE; VkResult res; unsigned int i, j;
@@ -227,6 +243,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 +282,8 @@ 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 (!strcmp(host_properties[i].extensionName, "VK_EXT_external_memory_host")) + have_external_memory_host = TRUE; }
TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties, num_properties); @@ -284,6 +304,24 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance } object->extension_count = num_properties;
+ if (use_external_memory() && have_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 VK_EXT_external_memory_host for memory mapping with alignment: %u\n", + object->external_memory_align); + } + free(host_properties); return object;
@@ -353,7 +391,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 +414,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 +499,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 +568,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 +754,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 +778,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 +848,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 +863,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 +1517,91 @@ 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;
+ /* For host visible memory, we try to use VK_EXT_external_memory_host on wow64 + * to ensure that mapped pointer is 32-bit. */ + 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; + static int once; + + if (!once++) + FIXME("Using VK_EXT_external_memory_host\n"); + + 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))) + { + /* If requested memory type is not allowed to use external memory, + * try to find a supported compatible type. */ + 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 compatible 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 +1616,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 +1633,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 +1660,46 @@ 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); +} + +VkResult wine_vkCreateBuffer(VkDevice handle, const VkBufferCreateInfo *create_info, + const VkAllocationCallbacks *allocator, VkBuffer *buffer) +{ + struct wine_device *device = wine_device_from_handle(handle); + VkExternalMemoryBufferCreateInfo external_memory_info; + VkBufferCreateInfo info = *create_info; + + if (device->phys_dev->external_memory_align && + !find_next_struct(info.pNext, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO)) + { + external_memory_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO; + external_memory_info.pNext = info.pNext; + external_memory_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + info.pNext = &external_memory_info; + } + + return device->funcs.p_vkCreateBuffer(device->device, &info, NULL, buffer); +} + +VkResult wine_vkCreateImage(VkDevice handle, const VkImageCreateInfo *create_info, + const VkAllocationCallbacks *allocator, VkImage *image) +{ + struct wine_device *device = wine_device_from_handle(handle); + VkExternalMemoryImageCreateInfo external_memory_info; + VkImageCreateInfo info = *create_info; + + if (device->phys_dev->external_memory_align && + !find_next_struct(info.pNext, VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO)) + { + external_memory_info.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO; + external_memory_info.pNext = info.pNext; + external_memory_info.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT; + info.pNext = &external_memory_info; + } + + return device->funcs.p_vkCreateImage(device->device, &info, NULL, image); }
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) diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index 4de13aba8b9..bb4efc6ea35 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -32414,7 +32414,7 @@ static NTSTATUS thunk64_vkCreateBuffer(void *args)
TRACE("%p, %p, %p, %p\n", params->device, params->pCreateInfo, params->pAllocator, params->pBuffer);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkCreateBuffer(wine_device_from_handle(params->device)->device, params->pCreateInfo, NULL, params->pBuffer); + params->result = wine_vkCreateBuffer(params->device, params->pCreateInfo, params->pAllocator, params->pBuffer); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -32436,7 +32436,7 @@ static NTSTATUS thunk32_vkCreateBuffer(void *args)
init_conversion_context(&ctx); convert_VkBufferCreateInfo_win32_to_host(&ctx, (const VkBufferCreateInfo32 *)UlongToPtr(params->pCreateInfo), &pCreateInfo_host); - params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkCreateBuffer(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, &pCreateInfo_host, NULL, (VkBuffer *)UlongToPtr(params->pBuffer)); + params->result = wine_vkCreateBuffer((VkDevice)UlongToPtr(params->device), &pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), (VkBuffer *)UlongToPtr(params->pBuffer)); free_conversion_context(&ctx); return STATUS_SUCCESS; } @@ -33025,7 +33025,7 @@ static NTSTATUS thunk64_vkCreateImage(void *args)
TRACE("%p, %p, %p, %p\n", params->device, params->pCreateInfo, params->pAllocator, params->pImage);
- params->result = wine_device_from_handle(params->device)->funcs.p_vkCreateImage(wine_device_from_handle(params->device)->device, params->pCreateInfo, NULL, params->pImage); + params->result = wine_vkCreateImage(params->device, params->pCreateInfo, params->pAllocator, params->pImage); return STATUS_SUCCESS; } #endif /* _WIN64 */ @@ -33047,7 +33047,7 @@ static NTSTATUS thunk32_vkCreateImage(void *args)
init_conversion_context(&ctx); convert_VkImageCreateInfo_win32_to_host(&ctx, (const VkImageCreateInfo32 *)UlongToPtr(params->pCreateInfo), &pCreateInfo_host); - params->result = wine_device_from_handle((VkDevice)UlongToPtr(params->device))->funcs.p_vkCreateImage(wine_device_from_handle((VkDevice)UlongToPtr(params->device))->device, &pCreateInfo_host, NULL, (VkImage *)UlongToPtr(params->pImage)); + params->result = wine_vkCreateImage((VkDevice)UlongToPtr(params->device), &pCreateInfo_host, (const VkAllocationCallbacks *)UlongToPtr(params->pAllocator), (VkImage *)UlongToPtr(params->pImage)); free_conversion_context(&ctx); return STATUS_SUCCESS; } diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index b893f15a9f3..e4b2ec6abf9 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -17,10 +17,12 @@ /* 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_vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) 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; VkResult wine_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, void *client_ptr) DECLSPEC_HIDDEN; +VkResult wine_vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) DECLSPEC_HIDDEN; VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance, void *client_ptr) DECLSPEC_HIDDEN; VkResult wine_vkCreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) DECLSPEC_HIDDEN; void wine_vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN;
I noticed that we should be fine and avoid spec violation by simply always declaring images and buffer as external host pointer compatible. Spec says that it means they may (not must) be used as a backing store. It's a bit weird and sub-optimal to do that and then bind them to device local only memory, but AFAICS it's not prohibited anywhere and fine with the spec.
What makes the aforementioned workarounds ugly or difficult?
A simple example is a typical buffer use in form of calls: (1) `vkCreateBuffer()`, (2) `vkGetBufferMemoryRequirements()`, (3) `vkAllocateMemory()`. Delaying is not enough because we need a handle for (2). If we re-create buffer in (3) we have no guarantees that the result of (2) is still valid (it's probably valid in practice, but implementation is free to return different requirements for host importable buffers).
Also, wrapping buffers/images means a lot more unwrapping code even for targets that don't need it. The number of required private thunks also quickly grows, meaning non-trivial future maintenance cost. This could be bearable if we didn't have a choice, but with VK_EXT_map_memory_placed on the horizon, I think it's valuable to keep fallback code path simple.
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.
I wouldn't call memcpy() solution safe. At very least because it would require quite invasive changes and memory coherency would be just broken. I would expect something like that to quickly get very ugly.
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.
I'm not sure what you're referring to. The MR was marked as a draft for a reason. And even if we had VK_EXT_map_memory_placed available tomorrow, having some fallback for existing drivers would still be interesting.
What makes the aforementioned workarounds ugly or difficult?
A simple example is a typical buffer use in form of calls: (1) `vkCreateBuffer()`, (2) `vkGetBufferMemoryRequirements()`, (3) `vkAllocateMemory()`. Delaying is not enough because we need a handle for (2). If we re-create buffer in (3) we have no guarantees that the result of (2) is still valid (it's probably valid in practice, but implementation is free to return different requirements for host importable buffers).
If we recreate the buffer in (3), recheck that the memory still meets the buffer requirements, and find that it doesn't, can we fall back to two buffers and a blit? Or return VK_ERROR_OUT_OF_HOST_MEMORY from vkBindBufferMemory()?
Also, wrapping buffers/images means a lot more unwrapping code even for targets that don't need it. The number of required private thunks also quickly grows, meaning non-trivial future maintenance cost. This could be bearable if we didn't have a choice, but with VK_EXT_map_memory_placed on the horizon, I think it's valuable to keep fallback code path simple.
Well, at a certain point I think the fallback code path has to just be "don't enumerate the device".
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.
I wouldn't call memcpy() solution safe. At very least because it would require quite invasive changes and memory coherency would be just broken. I would expect something like that to quickly get very ugly.
Hmm, well, it wouldn't necessarily be memcpy(), you could create a separate VkBuffer/VkMemory and blit. For coherency you'd presumably need to do an explicit blit command every time you do a draw or copy command. Granted, yes, this does get complicated.
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.
I'm not sure what you're referring to. The MR was marked as a draft for a reason. And even if we had VK_EXT_map_memory_placed available tomorrow, having some fallback for existing drivers would still be interesting.
Well, that's partly that it's not just this merge request that gives me that impression, partly because I didn't notice it was a draft (though I'm still unclear on what "draft" is supposed to mean with gitlab), and partly because the subject seems to imply that (except for the last patch) it's meant to be merged eventually anyway.
On Thu Dec 1 17:38:25 2022 +0000, Jacek Caban wrote:
I noticed that we should be fine and avoid spec violation by simply always declaring images and buffer as external host pointer compatible. Spec says that it means they may (not must) be used as a backing store. It's a bit weird and sub-optimal to do that and then bind them to device local only memory, but AFAICS it's not prohibited anywhere and fine with the spec.
I thought about suggesting this, but I thought it might end up either restricting memory requirements so as to make resources unusable, or else killing performance. Then again, thinking about it, if breaking the spec as the original version works (at least sometimes?) then maybe those aren't concerns.