winevulkan: Use VK_EXT_map_memory_placed for memory mapping on wow64.

This commit is contained in:
Jacek Caban 2024-02-26 20:49:51 +01:00 committed by Alexandre Julliard
parent d8e0c8adea
commit 1999e4f3f5
2 changed files with 119 additions and 5 deletions

View file

@ -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,

View file

@ -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;