winevulkan: Separate PE and Unix VkDevice structs.

This commit is contained in:
Jacek Caban 2022-09-01 14:33:59 +02:00 committed by Alexandre Julliard
parent 1f9ece9e32
commit a6dc349aad
8 changed files with 370 additions and 337 deletions

View file

@ -100,6 +100,13 @@ static BOOL is_available_device_function(VkDevice device, const char *name)
return vk_unix_call(unix_is_available_device_function, &params);
}
static void *alloc_vk_object(size_t size)
{
struct wine_vk_base *object = calloc(1, size);
object->loader_magic = VULKAN_ICD_MAGIC_VALUE;
return object;
}
PFN_vkVoidFunction WINAPI vkGetInstanceProcAddr(VkInstance instance, const char *name)
{
void *func;
@ -172,8 +179,8 @@ PFN_vkVoidFunction WINAPI vkGetDeviceProcAddr(VkDevice device, const char *name)
* https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323
* https://github.com/KhronosGroup/Vulkan-Docs/issues/655
*/
if (((struct wine_vk_device_base *)device)->quirks & WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR
&& ((func = wine_vk_get_instance_proc_addr(name))
if ((device->quirks & WINEVULKAN_QUIRK_GET_DEVICE_PROC_ADDR)
&& ((func = wine_vk_get_instance_proc_addr(name))
|| (func = wine_vk_get_phys_dev_proc_addr(name))))
{
WARN("Returning instance function %s.\n", debugstr_a(name));
@ -417,6 +424,37 @@ void WINAPI vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice phys_dev,
fill_luid_property(properties2);
}
VkResult WINAPI vkCreateDevice(VkPhysicalDevice phys_dev, const VkDeviceCreateInfo *create_info,
const VkAllocationCallbacks *allocator, VkDevice *ret)
{
struct vkCreateDevice_params params;
VkDevice device;
VkResult result;
if (!(device = alloc_vk_object(sizeof(*device))))
return VK_ERROR_OUT_OF_HOST_MEMORY;
params.physicalDevice = phys_dev;
params.pCreateInfo = create_info;
params.pAllocator = allocator;
params.pDevice = ret;
params.client_ptr = device;
result = vk_unix_call(unix_vkCreateDevice, &params);
if (!device->base.unix_handle)
free(device);
return result;
}
void WINAPI vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *allocator)
{
struct vkDestroyDevice_params params;
params.device = device;
params.pAllocator = allocator;
vk_unix_call(unix_vkDestroyDevice, &params);
free(device);
}
static BOOL WINAPI call_vulkan_debug_report_callback( struct wine_vk_debug_report_params *params, ULONG size )
{
return params->user_callback(params->flags, params->object_type, params->object_handle, params->location,

View file

@ -2110,16 +2110,6 @@ VkResult WINAPI vkCreateDescriptorUpdateTemplateKHR(VkDevice device, const VkDes
return vk_unix_call(unix_vkCreateDescriptorUpdateTemplateKHR, &params);
}
VkResult WINAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
{
struct vkCreateDevice_params params;
params.physicalDevice = physicalDevice;
params.pCreateInfo = pCreateInfo;
params.pAllocator = pAllocator;
params.pDevice = pDevice;
return vk_unix_call(unix_vkCreateDevice, &params);
}
VkResult WINAPI vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent)
{
struct vkCreateEvent_params params;
@ -2541,14 +2531,6 @@ void WINAPI vkDestroyDescriptorUpdateTemplateKHR(VkDevice device, VkDescriptorUp
vk_unix_call(unix_vkDestroyDescriptorUpdateTemplateKHR, &params);
}
void WINAPI vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator)
{
struct vkDestroyDevice_params params;
params.device = device;
params.pAllocator = pAllocator;
vk_unix_call(unix_vkDestroyDevice, &params);
}
void WINAPI vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator)
{
struct vkDestroyEvent_params params;

View file

@ -2155,6 +2155,7 @@ struct vkCreateDevice_params
const VkDeviceCreateInfo *pCreateInfo;
const VkAllocationCallbacks *pAllocator;
VkDevice *pDevice;
void *client_ptr;
};
struct vkCreateEvent_params

View file

@ -186,7 +186,7 @@ FUNCTION_OVERRIDES = {
"vkGetInstanceProcAddr": {"dispatch" : False, "driver" : True, "thunk" : ThunkType.NONE, "loader_thunk" : ThunkType.NONE},
# Instance functions
"vkCreateDevice" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkCreateDevice" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE, "loader_thunk" : ThunkType.PRIVATE, "extra_param" : "client_ptr"},
"vkDestroyInstance" : {"dispatch" : False, "driver" : True, "thunk" : ThunkType.NONE },
"vkEnumerateDeviceExtensionProperties" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkEnumerateDeviceLayerProperties": {"dispatch": True, "driver": False, "thunk": ThunkType.NONE},
@ -205,7 +205,7 @@ FUNCTION_OVERRIDES = {
"vkCreateComputePipelines" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.PRIVATE},
"vkCreateGraphicsPipelines" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.PRIVATE},
"vkDestroyCommandPool" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
"vkDestroyDevice" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkDestroyDevice" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE, "loader_thunk" : ThunkType.PRIVATE},
"vkFreeCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : ThunkType.NONE},
"vkGetDeviceProcAddr" : {"dispatch" : False, "driver" : True, "thunk" : ThunkType.NONE, "loader_thunk" : ThunkType.NONE},
"vkGetDeviceQueue" : {"dispatch": True, "driver" : False, "thunk" : ThunkType.NONE},
@ -553,6 +553,7 @@ class VkFunction(object):
self.driver = func_info["driver"] if func_info else False
self.thunk_type = func_info["thunk"] if func_info else ThunkType.PUBLIC
self.loader_thunk_type = func_info["loader_thunk"] if func_info and "loader_thunk" in func_info else ThunkType.PUBLIC
self.extra_param = func_info["extra_param"] if func_info and "extra_param" in func_info else None
# Required is set while parsing which APIs and types are required
# and is used by the code generation.
@ -767,8 +768,8 @@ class VkFunction(object):
body += "{0}result = ".format(params_prefix)
elif self.type != "void":
body += "return "
body += "{0}{1}.p_{2}({3});\n".format(params_prefix, self.params[0].dispatch_table(),
self.name, params)
body += "{0}.p_{1}({2});\n".format(self.params[0].dispatch_table(params_prefix),
self.name, params)
if self.type == "void" or self.returns_longlong():
body += " return STATUS_SUCCESS;\n"
@ -828,12 +829,12 @@ class VkFunction(object):
# Call the native Vulkan function.
if self.type == "void":
body += " {0}{1}.p_{2}({3});\n".format(params_prefix, self.params[0].dispatch_table(),
self.name, params)
body += " {0}.p_{1}({2});\n".format(self.params[0].dispatch_table(params_prefix),
self.name, params)
else:
body += " {0}result = {1}{2}.p_{3}({4});\n".format(result_prefix, params_prefix,
self.params[0].dispatch_table(),
self.name, params)
body += " {0}result = {1}.p_{2}({3});\n".format(result_prefix,
self.params[0].dispatch_table(params_prefix),
self.name, params)
body += "\n"
@ -1053,20 +1054,19 @@ class VkHandle(object):
parent = handle.attrib.get("parent") # Most objects have a parent e.g. VkQueue has VkDevice.
return VkHandle(name, _type, parent)
def dispatch_table(self):
def dispatch_table(self, param):
if not self.is_dispatchable():
return None
if self.parent is None:
# Should only happen for VkInstance
return "funcs"
return "{0}->funcs".format(param)
elif self.name == "VkDevice":
# VkDevice has VkInstance as a parent, but has its own dispatch table.
return "funcs"
return "wine_device_from_handle({0})->funcs".format(param)
elif self.parent in ["VkInstance", "VkPhysicalDevice"]:
return "instance->funcs"
return "{0}->instance->funcs".format(param)
elif self.parent in ["VkDevice", "VkCommandPool"]:
return "device->funcs"
return "{0}->device->funcs".format(param)
else:
LOGGER.error("Unhandled dispatchable parent: {0}".format(self.parent))
@ -1100,6 +1100,8 @@ class VkHandle(object):
return "wine_debug_utils_messenger_from_handle({0})->debug_messenger".format(name)
if self.name == "VkDebugReportCallbackEXT":
return "wine_debug_report_callback_from_handle({0})->debug_callback".format(name)
if self.name == "VkDevice":
return "wine_device_from_handle({0})->device".format(name)
if self.name == "VkSurfaceKHR":
return "wine_surface_from_handle({0})->surface".format(name)
@ -1107,8 +1109,6 @@ class VkHandle(object):
if self.name == "VkCommandBuffer":
native_handle_name = "command_buffer"
if self.name == "VkDevice":
native_handle_name = "device"
if self.name == "VkInstance":
native_handle_name = "instance"
if self.name == "VkPhysicalDevice":
@ -1701,13 +1701,13 @@ class VkParam(object):
return self._direction
def dispatch_table(self):
def dispatch_table(self, params_prefix=""):
""" Return functions dispatch table pointer for dispatchable objects. """
if not self.is_dispatchable():
return None
return "{0}->{1}".format(self.name, self.handle.dispatch_table())
return self.handle.dispatch_table(params_prefix + self.name)
def format_string(self):
return self.format_str
@ -3076,6 +3076,8 @@ class VkGenerator(object):
f.write("{\n");
for p in vk_func.params:
f.write(" {0};\n".format(p.definition(is_member=True)))
if vk_func.extra_param:
f.write(" void *{0};\n".format(vk_func.extra_param))
if vk_func.returns_longlong():
f.write(" {0} result;\n".format(vk_func.type))
f.write("};\n\n");

View file

@ -23,7 +23,6 @@
#include "config.h"
#include <time.h>
#include <stdlib.h>
#include "vulkan_private.h"
#include "wine/vulkan_driver.h"
@ -62,8 +61,8 @@ 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, object, native_handle) \
wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (uintptr_t) (native_handle), &(object)->mapping)
#define WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, client_handle, native_handle, object) \
wine_vk_add_handle_mapping((instance), (uintptr_t)(client_handle), (uintptr_t)(native_handle), &(object)->mapping)
#define WINE_VK_ADD_NON_DISPATCHABLE_MAPPING(instance, object, native_handle) \
wine_vk_add_handle_mapping((instance), (uint64_t) (uintptr_t) (object), (uint64_t) (native_handle), &(object)->mapping)
static void wine_vk_add_handle_mapping(struct VkInstance_T *instance, uint64_t wrapped_handle,
@ -238,7 +237,7 @@ static struct VkPhysicalDevice_T *wine_vk_physical_device_alloc(struct VkInstanc
object->instance = instance;
object->phys_dev = phys_dev;
WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, phys_dev);
WINE_VK_ADD_DISPATCHABLE_MAPPING(instance, object, phys_dev, object);
res = instance->funcs.p_vkEnumerateDeviceExtensionProperties(phys_dev,
NULL, &num_host_properties, NULL);
@ -306,7 +305,7 @@ err:
return NULL;
}
static void wine_vk_free_command_buffers(struct VkDevice_T *device,
static void wine_vk_free_command_buffers(struct wine_device *device,
struct wine_cmd_pool *pool, uint32_t count, const VkCommandBuffer *buffers)
{
unsigned int i;
@ -323,7 +322,7 @@ static void wine_vk_free_command_buffers(struct VkDevice_T *device,
}
}
static void wine_vk_device_get_queues(struct VkDevice_T *device,
static void wine_vk_device_get_queues(struct wine_device *device,
uint32_t family_index, uint32_t queue_count, VkDeviceQueueCreateFlags flags,
struct VkQueue_T* queues)
{
@ -359,7 +358,7 @@ static void wine_vk_device_get_queues(struct VkDevice_T *device,
device->funcs.p_vkGetDeviceQueue(device->device, family_index, i, &queue->queue);
}
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue, queue->queue);
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, queue, queue->queue, queue);
}
}
@ -405,7 +404,7 @@ static VkResult wine_vk_device_convert_create_info(const VkDeviceCreateInfo *src
/* 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 VkDevice_T *device)
static void wine_vk_device_free(struct wine_device *device)
{
struct VkQueue_T *queue;
@ -637,7 +636,7 @@ static void wine_vk_instance_free(struct VkInstance_T *instance)
NTSTATUS wine_vkAllocateCommandBuffers(void *args)
{
struct vkAllocateCommandBuffers_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
const VkCommandBufferAllocateInfo *allocate_info = params->pAllocateInfo;
VkCommandBuffer *buffers = params->pCommandBuffers;
struct wine_cmd_pool *pool;
@ -675,7 +674,8 @@ NTSTATUS wine_vkAllocateCommandBuffers(void *args)
list_add_tail(&pool->command_buffers, &buffers[i]->pool_link);
res = device->funcs.p_vkAllocateCommandBuffers(device->device,
&allocate_info_host, &buffers[i]->command_buffer);
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, buffers[i], buffers[i]->command_buffer);
WINE_VK_ADD_DISPATCHABLE_MAPPING(device->phys_dev->instance, buffers[i],
buffers[i]->command_buffer, buffers[i]);
if (res != VK_SUCCESS)
{
ERR("Failed to allocate command buffer, res=%d.\n", res);
@ -699,14 +699,15 @@ NTSTATUS wine_vkCreateDevice(void *args)
VkPhysicalDevice phys_dev = params->physicalDevice;
const VkDeviceCreateInfo *create_info = params->pCreateInfo;
const VkAllocationCallbacks *allocator = params->pAllocator;
VkDevice *device = params->pDevice;
VkDevice *ret_device = params->pDevice;
VkDevice device_handle = params->client_ptr;
VkDeviceCreateInfo create_info_host;
struct VkQueue_T *next_queue;
struct VkDevice_T *object;
struct wine_device *object;
unsigned int i;
VkResult res;
TRACE("%p, %p, %p, %p\n", phys_dev, create_info, allocator, device);
TRACE("%p, %p, %p, %p\n", phys_dev, create_info, allocator, ret_device);
if (allocator)
FIXME("Support for allocation callbacks not implemented yet\n");
@ -725,7 +726,6 @@ NTSTATUS wine_vkCreateDevice(void *args)
if (!(object = calloc(1, sizeof(*object))))
return VK_ERROR_OUT_OF_HOST_MEMORY;
object->base.base.loader_magic = VULKAN_ICD_MAGIC_VALUE;
object->phys_dev = phys_dev;
res = wine_vk_device_convert_create_info(create_info, &create_info_host);
@ -735,7 +735,7 @@ NTSTATUS wine_vkCreateDevice(void *args)
res = phys_dev->instance->funcs.p_vkCreateDevice(phys_dev->phys_dev,
&create_info_host, NULL /* allocator */, &object->device);
wine_vk_device_free_create_info(&create_info_host);
WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev->instance, object, object->device);
WINE_VK_ADD_DISPATCHABLE_MAPPING(phys_dev->instance, device_handle, object->device, object);
if (res != VK_SUCCESS)
{
WARN("Failed to create device, res=%d.\n", res);
@ -780,9 +780,9 @@ NTSTATUS wine_vkCreateDevice(void *args)
next_queue += queue_count;
}
object->base.quirks = phys_dev->instance->quirks;
*device = object;
device_handle->quirks = phys_dev->instance->quirks;
device_handle->base.unix_handle = (uintptr_t)object;
*ret_device = device_handle;
TRACE("Created device %p (native device %p).\n", object, object->device);
return VK_SUCCESS;
@ -830,7 +830,7 @@ NTSTATUS wine_vkCreateInstance(void *args)
return res;
}
WINE_VK_ADD_DISPATCHABLE_MAPPING(object, object, object->instance);
WINE_VK_ADD_DISPATCHABLE_MAPPING(object, object, object->instance, object);
/* 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
@ -876,7 +876,7 @@ NTSTATUS wine_vkCreateInstance(void *args)
NTSTATUS wine_vkDestroyDevice(void *args)
{
struct vkDestroyDevice_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
const VkAllocationCallbacks *allocator = params->pAllocator;
TRACE("%p %p\n", device, allocator);
@ -1058,7 +1058,7 @@ NTSTATUS wine_vkEnumeratePhysicalDevices(void *args)
NTSTATUS wine_vkFreeCommandBuffers(void *args)
{
struct vkFreeCommandBuffers_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
struct wine_cmd_pool *pool = wine_cmd_pool_from_handle(params->commandPool);
uint32_t count = params->commandBufferCount;
const VkCommandBuffer *buffers = params->pCommandBuffers;
@ -1069,8 +1069,9 @@ NTSTATUS wine_vkFreeCommandBuffers(void *args)
return STATUS_SUCCESS;
}
static VkQueue wine_vk_device_find_queue(VkDevice device, const VkDeviceQueueInfo2 *info)
static VkQueue wine_vk_device_find_queue(VkDevice handle, const VkDeviceQueueInfo2 *info)
{
struct wine_device *device = wine_device_from_handle(handle);
struct VkQueue_T* queue;
uint32_t i;
@ -1129,7 +1130,7 @@ NTSTATUS wine_vkGetDeviceQueue2(void *args)
NTSTATUS wine_vkCreateCommandPool(void *args)
{
struct vkCreateCommandPool_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
const VkCommandPoolCreateInfo *info = params->pCreateInfo;
const VkAllocationCallbacks *allocator = params->pAllocator;
VkCommandPool *command_pool = params->pCommandPool;
@ -1164,7 +1165,7 @@ NTSTATUS wine_vkCreateCommandPool(void *args)
NTSTATUS wine_vkDestroyCommandPool(void *args)
{
struct vkDestroyCommandPool_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
VkCommandPool handle = params->commandPool;
const VkAllocationCallbacks *allocator = params->pAllocator;
struct wine_cmd_pool *pool = wine_cmd_pool_from_handle(handle);
@ -1393,7 +1394,7 @@ static inline uint64_t convert_timestamp(VkTimeDomainEXT host_domain, VkTimeDoma
NTSTATUS wine_vkGetCalibratedTimestampsEXT(void *args)
{
struct vkGetCalibratedTimestampsEXT_params *params = args;
VkDevice device = params->device;
struct wine_device *device = wine_device_from_handle(params->device);
uint32_t timestamp_count = params->timestampCount;
const VkCalibratedTimestampInfoEXT *timestamp_infos = params->pTimestampInfos;
uint64_t *timestamps = params->pTimestamps;
@ -1881,5 +1882,6 @@ NTSTATUS vk_is_available_instance_function(void *arg)
NTSTATUS vk_is_available_device_function(void *arg)
{
struct is_available_device_function_params *params = arg;
return !!vk_funcs->p_vkGetDeviceProcAddr(params->device->device, params->name);
struct wine_device *device = wine_device_from_handle(params->device);
return !!vk_funcs->p_vkGetDeviceProcAddr(device->device, params->name);
}

View file

@ -23,6 +23,7 @@
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include <stdarg.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
@ -49,10 +50,11 @@ struct wine_vk_base
/* Special section in each dispatchable object for use by the ICD loader for
* storing dispatch tables. The start contains a magical value '0x01CDC0DE'.
*/
UINT_PTR loader_magic;
UINT64 loader_magic;
UINT64 unix_handle;
};
struct wine_vk_device_base
struct VkDevice_T
{
struct wine_vk_base base;
unsigned int quirks;

View file

@ -46,18 +46,19 @@ struct wine_vk_mapping
struct VkCommandBuffer_T
{
struct wine_vk_base base;
struct VkDevice_T *device; /* parent */
struct wine_device *device; /* parent */
VkCommandBuffer command_buffer; /* native command buffer */
struct list pool_link;
struct wine_vk_mapping mapping;
};
struct VkDevice_T
struct wine_device
{
struct wine_vk_device_base base;
struct vulkan_device_funcs funcs;
struct VkPhysicalDevice_T *phys_dev; /* parent */
VkDevice handle; /* client device */
VkDevice device; /* native device */
struct VkQueue_T* queues;
@ -66,6 +67,11 @@ struct VkDevice_T
struct wine_vk_mapping mapping;
};
static inline struct wine_device *wine_device_from_handle(VkDevice handle)
{
return (struct wine_device *)(uintptr_t)handle->base.unix_handle;
}
struct wine_debug_utils_messenger;
struct wine_debug_report_callback
@ -121,7 +127,7 @@ struct VkPhysicalDevice_T
struct VkQueue_T
{
struct wine_vk_base base;
struct VkDevice_T *device; /* parent */
struct wine_device *device; /* parent */
VkQueue queue; /* native queue */
uint32_t family_index;

File diff suppressed because it is too large Load diff