-- v3: winevulkan: Get rid of the wine_vk_instance_free helper. winevulkan: Add handle mappings on creation success only. winevulkan: Simplify wine_vk_instance_free helper. winevulkan: Get rid of the wine_vk_device_free helper. winevulkan: Use a single allocation for instance and physical devices. winevulkan: Rename wine_vk_physical_device_alloc parameters and variables. winevulkan: Pass VkDeviceQueueCreateInfo to wine_vk_device_init_queues. winevulkan: Use a single allocation for device and queues. winevulkan: Use an rb_tree and allocate entries for handle mappings.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 135 +++++++++++++++---------------- dlls/winevulkan/vulkan_private.h | 34 ++++---- 2 files changed, 84 insertions(+), 85 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c8cb525929d..39ecf1698b2 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -61,48 +61,55 @@ static uint32_t wine_vk_count_struct_(void *s, VkStructureType t)
static const struct vulkan_funcs *vk_funcs;
-#define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, client_handle, host_handle, object) \ - wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (uintptr_t)(host_handle), &(object)->mapping) -#define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, client_handle, host_handle, object) \ - wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (host_handle), &(object)->mapping) -static void wine_vk_add_handle_mapping(struct wine_instance *instance, uint64_t wrapped_handle, - uint64_t host_handle, struct wine_vk_mapping *mapping) +static int wrapper_entry_compare(const void *key, const struct rb_entry *entry) +{ + struct wrapper_entry *wrapper = RB_ENTRY_VALUE(entry, struct wrapper_entry, entry); + const uint64_t *host_handle = key; + if (*host_handle < wrapper->host_handle) return -1; + if (*host_handle > wrapper->host_handle) return 1; + return 0; +} + +static void add_handle_mapping(struct wine_instance *instance, uint64_t client_handle, + uint64_t host_handle, struct wrapper_entry *entry) { if (instance->enable_wrapper_list) { - mapping->host_handle = host_handle; - mapping->wine_wrapped_handle = wrapped_handle; + entry->host_handle = host_handle; + entry->client_handle = client_handle; + pthread_rwlock_wrlock(&instance->wrapper_lock); - list_add_tail(&instance->wrappers, &mapping->link); + rb_put(&instance->wrappers, &host_handle, &entry->entry); pthread_rwlock_unlock(&instance->wrapper_lock); } }
-#define WINE_VK_REMOVE_HANDLE_MAPPING(instance, object) \ - wine_vk_remove_handle_mapping((instance), &(object)->mapping) -static void wine_vk_remove_handle_mapping(struct wine_instance *instance, struct wine_vk_mapping *mapping) +static void add_handle_mapping_ptr(struct wine_instance *instance, void *client_handle, + void *host_handle, struct wrapper_entry *entry) +{ + add_handle_mapping(instance, (uintptr_t)client_handle, (uintptr_t)host_handle, entry); +} + +static void remove_handle_mapping(struct wine_instance *instance, struct wrapper_entry *entry) { if (instance->enable_wrapper_list) { pthread_rwlock_wrlock(&instance->wrapper_lock); - list_remove(&mapping->link); + rb_remove(&instance->wrappers, &entry->entry); pthread_rwlock_unlock(&instance->wrapper_lock); } }
-static uint64_t wine_vk_get_wrapper(struct wine_instance *instance, uint64_t host_handle) +static uint64_t client_handle_from_host(struct wine_instance *instance, uint64_t host_handle) { - struct wine_vk_mapping *mapping; + struct rb_entry *entry; uint64_t result = 0;
pthread_rwlock_rdlock(&instance->wrapper_lock); - LIST_FOR_EACH_ENTRY(mapping, &instance->wrappers, struct wine_vk_mapping, link) + if ((entry = rb_get(&instance->wrappers, &host_handle))) { - if (mapping->host_handle == host_handle) - { - result = mapping->wine_wrapped_handle; - break; - } + struct wrapper_entry *wrapper = RB_ENTRY_VALUE(entry, struct wrapper_entry, entry); + result = wrapper->client_handle; } pthread_rwlock_unlock(&instance->wrapper_lock); return result; @@ -148,7 +155,7 @@ static VkBool32 debug_utils_callback_conversion(VkDebugUtilsMessageSeverityFlagB
if (wine_vk_is_type_wrapped(callback_data->pObjects[i].objectType)) { - object_name_infos[i].objectHandle = wine_vk_get_wrapper(object->instance, callback_data->pObjects[i].objectHandle); + object_name_infos[i].objectHandle = client_handle_from_host(object->instance, callback_data->pObjects[i].objectHandle); if (!object_name_infos[i].objectHandle) { WARN("handle conversion failed 0x%s\n", wine_dbgstr_longlong(callback_data->pObjects[i].objectHandle)); @@ -201,7 +208,7 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk params.layer_prefix = layer_prefix; params.message = message;
- params.object_handle = wine_vk_get_wrapper(object->instance, object_handle); + params.object_handle = client_handle_from_host(object->instance, object_handle); if (!params.object_handle) params.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
@@ -215,7 +222,7 @@ static void wine_vk_physical_device_free(struct wine_phys_dev *phys_dev) if (!phys_dev) return;
- WINE_VK_REMOVE_HANDLE_MAPPING(phys_dev->instance, phys_dev); + remove_handle_mapping(phys_dev->instance, &phys_dev->wrapper_entry); free(phys_dev->extensions); free(phys_dev); } @@ -239,7 +246,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance object->host_physical_device = phys_dev;
handle->base.unix_handle = (uintptr_t)object; - WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, handle, phys_dev, object); + add_handle_mapping_ptr(instance, handle, phys_dev, &object->wrapper_entry);
instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(phys_dev, &object->memory_properties);
@@ -378,7 +385,7 @@ static void wine_vk_free_command_buffers(struct wine_device *device,
device->funcs.p_vkFreeCommandBuffers(device->host_device, pool->host_command_pool, 1, &buffer->host_command_buffer); - WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, buffer); + remove_handle_mapping(device->phys_dev->instance, &buffer->wrapper_entry); buffer->handle->base.unix_handle = 0; free(buffer); } @@ -421,7 +428,7 @@ static void wine_vk_device_get_queues(struct wine_device *device, }
queue->handle->base.unix_handle = (uintptr_t)queue; - WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue->handle, queue->host_queue, queue); + add_handle_mapping_ptr(device->phys_dev->instance, queue->handle, queue->host_queue, &queue->wrapper_entry);
TRACE("Got device %p queue %p, host_queue %p.\n", device, queue, queue->host_queue); } @@ -516,7 +523,7 @@ static void wine_vk_device_free(struct wine_device *device) { queue = &device->queues[i]; if (queue && queue->host_queue) - WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, queue); + remove_handle_mapping(device->phys_dev->instance, &queue->wrapper_entry); } free(device->queues); device->queues = NULL; @@ -524,7 +531,7 @@ static void wine_vk_device_free(struct wine_device *device)
if (device->host_device && device->funcs.p_vkDestroyDevice) { - WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, device); + remove_handle_mapping(device->phys_dev->instance, &device->wrapper_entry); device->funcs.p_vkDestroyDevice(device->host_device, NULL /* pAllocator */); }
@@ -738,7 +745,7 @@ static void wine_vk_instance_free(struct wine_instance *instance) if (instance->host_instance) { vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); - WINE_VK_REMOVE_HANDLE_MAPPING(instance, instance); + remove_handle_mapping(instance, &instance->wrapper_entry); }
pthread_rwlock_destroy(&instance->wrapper_lock); @@ -783,7 +790,7 @@ VkResult wine_vkAllocateCommandBuffers(VkDevice handle, const VkCommandBufferAll res = device->funcs.p_vkAllocateCommandBuffers(device->host_device, &allocate_info_host, &buffer->host_command_buffer); buffer->handle->base.unix_handle = (uintptr_t)buffer; - WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, buffer->handle, buffer->host_command_buffer, buffer); + add_handle_mapping_ptr(device->phys_dev->instance, buffer->handle, buffer->host_command_buffer, &buffer->wrapper_entry); if (res != VK_SUCCESS) { ERR("Failed to allocate command buffer, res=%d.\n", res); @@ -838,7 +845,7 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre res = instance->funcs.p_vkCreateDevice(phys_dev->host_physical_device, &create_info_host, NULL /* allocator */, &object->host_device); free_conversion_context(&ctx); - WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, device_handle, object->host_device, object); + add_handle_mapping_ptr(instance, device_handle, object->host_device, &object->wrapper_entry); if (res != VK_SUCCESS) { WARN("Failed to create device, res=%d.\n", res); @@ -914,7 +921,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, ERR("Failed to allocate memory for instance\n"); return VK_ERROR_OUT_OF_HOST_MEMORY; } - list_init(&object->wrappers); + rb_init(&object->wrappers, wrapper_entry_compare); pthread_rwlock_init(&object->wrapper_lock, NULL);
init_conversion_context(&ctx); @@ -930,7 +937,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, }
object->handle = client_instance; - WINE_VK_ADD_DISPATCHABLE_MAPPING(object, object->handle, object->host_instance, object); + add_handle_mapping_ptr(object, object->handle, object->host_instance, &object->wrapper_entry);
/* Load all instance functions we are aware of. Note the loader takes care * of any filtering for extensions which were not requested, but which the @@ -1195,21 +1202,18 @@ VkResult wine_vkCreateCommandPool(VkDevice device_handle, const VkCommandPoolCre return VK_ERROR_OUT_OF_HOST_MEMORY;
res = device->funcs.p_vkCreateCommandPool(device->host_device, info, NULL, &object->host_command_pool); - - if (res == VK_SUCCESS) - { - object->handle = (uintptr_t)handle; - handle->unix_handle = (uintptr_t)object; - WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object->handle, - object->host_command_pool, object); - *command_pool = object->handle; - } - else + if (res != VK_SUCCESS) { free(object); + return res; }
- return res; + object->handle = (uintptr_t)handle; + handle->unix_handle = (uintptr_t)object; + + *command_pool = object->handle; + add_handle_mapping(device->phys_dev->instance, *command_pool, object->host_command_pool, &object->wrapper_entry); + return VK_SUCCESS; }
void wine_vkDestroyCommandPool(VkDevice device_handle, VkCommandPool handle, @@ -1221,8 +1225,7 @@ void wine_vkDestroyCommandPool(VkDevice device_handle, VkCommandPool handle, if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
- WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, pool); - + remove_handle_mapping(device->phys_dev->instance, &pool->wrapper_entry); device->funcs.p_vkDestroyCommandPool(device->host_device, pool->host_command_pool, NULL); free(pool); } @@ -1604,13 +1607,10 @@ VkResult wine_vkCreateWin32SurfaceKHR(VkInstance handle, const VkWin32SurfaceCre }
object->host_surface = vk_funcs->p_wine_get_host_surface(object->driver_surface); - WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->host_surface, object); - - *surface = wine_surface_to_handle(object); if (dummy) NtUserDestroyWindow(dummy);
*surface = wine_surface_to_handle(object); - + add_handle_mapping(instance, *surface, object->host_surface, &object->wrapper_entry); return VK_SUCCESS; }
@@ -1624,7 +1624,7 @@ void wine_vkDestroySurfaceKHR(VkInstance handle, VkSurfaceKHR surface, return;
instance->funcs.p_vkDestroySurfaceKHR(instance->host_instance, object->driver_surface, NULL); - WINE_VK_REMOVE_HANDLE_MAPPING(instance, object); + remove_handle_mapping(instance, &object->wrapper_entry);
free(object); } @@ -1666,10 +1666,9 @@ VkResult wine_vkCreateSwapchainKHR(VkDevice device_handle, const VkSwapchainCrea return res; }
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object, object->host_swapchain, object); *swapchain_handle = wine_swapchain_to_handle(object); - - return res; + add_handle_mapping(instance, *swapchain_handle, object->host_swapchain, &object->wrapper_entry); + return VK_SUCCESS; }
void wine_vkDestroySwapchainKHR(VkDevice device_handle, VkSwapchainKHR swapchain_handle, @@ -1682,7 +1681,7 @@ void wine_vkDestroySwapchainKHR(VkDevice device_handle, VkSwapchainKHR swapchain if (!swapchain) return;
device->funcs.p_vkDestroySwapchainKHR(device->host_device, swapchain->host_swapchain, NULL); - WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, swapchain); + remove_handle_mapping(device->phys_dev->instance, &swapchain->wrapper_entry);
free(swapchain); } @@ -1776,10 +1775,11 @@ VkResult wine_vkAllocateMemory(VkDevice handle, const VkMemoryAllocateInfo *allo return result; }
- 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; + add_handle_mapping(device->phys_dev->instance, *ret, memory->host_memory, &memory->wrapper_entry); return VK_SUCCESS; }
@@ -1803,7 +1803,7 @@ void wine_vkFreeMemory(VkDevice handle, VkDeviceMemory memory_handle, const VkAl device->funcs.p_vkUnmapMemory2KHR(device->host_device, &info); }
- WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, memory); + remove_handle_mapping(device->phys_dev->instance, &memory->wrapper_entry); device->funcs.p_vkFreeMemory(device->host_device, memory->host_memory, NULL);
if (memory->vm_map) @@ -2155,9 +2155,8 @@ VkResult wine_vkCreateDebugUtilsMessengerEXT(VkInstance handle, return res; }
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->host_debug_messenger, object); *messenger = wine_debug_utils_messenger_to_handle(object); - + add_handle_mapping(instance, *messenger, object->host_debug_messenger, &object->wrapper_entry); return VK_SUCCESS; }
@@ -2173,7 +2172,7 @@ void wine_vkDestroyDebugUtilsMessengerEXT(VkInstance handle, VkDebugUtilsMesseng return;
instance->funcs.p_vkDestroyDebugUtilsMessengerEXT(instance->host_instance, object->host_debug_messenger, NULL); - WINE_VK_REMOVE_HANDLE_MAPPING(instance, object); + remove_handle_mapping(instance, &object->wrapper_entry);
free(object); } @@ -2211,9 +2210,8 @@ VkResult wine_vkCreateDebugReportCallbackEXT(VkInstance handle, return res; }
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, object->host_debug_callback, object); *callback = wine_debug_report_callback_to_handle(object); - + add_handle_mapping(instance, *callback, object->host_debug_callback, &object->wrapper_entry); return VK_SUCCESS; }
@@ -2229,14 +2227,14 @@ void wine_vkDestroyDebugReportCallbackEXT(VkInstance handle, VkDebugReportCallba return;
instance->funcs.p_vkDestroyDebugReportCallbackEXT(instance->host_instance, object->host_debug_callback, NULL); - WINE_VK_REMOVE_HANDLE_MAPPING(instance, object); + remove_handle_mapping(instance, &object->wrapper_entry);
free(object); }
VkResult wine_vkCreateDeferredOperationKHR(VkDevice handle, const VkAllocationCallbacks* allocator, - VkDeferredOperationKHR* deferredOperation) + VkDeferredOperationKHR* operation) { struct wine_device *device = wine_device_from_handle(handle); struct wine_deferred_operation *object; @@ -2258,9 +2256,8 @@ VkResult wine_vkCreateDeferredOperationKHR(VkDevice handle,
init_conversion_context(&object->ctx);
- WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(device->phys_dev->instance, object, object->host_deferred_operation, object); - *deferredOperation = wine_deferred_operation_to_handle(object); - + *operation = wine_deferred_operation_to_handle(object); + add_handle_mapping(device->phys_dev->instance, *operation, object->host_deferred_operation, &object->wrapper_entry); return VK_SUCCESS; }
@@ -2277,7 +2274,7 @@ void wine_vkDestroyDeferredOperationKHR(VkDevice handle, return;
device->funcs.p_vkDestroyDeferredOperationKHR(device->host_device, object->host_deferred_operation, NULL); - WINE_VK_REMOVE_HANDLE_MAPPING(device->phys_dev->instance, object); + remove_handle_mapping(device->phys_dev->instance, &object->wrapper_entry);
free_conversion_context(&object->ctx); free(object); diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 94eecc5e5d5..7b1e24f3e56 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -28,14 +28,16 @@ #include "vulkan_loader.h" #include "vulkan_thunks.h"
+#include "wine/rbtree.h" + /* Some extensions have callbacks for those we need to be able to * get the wine wrapper for a host handle */ -struct wine_vk_mapping +struct wrapper_entry { - struct list link; + struct rb_entry entry; uint64_t host_handle; - uint64_t wine_wrapped_handle; + uint64_t client_handle; };
struct wine_cmd_buffer @@ -45,7 +47,7 @@ struct wine_cmd_buffer VkCommandBuffer handle; /* client command buffer */ VkCommandBuffer host_command_buffer;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_cmd_buffer *wine_cmd_buffer_from_handle(VkCommandBuffer handle) @@ -64,7 +66,7 @@ struct wine_device struct wine_queue *queues; uint32_t queue_count;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_device *wine_device_from_handle(VkDevice handle) @@ -83,7 +85,7 @@ struct wine_debug_report_callback PFN_vkDebugReportCallbackEXT user_callback; void *user_data;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
struct wine_instance @@ -101,7 +103,7 @@ struct wine_instance
VkBool32 enable_win32_surface; VkBool32 enable_wrapper_list; - struct list wrappers; + struct rb_tree wrappers; pthread_rwlock_t wrapper_lock;
struct wine_debug_utils_messenger *utils_messengers; @@ -111,7 +113,7 @@ struct wine_instance
unsigned int quirks;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_instance *wine_instance_from_handle(VkInstance handle) @@ -133,7 +135,7 @@ struct wine_phys_dev uint32_t external_memory_align; uint32_t map_placed_align;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_phys_dev *wine_phys_dev_from_handle(VkPhysicalDevice handle) @@ -152,7 +154,7 @@ struct wine_queue uint32_t queue_index; VkDeviceQueueCreateFlags flags;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_queue *wine_queue_from_handle(VkQueue handle) @@ -165,7 +167,7 @@ struct wine_cmd_pool VkCommandPool handle; VkCommandPool host_command_pool;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_cmd_pool *wine_cmd_pool_from_handle(VkCommandPool handle) @@ -180,7 +182,7 @@ struct wine_device_memory VkDeviceSize size; void *vm_map;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_device_memory *wine_device_memory_from_handle(VkDeviceMemory handle) @@ -197,7 +199,7 @@ struct wine_debug_utils_messenger PFN_vkDebugUtilsMessengerCallbackEXT user_callback; void *user_data;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_debug_utils_messenger *wine_debug_utils_messenger_from_handle( @@ -230,7 +232,7 @@ struct wine_surface VkSurfaceKHR driver_surface; HWND hwnd;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_surface *wine_surface_from_handle(VkSurfaceKHR handle) @@ -247,7 +249,7 @@ struct wine_swapchain { VkSwapchainKHR host_swapchain;
- struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_swapchain *wine_swapchain_from_handle(VkSwapchainKHR handle) @@ -314,7 +316,7 @@ struct wine_deferred_operation { VkDeferredOperationKHR host_deferred_operation; struct conversion_context ctx; /* to keep params alive. */ - struct wine_vk_mapping mapping; + struct wrapper_entry wrapper_entry; };
static inline struct wine_deferred_operation *wine_deferred_operation_from_handle(
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 38 ++++++++------------------ dlls/winevulkan/vulkan_private.h | 46 +++++++++++++++++--------------- 2 files changed, 35 insertions(+), 49 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 39ecf1698b2..a6169f4f824 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -511,22 +511,15 @@ static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_de */ static void wine_vk_device_free(struct wine_device *device) { - struct wine_queue *queue; + unsigned int i;
if (!device) return;
- if (device->queues) + for (i = 0; i < device->queue_count; i++) { - unsigned int i; - for (i = 0; i < device->queue_count; i++) - { - queue = &device->queues[i]; - if (queue && queue->host_queue) - remove_handle_mapping(device->phys_dev->instance, &queue->wrapper_entry); - } - free(device->queues); - device->queues = NULL; + struct wine_queue *queue = device->queues + i; + if (queue->host_queue) remove_handle_mapping(device->phys_dev->instance, &queue->wrapper_entry); }
if (device->host_device && device->funcs.p_vkDestroyDevice) @@ -817,7 +810,7 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre struct wine_queue *next_queue; struct conversion_context ctx; struct wine_device *object; - unsigned int i; + unsigned int queue_count, i; VkResult res;
if (allocator) @@ -834,7 +827,11 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre TRACE("Driver version: %#x.\n", properties.driverVersion); }
- if (!(object = calloc(1, sizeof(*object)))) + /* We need to cache all queues within the device as each requires wrapping since queues are dispatchable objects. */ + for (queue_count = 0, i = 0; i < create_info->queueCreateInfoCount; i++) + queue_count += create_info->pQueueCreateInfos[i].queueCount; + + if (!(object = calloc(1, offsetof(struct wine_device, queues[queue_count])))) return VK_ERROR_OUT_OF_HOST_MEMORY;
object->phys_dev = phys_dev; @@ -862,20 +859,6 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre ALL_VK_DEVICE_FUNCS() #undef USE_VK_FUNC
- /* We need to cache all queues within the device as each requires wrapping since queues are - * dispatchable objects. - */ - for (i = 0; i < create_info_host.queueCreateInfoCount; i++) - { - object->queue_count += create_info_host.pQueueCreateInfos[i].queueCount; - } - - if (!(object->queues = calloc(object->queue_count, sizeof(*object->queues)))) - { - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto fail; - } - next_queue = object->queues; queue_handles = device_handle->queues; for (i = 0; i < create_info_host.queueCreateInfoCount; i++) @@ -889,6 +872,7 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre wine_vk_device_get_queues(object, family_index, queue_count, flags, next_queue, &queue_handles); next_queue += queue_count; } + object->queue_count = next_queue - object->queues;
device_handle->quirks = instance->quirks; device_handle->base.unix_handle = (uintptr_t)object; diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 7b1e24f3e56..31e9e981168 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -55,6 +55,25 @@ static inline struct wine_cmd_buffer *wine_cmd_buffer_from_handle(VkCommandBuffe return (struct wine_cmd_buffer *)(uintptr_t)handle->base.unix_handle; }
+struct wine_queue +{ + struct wine_device *device; /* parent */ + + VkQueue handle; /* client queue */ + VkQueue host_queue; + + uint32_t family_index; + uint32_t queue_index; + VkDeviceQueueCreateFlags flags; + + struct wrapper_entry wrapper_entry; +}; + +static inline struct wine_queue *wine_queue_from_handle(VkQueue handle) +{ + return (struct wine_queue *)(uintptr_t)handle->base.unix_handle; +} + struct wine_device { struct vulkan_device_funcs funcs; @@ -63,12 +82,14 @@ struct wine_device VkDevice handle; /* client device */ VkDevice host_device;
- struct wine_queue *queues; - uint32_t queue_count; - struct wrapper_entry wrapper_entry; + + uint32_t queue_count; + struct wine_queue queues[]; };
+C_ASSERT(sizeof(struct wine_device) == offsetof(struct wine_device, queues[0])); + static inline struct wine_device *wine_device_from_handle(VkDevice handle) { return (struct wine_device *)(uintptr_t)handle->base.unix_handle; @@ -143,25 +164,6 @@ static inline struct wine_phys_dev *wine_phys_dev_from_handle(VkPhysicalDevice h return (struct wine_phys_dev *)(uintptr_t)handle->base.unix_handle; }
-struct wine_queue -{ - struct wine_device *device; /* parent */ - - VkQueue handle; /* client queue */ - VkQueue host_queue; - - uint32_t family_index; - uint32_t queue_index; - VkDeviceQueueCreateFlags flags; - - struct wrapper_entry wrapper_entry; -}; - -static inline struct wine_queue *wine_queue_from_handle(VkQueue handle) -{ - return (struct wine_queue *)(uintptr_t)handle->base.unix_handle; -} - struct wine_cmd_pool { VkCommandPool handle;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 41 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index a6169f4f824..995b059fd54 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -391,40 +391,41 @@ static void wine_vk_free_command_buffers(struct wine_device *device, } }
-static void wine_vk_device_get_queues(struct wine_device *device, - uint32_t family_index, uint32_t queue_count, VkDeviceQueueCreateFlags flags, - struct wine_queue *queues, VkQueue *handles) +static void wine_vk_device_init_queues(struct wine_device *device, const VkDeviceQueueCreateInfo *info, + VkQueue *handles) { VkDeviceQueueInfo2 queue_info; - unsigned int i; + UINT i; + + TRACE("Queue family index %u, queue count %u.\n", info->queueFamilyIndex, info->queueCount);
- for (i = 0; i < queue_count; i++) + for (i = 0; i < info->queueCount; i++) { - struct wine_queue *queue = &queues[i]; + struct wine_queue *queue = device->queues + device->queue_count + i;
queue->device = device; queue->handle = (*handles)++; - queue->family_index = family_index; + queue->family_index = info->queueFamilyIndex; queue->queue_index = i; - queue->flags = flags; + queue->flags = info->flags;
/* The Vulkan spec says: * * "vkGetDeviceQueue must only be used to get queues that were created * with the flags parameter of VkDeviceQueueCreateInfo set to zero." */ - if (flags && device->funcs.p_vkGetDeviceQueue2) + if (info->flags && device->funcs.p_vkGetDeviceQueue2) { queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; queue_info.pNext = NULL; - queue_info.flags = flags; - queue_info.queueFamilyIndex = family_index; + queue_info.flags = info->flags; + queue_info.queueFamilyIndex = info->queueFamilyIndex; queue_info.queueIndex = i; device->funcs.p_vkGetDeviceQueue2(device->host_device, &queue_info, &queue->host_queue); } else { - device->funcs.p_vkGetDeviceQueue(device->host_device, family_index, i, &queue->host_queue); + device->funcs.p_vkGetDeviceQueue(device->host_device, info->queueFamilyIndex, i, &queue->host_queue); }
queue->handle->base.unix_handle = (uintptr_t)queue; @@ -432,6 +433,8 @@ static void wine_vk_device_get_queues(struct wine_device *device,
TRACE("Got device %p queue %p, host_queue %p.\n", device, queue, queue->host_queue); } + + device->queue_count += info->queueCount; }
static const char *find_extension(const char *const *extensions, uint32_t count, const char *ext) @@ -807,7 +810,6 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre VkDevice device_handle = client_ptr; VkDeviceCreateInfo create_info_host; struct VkQueue_T *queue_handles; - struct wine_queue *next_queue; struct conversion_context ctx; struct wine_device *object; unsigned int queue_count, i; @@ -859,20 +861,9 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre ALL_VK_DEVICE_FUNCS() #undef USE_VK_FUNC
- next_queue = object->queues; queue_handles = device_handle->queues; for (i = 0; i < create_info_host.queueCreateInfoCount; i++) - { - uint32_t flags = create_info_host.pQueueCreateInfos[i].flags; - uint32_t family_index = create_info_host.pQueueCreateInfos[i].queueFamilyIndex; - uint32_t queue_count = create_info_host.pQueueCreateInfos[i].queueCount; - - TRACE("Queue family index %u, queue count %u.\n", family_index, queue_count); - - wine_vk_device_get_queues(object, family_index, queue_count, flags, next_queue, &queue_handles); - next_queue += queue_count; - } - object->queue_count = next_queue - object->queues; + wine_vk_device_init_queues(object, create_info_host.pQueueCreateInfos + i, &queue_handles);
device_handle->quirks = instance->quirks; device_handle->base.unix_handle = (uintptr_t)object;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 995b059fd54..6df610e7e36 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -228,7 +228,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) + VkPhysicalDevice host_handle, VkPhysicalDevice client_handle) { BOOL have_memory_placed = FALSE, have_map_memory2 = FALSE; struct wine_phys_dev *object; @@ -242,15 +242,15 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance return NULL;
object->instance = instance; - object->handle = handle; - object->host_physical_device = phys_dev; + object->handle = client_handle; + object->host_physical_device = host_handle;
- handle->base.unix_handle = (uintptr_t)object; - add_handle_mapping_ptr(instance, handle, phys_dev, &object->wrapper_entry); + client_handle->base.unix_handle = (uintptr_t)object; + add_handle_mapping_ptr(instance, client_handle, host_handle, &object->wrapper_entry);
- instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(phys_dev, &object->memory_properties); + instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(host_handle, &object->memory_properties);
- res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev, + res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(host_handle, NULL, &num_host_properties, NULL); if (res != VK_SUCCESS) { @@ -265,7 +265,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance goto err; }
- res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev, + res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(host_handle, NULL, &num_host_properties, host_properties); if (res != VK_SUCCESS) { @@ -325,7 +325,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance .pNext = &map_placed_feature, };
- instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(phys_dev, &features); + instance->funcs.p_vkGetPhysicalDeviceFeatures2KHR(host_handle, &features); if (map_placed_feature.memoryMapPlaced && map_placed_feature.memoryUnmapReserve) { VkPhysicalDeviceMapMemoryPlacedPropertiesEXT map_placed_props = @@ -338,7 +338,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance .pNext = &map_placed_props, };
- instance->funcs.p_vkGetPhysicalDeviceProperties2(phys_dev, &props); + instance->funcs.p_vkGetPhysicalDeviceProperties2(host_handle, &props); object->map_placed_align = map_placed_props.minPlacedMemoryMapAlignment; TRACE( "Using placed map with alignment %u\n", object->map_placed_align ); } @@ -355,7 +355,7 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .pNext = &host_mem_props, }; - instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(phys_dev, &props); + instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(host_handle, &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", @@ -645,7 +645,7 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * /* Helper function which stores wrapped physical devices in the instance object. */ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *instance) { - VkPhysicalDevice *tmp_phys_devs; + VkPhysicalDevice *host_handles; uint32_t phys_dev_count; unsigned int i; VkResult res; @@ -666,32 +666,32 @@ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *ins } instance->handle->phys_dev_count = phys_dev_count;
- if (!(tmp_phys_devs = calloc(phys_dev_count, sizeof(*tmp_phys_devs)))) + if (!(host_handles = calloc(phys_dev_count, sizeof(*host_handles)))) return VK_ERROR_OUT_OF_HOST_MEMORY;
- res = instance->funcs.p_vkEnumeratePhysicalDevices(instance->host_instance, &phys_dev_count, tmp_phys_devs); + res = instance->funcs.p_vkEnumeratePhysicalDevices(instance->host_instance, &phys_dev_count, host_handles); if (res != VK_SUCCESS) { - free(tmp_phys_devs); + free(host_handles); return res; }
instance->phys_devs = calloc(phys_dev_count, sizeof(*instance->phys_devs)); if (!instance->phys_devs) { - free(tmp_phys_devs); + free(host_handles); return VK_ERROR_OUT_OF_HOST_MEMORY; }
/* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ for (i = 0; i < phys_dev_count; i++) { - struct wine_phys_dev *phys_dev = wine_vk_physical_device_alloc(instance, tmp_phys_devs[i], + struct wine_phys_dev *phys_dev = wine_vk_physical_device_alloc(instance, host_handles[i], &instance->handle->phys_devs[i]); if (!phys_dev) { ERR("Unable to allocate memory for physical device!\n"); - free(tmp_phys_devs); + free(host_handles); return VK_ERROR_OUT_OF_HOST_MEMORY; }
@@ -700,22 +700,22 @@ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *ins } instance->phys_dev_count = phys_dev_count;
- free(tmp_phys_devs); + free(host_handles); return VK_SUCCESS; }
static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_instance *instance, - VkPhysicalDevice physical_device) + VkPhysicalDevice host_handle) { unsigned int i;
for (i = 0; i < instance->phys_dev_count; ++i) { struct wine_phys_dev *current = instance->phys_devs[i]; - if (current->host_physical_device == physical_device) return current; + if (current->host_physical_device == host_handle) return current; }
- ERR("Unrecognized physical device %p.\n", physical_device); + ERR("Unrecognized physical device %p.\n", host_handle); return NULL; }
@@ -1221,8 +1221,8 @@ static VkResult wine_vk_enumerate_physical_device_groups(struct wine_instance *i VkPhysicalDeviceGroupProperties *current = &properties[i]; for (j = 0; j < current->physicalDeviceCount; ++j) { - VkPhysicalDevice dev = current->physicalDevices[j]; - struct wine_phys_dev *phys_dev = wine_vk_instance_wrap_physical_device(instance, dev); + VkPhysicalDevice host_handle = current->physicalDevices[j]; + struct wine_phys_dev *phys_dev = wine_vk_instance_wrap_physical_device(instance, host_handle); if (!phys_dev) return VK_ERROR_INITIALIZATION_FAILED; current->physicalDevices[j] = phys_dev->handle;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 71 +++++++++++--------------------- dlls/winevulkan/vulkan_private.h | 58 +++++++++++++------------- 2 files changed, 54 insertions(+), 75 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 6df610e7e36..b2c386dbd2a 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -217,30 +217,22 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk return VK_FALSE; }
-static void wine_vk_physical_device_free(struct wine_phys_dev *phys_dev) +static void wine_phys_dev_cleanup(struct wine_phys_dev *phys_dev) { - if (!phys_dev) - return; - remove_handle_mapping(phys_dev->instance, &phys_dev->wrapper_entry); free(phys_dev->extensions); - free(phys_dev); }
-static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance *instance, - VkPhysicalDevice host_handle, VkPhysicalDevice client_handle) +static VkResult wine_vk_physical_device_init(struct wine_phys_dev *object, VkPhysicalDevice host_handle, + VkPhysicalDevice client_handle, struct wine_instance *instance) { 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; BOOL have_external_memory_host = FALSE; VkResult res; unsigned int i, j;
- if (!(object = calloc(1, sizeof(*object)))) - return NULL; - object->instance = instance; object->handle = client_handle; object->host_physical_device = host_handle; @@ -363,12 +355,12 @@ static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance }
free(host_properties); - return object; + return VK_SUCCESS;
err: - wine_vk_physical_device_free(object); + wine_phys_dev_cleanup(object); free(host_properties); - return NULL; + return res; }
static void wine_vk_free_command_buffers(struct wine_device *device, @@ -643,7 +635,7 @@ static VkResult wine_vk_instance_convert_create_info(struct conversion_context * }
/* Helper function which stores wrapped physical devices in the instance object. */ -static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *instance) +static VkResult wine_vk_instance_init_physical_devices(struct wine_instance *instance) { VkPhysicalDevice *host_handles; uint32_t phys_dev_count; @@ -676,32 +668,23 @@ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *ins return res; }
- instance->phys_devs = calloc(phys_dev_count, sizeof(*instance->phys_devs)); - if (!instance->phys_devs) - { - free(host_handles); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */ for (i = 0; i < phys_dev_count; i++) { - struct wine_phys_dev *phys_dev = wine_vk_physical_device_alloc(instance, host_handles[i], - &instance->handle->phys_devs[i]); - if (!phys_dev) - { - ERR("Unable to allocate memory for physical device!\n"); - free(host_handles); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - - instance->phys_devs[i] = phys_dev; - instance->phys_dev_count = i + 1; + struct wine_phys_dev *phys_dev = instance->phys_devs + i; + res = wine_vk_physical_device_init(phys_dev, host_handles[i], &instance->handle->phys_devs[i], instance); + if (res != VK_SUCCESS) + goto err; } instance->phys_dev_count = phys_dev_count;
free(host_handles); return VK_SUCCESS; + +err: + while (i) wine_phys_dev_cleanup(&instance->phys_devs[--i]); + free(host_handles); + return res; }
static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_instance *instance, @@ -711,7 +694,7 @@ static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_i
for (i = 0; i < instance->phys_dev_count; ++i) { - struct wine_phys_dev *current = instance->phys_devs[i]; + struct wine_phys_dev *current = instance->phys_devs + i; if (current->host_physical_device == host_handle) return current; }
@@ -724,19 +707,13 @@ static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_i */ static void wine_vk_instance_free(struct wine_instance *instance) { + unsigned int i; + if (!instance) return;
- if (instance->phys_devs) - { - unsigned int i; - - for (i = 0; i < instance->phys_dev_count; i++) - { - wine_vk_physical_device_free(instance->phys_devs[i]); - } - free(instance->phys_devs); - } + for (i = 0; i < instance->phys_dev_count; i++) + wine_phys_dev_cleanup(&instance->phys_devs[i]);
if (instance->host_instance) { @@ -891,7 +868,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
- if (!(object = calloc(1, sizeof(*object)))) + if (!(object = calloc(1, offsetof(struct wine_instance, phys_devs[client_instance->phys_dev_count])))) { ERR("Failed to allocate memory for instance\n"); return VK_ERROR_OUT_OF_HOST_MEMORY; @@ -928,7 +905,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, * the host physical devices and present those to the application. * Cleanup happens as part of wine_vkDestroyInstance. */ - res = wine_vk_instance_load_physical_devices(object); + res = wine_vk_instance_init_physical_devices(object); if (res != VK_SUCCESS) { ERR("Failed to load physical devices, res=%d\n", res); @@ -1102,7 +1079,7 @@ VkResult wine_vkEnumeratePhysicalDevices(VkInstance handle, uint32_t *count, VkP *count = min(*count, instance->phys_dev_count); for (i = 0; i < *count; i++) { - devices[i] = instance->phys_devs[i]->handle; + devices[i] = instance->phys_devs[i].handle; }
TRACE("Returning %u devices.\n", *count); diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 31e9e981168..f65b285e02a 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -109,6 +109,30 @@ struct wine_debug_report_callback struct wrapper_entry wrapper_entry; };
+struct wine_phys_dev +{ + struct wine_instance *instance; /* parent */ + + VkPhysicalDevice handle; /* client physical device */ + VkPhysicalDevice host_physical_device; + + VkPhysicalDeviceMemoryProperties memory_properties; + VkExtensionProperties *extensions; + uint32_t extension_count; + + uint32_t external_memory_align; + uint32_t map_placed_align; + + struct wrapper_entry wrapper_entry; +}; + +static inline struct wine_phys_dev *wine_phys_dev_from_handle(VkPhysicalDevice handle) +{ + return (struct wine_phys_dev *)(uintptr_t)handle->base.unix_handle; +} + +struct wine_debug_report_callback; + struct wine_instance { struct vulkan_instance_funcs funcs; @@ -116,12 +140,6 @@ struct wine_instance VkInstance handle; /* client instance */ VkInstance host_instance;
- /* We cache devices as we need to wrap them as they are - * dispatchable objects. - */ - struct wine_phys_dev **phys_devs; - uint32_t phys_dev_count; - VkBool32 enable_win32_surface; VkBool32 enable_wrapper_list; struct rb_tree wrappers; @@ -135,35 +153,19 @@ struct wine_instance unsigned int quirks;
struct wrapper_entry wrapper_entry; + + /* We cache devices as we need to wrap them as they are dispatchable objects. */ + uint32_t phys_dev_count; + struct wine_phys_dev phys_devs[]; };
+C_ASSERT(sizeof(struct wine_instance) == offsetof(struct wine_instance, phys_devs[0])); + static inline struct wine_instance *wine_instance_from_handle(VkInstance handle) { return (struct wine_instance *)(uintptr_t)handle->base.unix_handle; }
-struct wine_phys_dev -{ - struct wine_instance *instance; /* parent */ - - VkPhysicalDevice handle; /* client physical device */ - VkPhysicalDevice host_physical_device; - - VkPhysicalDeviceMemoryProperties memory_properties; - VkExtensionProperties *extensions; - uint32_t extension_count; - - uint32_t external_memory_align; - uint32_t map_placed_align; - - struct wrapper_entry wrapper_entry; -}; - -static inline struct wine_phys_dev *wine_phys_dev_from_handle(VkPhysicalDevice handle) -{ - return (struct wine_phys_dev *)(uintptr_t)handle->base.unix_handle; -} - struct wine_cmd_pool { VkCommandPool handle;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 43 +++++++++++----------------------------- 1 file changed, 12 insertions(+), 31 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index b2c386dbd2a..90ceb5e324d 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -501,31 +501,6 @@ static VkResult wine_vk_device_convert_create_info(struct wine_phys_dev *phys_de return VK_SUCCESS; }
-/* Helper function used for freeing a device structure. This function supports full - * and partial object cleanups and can thus be used for vkCreateDevice failures. - */ -static void wine_vk_device_free(struct wine_device *device) -{ - unsigned int i; - - if (!device) - return; - - for (i = 0; i < device->queue_count; i++) - { - struct wine_queue *queue = device->queues + i; - if (queue->host_queue) remove_handle_mapping(device->phys_dev->instance, &queue->wrapper_entry); - } - - if (device->host_device && device->funcs.p_vkDestroyDevice) - { - remove_handle_mapping(device->phys_dev->instance, &device->wrapper_entry); - device->funcs.p_vkDestroyDevice(device->host_device, NULL /* pAllocator */); - } - - free(device); -} - NTSTATUS init_vulkan(void *args) { vk_funcs = __wine_get_vulkan_driver(WINE_VULKAN_DRIVER_VERSION); @@ -825,7 +800,9 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre if (res != VK_SUCCESS) { WARN("Failed to create device, res=%d.\n", res); - goto fail; + remove_handle_mapping(object->phys_dev->instance, &object->wrapper_entry); + free(object); + return res; }
/* Just load all function pointers we are aware off. The loader takes care of filtering. @@ -848,10 +825,6 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre
TRACE("Created device %p, host_device %p.\n", object, object->host_device); return VK_SUCCESS; - -fail: - wine_vk_device_free(object); - return res; }
VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, @@ -935,11 +908,19 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, void wine_vkDestroyDevice(VkDevice handle, const VkAllocationCallbacks *allocator) { struct wine_device *device = wine_device_from_handle(handle); + unsigned int i;
if (allocator) FIXME("Support for allocation callbacks not implemented yet\n"); + if (!device) + return;
- wine_vk_device_free(device); + for (i = 0; i < device->queue_count; i++) + remove_handle_mapping(device->phys_dev->instance, &device->queues[i].wrapper_entry); + remove_handle_mapping(device->phys_dev->instance, &device->wrapper_entry); + device->funcs.p_vkDestroyDevice(device->host_device, NULL /* pAllocator */); + + free(device); }
void wine_vkDestroyInstance(VkInstance handle, const VkAllocationCallbacks *allocator)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 90ceb5e324d..03162b341e2 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -684,17 +684,11 @@ static void wine_vk_instance_free(struct wine_instance *instance) { unsigned int i;
- if (!instance) - return; - for (i = 0; i < instance->phys_dev_count; i++) wine_phys_dev_cleanup(&instance->phys_devs[i]);
- if (instance->host_instance) - { - vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); - remove_handle_mapping(instance, &instance->wrapper_entry); - } + vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); + remove_handle_mapping(instance, &instance->wrapper_entry);
pthread_rwlock_destroy(&instance->wrapper_lock); free(instance->utils_messengers); @@ -846,8 +840,6 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, ERR("Failed to allocate memory for instance\n"); return VK_ERROR_OUT_OF_HOST_MEMORY; } - rb_init(&object->wrappers, wrapper_entry_compare); - pthread_rwlock_init(&object->wrapper_lock, NULL);
init_conversion_context(&ctx); res = wine_vk_instance_convert_create_info(&ctx, create_info, &create_info_host, object); @@ -857,10 +849,14 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, if (res != VK_SUCCESS) { ERR("Failed to create instance, res=%d\n", res); - wine_vk_instance_free(object); + free(object->utils_messengers); + free(object); return res; }
+ rb_init(&object->wrappers, wrapper_entry_compare); + pthread_rwlock_init(&object->wrapper_lock, NULL); + object->handle = client_instance; add_handle_mapping_ptr(object, object->handle, object->host_instance, &object->wrapper_entry);
@@ -929,6 +925,8 @@ void wine_vkDestroyInstance(VkInstance handle, const VkAllocationCallbacks *allo
if (allocator) FIXME("Support allocation allocators\n"); + if (!instance) + return;
wine_vk_instance_free(instance); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 03162b341e2..f60a4720b5f 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -219,7 +219,6 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk
static void wine_phys_dev_cleanup(struct wine_phys_dev *phys_dev) { - remove_handle_mapping(phys_dev->instance, &phys_dev->wrapper_entry); free(phys_dev->extensions); }
@@ -238,7 +237,6 @@ static VkResult wine_vk_physical_device_init(struct wine_phys_dev *object, VkPhy object->host_physical_device = host_handle;
client_handle->base.unix_handle = (uintptr_t)object; - add_handle_mapping_ptr(instance, client_handle, host_handle, &object->wrapper_entry);
instance->funcs.p_vkGetPhysicalDeviceMemoryProperties(host_handle, &object->memory_properties);
@@ -421,8 +419,6 @@ static void wine_vk_device_init_queues(struct wine_device *device, const VkDevic }
queue->handle->base.unix_handle = (uintptr_t)queue; - add_handle_mapping_ptr(device->phys_dev->instance, queue->handle, queue->host_queue, &queue->wrapper_entry); - TRACE("Got device %p queue %p, host_queue %p.\n", device, queue, queue->host_queue); }
@@ -684,10 +680,12 @@ static void wine_vk_instance_free(struct wine_instance *instance) { unsigned int i;
+ vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); for (i = 0; i < instance->phys_dev_count; i++) + { + remove_handle_mapping(instance, &instance->phys_devs[i].wrapper_entry); wine_phys_dev_cleanup(&instance->phys_devs[i]); - - vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); + } remove_handle_mapping(instance, &instance->wrapper_entry);
pthread_rwlock_destroy(&instance->wrapper_lock); @@ -790,11 +788,9 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre res = instance->funcs.p_vkCreateDevice(phys_dev->host_physical_device, &create_info_host, NULL /* allocator */, &object->host_device); free_conversion_context(&ctx); - add_handle_mapping_ptr(instance, device_handle, object->host_device, &object->wrapper_entry); if (res != VK_SUCCESS) { WARN("Failed to create device, res=%d.\n", res); - remove_handle_mapping(object->phys_dev->instance, &object->wrapper_entry); free(object); return res; } @@ -815,9 +811,16 @@ VkResult wine_vkCreateDevice(VkPhysicalDevice phys_dev_handle, const VkDeviceCre
device_handle->quirks = instance->quirks; device_handle->base.unix_handle = (uintptr_t)object; - *ret_device = device_handle;
TRACE("Created device %p, host_device %p.\n", object, object->host_device); + for (i = 0; i < object->queue_count; i++) + { + struct wine_queue *queue = object->queues + i; + add_handle_mapping_ptr(instance, queue->handle, queue->host_queue, &queue->wrapper_entry); + } + + *ret_device = device_handle; + add_handle_mapping_ptr(instance, *ret_device, object->host_device, &object->wrapper_entry); return VK_SUCCESS; }
@@ -830,6 +833,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, const VkApplicationInfo *app_info; struct conversion_context ctx; struct wine_instance *object; + unsigned int i; VkResult res;
if (allocator) @@ -858,7 +862,6 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, pthread_rwlock_init(&object->wrapper_lock, NULL);
object->handle = client_instance; - add_handle_mapping_ptr(object, object->handle, object->host_instance, &object->wrapper_entry);
/* Load all instance functions we are aware of. Note the loader takes care * of any filtering for extensions which were not requested, but which the @@ -895,9 +898,16 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, }
client_instance->base.unix_handle = (uintptr_t)object; - *instance = client_instance; + TRACE("Created instance %p, host_instance %p.\n", object, object->host_instance); + for (i = 0; i < object->phys_dev_count; i++) + { + struct wine_phys_dev *phys_dev = &object->phys_devs[i]; + add_handle_mapping_ptr(object, phys_dev->handle, phys_dev->host_physical_device, &phys_dev->wrapper_entry); + }
+ *instance = client_instance; + add_handle_mapping_ptr(object, *instance, object->host_instance, &object->wrapper_entry); return VK_SUCCESS; }
@@ -911,10 +921,10 @@ void wine_vkDestroyDevice(VkDevice handle, const VkAllocationCallbacks *allocato if (!device) return;
+ device->funcs.p_vkDestroyDevice(device->host_device, NULL /* pAllocator */); for (i = 0; i < device->queue_count; i++) remove_handle_mapping(device->phys_dev->instance, &device->queues[i].wrapper_entry); remove_handle_mapping(device->phys_dev->instance, &device->wrapper_entry); - device->funcs.p_vkDestroyDevice(device->host_device, NULL /* pAllocator */);
free(device); } @@ -1156,8 +1166,8 @@ void wine_vkDestroyCommandPool(VkDevice device_handle, VkCommandPool handle, if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
- remove_handle_mapping(device->phys_dev->instance, &pool->wrapper_entry); device->funcs.p_vkDestroyCommandPool(device->host_device, pool->host_command_pool, NULL); + remove_handle_mapping(device->phys_dev->instance, &pool->wrapper_entry); free(pool); }
@@ -1734,8 +1744,8 @@ void wine_vkFreeMemory(VkDevice handle, VkDeviceMemory memory_handle, const VkAl device->funcs.p_vkUnmapMemory2KHR(device->host_device, &info); }
- remove_handle_mapping(device->phys_dev->instance, &memory->wrapper_entry); device->funcs.p_vkFreeMemory(device->host_device, memory->host_memory, NULL); + remove_handle_mapping(device->phys_dev->instance, &memory->wrapper_entry);
if (memory->vm_map) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winevulkan/vulkan.c | 45 +++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 26 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index f60a4720b5f..9981bd0141e 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -673,27 +673,6 @@ static struct wine_phys_dev *wine_vk_instance_wrap_physical_device(struct wine_i return NULL; }
-/* Helper function used for freeing an instance structure. This function supports full - * and partial object cleanups and can thus be used for vkCreateInstance failures. - */ -static void wine_vk_instance_free(struct wine_instance *instance) -{ - unsigned int i; - - vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); - for (i = 0; i < instance->phys_dev_count; i++) - { - remove_handle_mapping(instance, &instance->phys_devs[i].wrapper_entry); - wine_phys_dev_cleanup(&instance->phys_devs[i]); - } - remove_handle_mapping(instance, &instance->wrapper_entry); - - pthread_rwlock_destroy(&instance->wrapper_lock); - free(instance->utils_messengers); - - free(instance); -} - VkResult wine_vkAllocateCommandBuffers(VkDevice handle, const VkCommandBufferAllocateInfo *allocate_info, VkCommandBuffer *buffers ) { @@ -858,9 +837,6 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, return res; }
- rb_init(&object->wrappers, wrapper_entry_compare); - pthread_rwlock_init(&object->wrapper_lock, NULL); - object->handle = client_instance;
/* Load all instance functions we are aware of. Note the loader takes care @@ -881,7 +857,9 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, if (res != VK_SUCCESS) { ERR("Failed to load physical devices, res=%d\n", res); - wine_vk_instance_free(object); + vk_funcs->p_vkDestroyInstance(object->host_instance, NULL /* allocator */); + free(object->utils_messengers); + free(object); return res; }
@@ -900,6 +878,10 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info, client_instance->base.unix_handle = (uintptr_t)object;
TRACE("Created instance %p, host_instance %p.\n", object, object->host_instance); + + rb_init(&object->wrappers, wrapper_entry_compare); + pthread_rwlock_init(&object->wrapper_lock, NULL); + for (i = 0; i < object->phys_dev_count; i++) { struct wine_phys_dev *phys_dev = &object->phys_devs[i]; @@ -932,13 +914,24 @@ void wine_vkDestroyDevice(VkDevice handle, const VkAllocationCallbacks *allocato void wine_vkDestroyInstance(VkInstance handle, const VkAllocationCallbacks *allocator) { struct wine_instance *instance = wine_instance_from_handle(handle); + unsigned int i;
if (allocator) FIXME("Support allocation allocators\n"); if (!instance) return;
- wine_vk_instance_free(instance); + vk_funcs->p_vkDestroyInstance(instance->host_instance, NULL /* allocator */); + for (i = 0; i < instance->phys_dev_count; i++) + { + remove_handle_mapping(instance, &instance->phys_devs[i].wrapper_entry); + wine_phys_dev_cleanup(&instance->phys_devs[i]); + } + remove_handle_mapping(instance, &instance->wrapper_entry); + + pthread_rwlock_destroy(&instance->wrapper_lock); + free(instance->utils_messengers); + free(instance); }
VkResult wine_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice phys_dev_handle, const char *layer_name,
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144070
Your paranoid android.
=== debian11b (64 bit WoW report) ===
d3dx10_34: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C0B40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011C0A70. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 0000000001195BD0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E35C0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3790.
d3dx10_35: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011B23C0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001195A50. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 0000000001195A50. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011B23C0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001195A50.
d3dx10_36: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011A45D0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011A47A0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D19A0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011A47A0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C3380.
d3dx10_37: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239DE0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011A4A60. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D5720. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011B6050.
d3dx10_38: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011A4B40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001239DB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011BC970. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E3530. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3700.
d3dx10_39: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C0B40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3E40. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011C0A70. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001195CA0.
d3dx10_40: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011D6A50. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011D6980. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4A10. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011E3980.
d3dx10_41: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239CE0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011D56A0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 0000000001239EB0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D56A0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011B20B0.
d3dx10_42: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3D60. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3970. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E3970. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E3A30. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011B5F10.
d3dx10_43: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C37C0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011B6000. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011B6000. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011A4750. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011B5D20.
On Thu Mar 14 15:37:08 2024 +0000, Jacek Caban wrote:
I also don't see what command buffers allocation achieves, but it's not wrong, so that's probably fine.
Indeed, I left this out then. It was mostly part of the other changes to remove the wrapper indirections there too.
On Thu Mar 14 15:35:48 2024 +0000, Rémi Bernon wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/5274/diffs?diff_id=105081&start_sha=32be9eb0489bc2b582e2a4a7f743f1bb56769f77#561751f09a3d9e02a084f385e9182f0184b50581_68_68)
Thanks, should be fixed now.
This merge request was approved by Jacek Caban.