[PATCH 08/10] winex11: Add initial vkCreateInstance implementation.

Roderick Colenbrander thunderbird2k at gmail.com
Tue Oct 31 12:24:54 CDT 2017


Signed-off-by: Roderick Colenbrander <thunderbird2k at gmail.com>
---
 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




More information about the wine-patches mailing list