winevulkan: Use a single allocation for instance and physical devices.

This commit is contained in:
Rémi Bernon 2024-03-13 18:06:49 +01:00 committed by Alexandre Julliard
parent bda48ed85e
commit aaeb221f52
2 changed files with 59 additions and 80 deletions

View file

@ -217,30 +217,22 @@ static VkBool32 debug_report_callback_conversion(VkDebugReportFlagsEXT flags, Vk
return VK_FALSE; 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); remove_handle_mapping(phys_dev->instance, &phys_dev->wrapper_entry);
free(phys_dev->extensions); free(phys_dev->extensions);
free(phys_dev);
} }
static struct wine_phys_dev *wine_vk_physical_device_alloc(struct wine_instance *instance, static VkResult wine_vk_physical_device_init(struct wine_phys_dev *object, VkPhysicalDevice host_handle,
VkPhysicalDevice host_handle, VkPhysicalDevice client_handle) VkPhysicalDevice client_handle, struct wine_instance *instance)
{ {
BOOL have_memory_placed = FALSE, have_map_memory2 = FALSE; BOOL have_memory_placed = FALSE, have_map_memory2 = FALSE;
struct wine_phys_dev *object;
uint32_t num_host_properties, num_properties = 0; uint32_t num_host_properties, num_properties = 0;
VkExtensionProperties *host_properties = NULL; VkExtensionProperties *host_properties = NULL;
BOOL have_external_memory_host = FALSE; BOOL have_external_memory_host = FALSE;
VkResult res; VkResult res;
unsigned int i, j; unsigned int i, j;
if (!(object = calloc(1, sizeof(*object))))
return NULL;
object->instance = instance; object->instance = instance;
object->handle = client_handle; object->handle = client_handle;
object->host_physical_device = host_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); free(host_properties);
return object; return VK_SUCCESS;
err: err:
wine_vk_physical_device_free(object); wine_phys_dev_cleanup(object);
free(host_properties); free(host_properties);
return NULL; return res;
} }
static void wine_vk_free_command_buffers(struct wine_device *device, 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. */ /* 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; VkPhysicalDevice *host_handles;
uint32_t phys_dev_count; uint32_t phys_dev_count;
@ -676,32 +668,23 @@ static VkResult wine_vk_instance_load_physical_devices(struct wine_instance *ins
return res; 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. */ /* Wrap each host physical device handle into a dispatchable object for the ICD loader. */
for (i = 0; i < phys_dev_count; i++) for (i = 0; i < phys_dev_count; i++)
{ {
struct wine_phys_dev *phys_dev = wine_vk_physical_device_alloc(instance, host_handles[i], struct wine_phys_dev *phys_dev = instance->phys_devs + i;
&instance->handle->phys_devs[i]); res = wine_vk_physical_device_init(phys_dev, host_handles[i], &instance->handle->phys_devs[i], instance);
if (!phys_dev) if (res != VK_SUCCESS)
{ goto err;
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;
} }
instance->phys_dev_count = phys_dev_count; instance->phys_dev_count = phys_dev_count;
free(host_handles); free(host_handles);
return VK_SUCCESS; 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, 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) 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; 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) static void wine_vk_instance_free(struct wine_instance *instance)
{ {
unsigned int i;
if (!instance) if (!instance)
return; return;
if (instance->phys_devs)
{
unsigned int i;
for (i = 0; i < instance->phys_dev_count; i++) for (i = 0; i < instance->phys_dev_count; i++)
{ wine_phys_dev_cleanup(&instance->phys_devs[i]);
wine_vk_physical_device_free(instance->phys_devs[i]);
}
free(instance->phys_devs);
}
if (instance->host_instance) if (instance->host_instance)
{ {
@ -891,7 +868,7 @@ VkResult wine_vkCreateInstance(const VkInstanceCreateInfo *create_info,
if (allocator) if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n"); 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"); ERR("Failed to allocate memory for instance\n");
return VK_ERROR_OUT_OF_HOST_MEMORY; 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. * the host physical devices and present those to the application.
* Cleanup happens as part of wine_vkDestroyInstance. * 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) if (res != VK_SUCCESS)
{ {
ERR("Failed to load physical devices, res=%d\n", res); 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); *count = min(*count, instance->phys_dev_count);
for (i = 0; i < *count; i++) 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); TRACE("Returning %u devices.\n", *count);

View file

@ -109,39 +109,6 @@ struct wine_debug_report_callback
struct wrapper_entry wrapper_entry; struct wrapper_entry wrapper_entry;
}; };
struct wine_instance
{
struct vulkan_instance_funcs funcs;
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;
pthread_rwlock_t wrapper_lock;
struct wine_debug_utils_messenger *utils_messengers;
uint32_t utils_messenger_count;
struct wine_debug_report_callback default_callback;
unsigned int quirks;
struct wrapper_entry wrapper_entry;
};
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_phys_dev
{ {
struct wine_instance *instance; /* parent */ struct wine_instance *instance; /* parent */
@ -164,6 +131,41 @@ static inline struct wine_phys_dev *wine_phys_dev_from_handle(VkPhysicalDevice h
return (struct wine_phys_dev *)(uintptr_t)handle->base.unix_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;
VkInstance handle; /* client instance */
VkInstance host_instance;
VkBool32 enable_win32_surface;
VkBool32 enable_wrapper_list;
struct rb_tree wrappers;
pthread_rwlock_t wrapper_lock;
struct wine_debug_utils_messenger *utils_messengers;
uint32_t utils_messenger_count;
struct wine_debug_report_callback default_callback;
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_cmd_pool struct wine_cmd_pool
{ {
VkCommandPool handle; VkCommandPool handle;