Module: wine Branch: master Commit: 1999e4f3f51c805a96e93fdf62bec0b200912229 URL: https://gitlab.winehq.org/wine/wine/-/commit/1999e4f3f51c805a96e93fdf62bec0b...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Feb 26 20:49:51 2024 +0100
winevulkan: Use VK_EXT_map_memory_placed for memory mapping on wow64.
---
dlls/winevulkan/vulkan.c | 122 +++++++++++++++++++++++++++++++++++++-- dlls/winevulkan/vulkan_private.h | 2 + 2 files changed, 119 insertions(+), 5 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 93a36f28469..0a6224476e2 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -223,6 +223,7 @@ static void wine_vk_physical_device_free(struct wine_phys_dev *phys_dev) static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance *instance, VkPhysicalDevice phys_dev, VkPhysicalDevice handle) { + BOOL have_memory_placed = FALSE, have_map_memory2 = FALSE; struct wine_phys_dev *object; uint32_t num_host_properties, num_properties = 0; VkExtensionProperties *host_properties = NULL; @@ -281,6 +282,10 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance } if (!strcmp(host_properties[i].extensionName, "VK_EXT_external_memory_host")) have_external_memory_host = TRUE; + else if (!strcmp(host_properties[i].extensionName, "VK_EXT_map_memory_placed")) + have_memory_placed = TRUE; + else if (!strcmp(host_properties[i].extensionName, "VK_KHR_map_memory2")) + have_map_memory2 = TRUE; }
TRACE("Host supported extensions %u, Wine supported extensions %u\n", num_host_properties, num_properties); @@ -301,7 +306,38 @@ 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) + if (zero_bits && have_memory_placed && have_map_memory2) + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT map_placed_feature = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT, + }; + VkPhysicalDeviceFeatures2 features = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .pNext = &map_placed_feature, + }; + + instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(phys_dev, &features); + if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) + { + VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT, + }; + VkPhysicalDeviceProperties2 props = + { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, + .pNext = &map_placed_props, + }; + + instance->funcs.p_vkGetPhysicalDeviceProperties2(phys_dev, &props); + object->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; + TRACE( "Using placed map with alignment %u\n", object->map_placed_align ); + } + } + + if (zero_bits && have_external_memory_host && !object->map_placed_align) { VkPhysicalDeviceExternalMemoryHostPropertiesEXT host_mem_props = { @@ -425,7 +461,23 @@ static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_de } }
- if (phys_dev->external_memory_align) + if (phys_dev->map_placed_align) + { + VkPhysicalDeviceMapMemoryPlacedFeaturesEXT *map_placed_features; + map_placed_features = conversion_context_alloc(ctx, sizeof(*map_placed_features)); + map_placed_features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_FEATURES_EXT; + map_placed_features->pNext = (void *)dst->pNext; + map_placed_features->memoryMapPlaced = VK_TRUE; + map_placed_features->memoryMapRangePlaced = VK_FALSE; + map_placed_features->memoryUnmapReserve = VK_TRUE; + dst->pNext = map_placed_features; + + if (!find_extension(extensions, extensions_count, "VK_EXT_map_memory_placed")) + extra_extensions[extra_count++] = "VK_EXT_map_memory_placed"; + if (!find_extension(extensions, extensions_count, "VK_KHR_map_memory2")) + extra_extensions[extra_count++] = "VK_KHR_map_memory2"; + } + else if (phys_dev->external_memory_align) { if (!find_extension(extensions, extensions_count, "VK_KHR_external_memory")) extra_extensions[extra_count++] = "VK_KHR_external_memory"; @@ -1721,6 +1773,7 @@ VkResult wine_vkAllocateMemory(VkDevice handle, const VkMemoryAllocateInfo *allo }
WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, memory, memory->host_memory, memory); + memory->size = info.allocationSize; memory->vm_map = mapping; *ret = (VkDeviceMemory)(uintptr_t)memory; return VK_SUCCESS; @@ -1735,6 +1788,17 @@ void wine_vkFreeMemory(VkDevice handle, VkDeviceMemory memory_handle, const VkAl return; memory = wine_device_memory_from_handle(memory_handle);
+ if (memory->vm_map && !device->phys_dev->external_memory_align) + { + const VkMemoryUnmapInfoKHR info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_UNMAP_INFO_KHR, + .memory = memory->host_memory, + .flags = VK_MEMORY_UNMAP_RESERVE_BIT_EXT, + }; + device->funcs.p_vkUnmapMemory2KHR(device->host_device, &info); + } + WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, memory); device->funcs.p_vkFreeMemory(device->host_device, memory->host_memory, NULL);
@@ -1767,6 +1831,10 @@ VkResult wine_vkMapMemory2KHR(VkDevice handle, const VkMemoryMapInfoKHR *map_inf struct wine_device *device = wine_device_from_handle(handle); struct wine_device_memory *memory = wine_device_memory_from_handle(map_info->memory); VkMemoryMapInfoKHR info = *map_info; + VkMemoryMapPlacedInfoEXT placed_info = + { + .sType = VK_STRUCTURE_TYPE_MEMORY_MAP_PLACED_INFO_EXT, + }; VkResult result;
info.memory = memory->host_memory; @@ -1777,6 +1845,24 @@ VkResult wine_vkMapMemory2KHR(VkDevice handle, const VkMemoryMapInfoKHR *map_inf return VK_SUCCESS; }
+ if (device->phys_dev->map_placed_align) + { + SIZE_T alloc_size = memory->size; + + placed_info.pNext = info.pNext; + info.pNext = &placed_info; + info.offset = 0; + info.size = VK_WHOLE_SIZE; + info.flags |= VK_MEMORY_MAP_PLACED_BIT_EXT; + + if (NtAllocateVirtualMemory(GetCurrentProcess(), &placed_info.pPlacedAddress, zero_bits, &alloc_size, + MEM_RESERVE, PAGE_READWRITE)) + { + ERR("NtAllocateVirtualMemory failed\n"); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + } + if (device->funcs.p_vkMapMemory2KHR) { result = device->funcs.p_vkMapMemory2KHR(device->host_device, &info, data); @@ -1788,6 +1874,20 @@ VkResult wine_vkMapMemory2KHR(VkDevice handle, const VkMemoryMapInfoKHR *map_inf info.size, info.flags, data); }
+ if (placed_info.pPlacedAddress) + { + if (result != VK_SUCCESS) + { + SIZE_T alloc_size = 0; + ERR("vkMapMemory2EXT failed: %d\n", result); + NtFreeVirtualMemory(GetCurrentProcess(), &placed_info.pPlacedAddress, &alloc_size, MEM_RELEASE); + return result; + } + memory->vm_map = placed_info.pPlacedAddress; + *data = (char *)memory->vm_map + map_info->offset; + TRACE("Using placed mapping %p\n", memory->vm_map); + } + #ifdef _WIN64 if (NtCurrentTeb()->WowTebOffset && result == VK_SUCCESS && (UINT_PTR)*data >> 32) { @@ -1817,20 +1917,32 @@ VkResult wine_vkUnmapMemory2KHR(VkDevice handle, const VkMemoryUnmapInfoKHR *unm struct wine_device *device = wine_device_from_handle(handle); struct wine_device_memory *memory = wine_device_memory_from_handle(unmap_info->memory); VkMemoryUnmapInfoKHR info; + VkResult result;
- if (memory->vm_map) + if (memory->vm_map && device->phys_dev->external_memory_align) return VK_SUCCESS;
if (!device->funcs.p_vkUnmapMemory2KHR) { - assert(!unmap_info->pNext); + assert(!unmap_info->pNext && !memory->vm_map); device->funcs.p_vkUnmapMemory(device->host_device, memory->host_memory); return VK_SUCCESS; }
info = *unmap_info; info.memory = memory->host_memory; - return device->funcs.p_vkUnmapMemory2KHR(device->host_device, &info); + if (memory->vm_map) + info.flags |= VK_MEMORY_UNMAP_RESERVE_BIT_EXT; + + result = device->funcs.p_vkUnmapMemory2KHR(device->host_device, &info); + + if (result == VK_SUCCESS && memory->vm_map) + { + SIZE_T size = 0; + NtFreeVirtualMemory(GetCurrentProcess(), &memory->vm_map, &size, MEM_RELEASE); + memory->vm_map = NULL; + } + return result; }
VkResult wine_vkCreateBuffer(VkDevice handle, const VkBufferCreateInfo *create_info, diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index fd5d58870cc..1697298a3d0 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -130,6 +130,7 @@ struct wine_phys_dev uint32_t extension_count;
uint32_t external_memory_align; + uint32_t map_placed_align;
struct wine_vk_mapping mapping; }; @@ -175,6 +176,7 @@ static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool hand struct wine_device_memory { VkDeviceMemory host_memory; + VkDeviceSize size; void *vm_map;
struct wine_vk_mapping mapping;