[PATCH 08/10] winex11: Add initial vkCreateInstance implementation.
Roderick Colenbrander <[email protected]>
| Newsgroups | gmane.comp.emulators.wine.patches |
|---|---|
| Message-ID | <[email protected]> |
Signed-off-by: Roderick Colenbrander <[email protected]> --- dlls/winex11.drv/vulkan.c | 81 +++++++++++++++++++++++++++++++++++++-- dlls/winex11.drv/vulkan_private.h | 27 +++++++++++++ 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 8632c46010..f1c41908d8 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -39,6 +39,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(vulkan); void* WINAPI X11DRV_vk_icdGetInstanceProcAddr(VkInstance instance, const char* pName); +/* Function pointers to native calls we need. Define them by hand instead of using a MAKE_FUNCPTR macro + * to avoid messing with calling conventions. + */ +static VkResult (*pvkCreateInstance)(const VkInstanceCreateInfo*, const VkAllocationCallbacks*, VkInstance*); +static void (*pvkDestroyInstance)(VkInstance, const VkAllocationCallbacks*); + /* All Vulkan structures use this structure for the first elements. */ struct wine_vk_structure_header { @@ -47,6 +53,19 @@ struct wine_vk_structure_header }; +static void *wine_vk_alloc_dispatchable_object(size_t size) +{ + struct wine_vk_dispatchable_object *object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); + + if (!object) + return NULL; + + /* Set special header for ICD loader. */ + ((struct wine_vk_base*)object)->loader_magic = VULKAN_ICD_MAGIC_VALUE; + + return object; +} + static BOOL wine_vk_init(void) { static BOOL init_done = FALSE; @@ -57,6 +76,11 @@ static BOOL wine_vk_init(void) if (!(vulkan_handle = wine_dlopen(SONAME_LIBVULKAN, RTLD_NOW, NULL, 0))) return FALSE; +#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(vulkan_handle, #f, NULL, 0)) == NULL) return FALSE; +LOAD_FUNCPTR(vkCreateInstance) +LOAD_FUNCPTR(vkDestroyInstance) +#undef LOAD_FUNCPTR + return TRUE; } @@ -109,15 +133,66 @@ static void wine_vk_instance_dump_create_info(const VkInstanceCreateInfo *info) } } +/* 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 VkInstance_T *instance) +{ + if (!instance) + return; + + if (instance->instance) + pvkDestroyInstance(instance->instance, NULL /* pAllocator */); + + HeapFree(GetProcessHeap(), 0, instance); +} + VkResult WINAPI X11DRV_vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) { - FIXME("stub: %p, %p, %p\n", pCreateInfo, pAllocator, pInstance); + VkInstance instance = NULL; + VkResult res; + + TRACE("pCreateInfo %p, pAllocater %p, pInstance %p\n", pCreateInfo, pAllocator, pInstance); + + if (pAllocator) + { + FIXME("Support for allocation callbacks not implemented yet\n"); + } wine_vk_instance_dump_create_info(pCreateInfo); - return VK_ERROR_INCOMPATIBLE_DRIVER; -} + if (pCreateInfo->enabledExtensionCount > 0) + { + FIXME("Extensions are not supported yet, aborting!\n"); + res = VK_ERROR_INCOMPATIBLE_DRIVER; + goto err; + } + instance = wine_vk_alloc_dispatchable_object(sizeof(*instance)); + if (!instance) + { + ERR("Failed to allocate memory for instance\n"); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err; + } + + res = pvkCreateInstance(pCreateInfo, NULL /* pAllocator */, &instance->instance); + if (res != VK_SUCCESS) + { + ERR("Failed to create instance, res=%d\n", res); + goto err; + } + + *pInstance = instance; + TRACE("Done, instance=%p wrapped_instance=%p\n", instance, instance->instance); + return VK_SUCCESS; + +err: + if (instance) + wine_vk_instance_free(instance); + + return res; +} VkResult WINAPI X11DRV_vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, VkExtensionProperties* pProperties) diff --git a/dlls/winex11.drv/vulkan_private.h b/dlls/winex11.drv/vulkan_private.h index bb722ddb06..d3fa7be167 100644 --- a/dlls/winex11.drv/vulkan_private.h +++ b/dlls/winex11.drv/vulkan_private.h @@ -26,6 +26,33 @@ #ifdef SONAME_LIBVULKAN +/* Magic value defined by Vulkan ICD / Loader spec */ +#define VULKAN_ICD_MAGIC_VALUE 0x01CDC0DE + +/* Base 'class' for our Vulkan dispatchable objects such as VkDevice and VkInstance. + * This structure MUST be the first element of a dispatchable object as the ICD + * loader depends on it. For now only contains loader_magic, but over time more common + * functionality is expected. + */ +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'. + */ + uintptr_t loader_magic; +}; + +/* Vulkan defines handles for objects through VK_DEFINE_HANDLE. As part of this + * it defines forward declarations for structs '_T', which the implementor (us) + * can use. + */ +struct VkInstance_T +{ + struct wine_vk_base base; + VkInstance instance; /* native instance */ +}; + + struct vulkan_func { const char *name; -- 2.13.6