Module: wine Branch: master Commit: a553e88fba0291a266869fdbfc981d829c0ded48 URL: https://source.winehq.org/git/wine.git/?a=commit;h=a553e88fba0291a266869fdbf...
Author: Roderick Colenbrander thunderbird2k@gmail.com Date: Tue Mar 6 17:28:48 2018 +0100
winevulkan: Implement vkEnumeratePhysicalDevices.
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com Signed-off-by: Józef Kucia jkucia@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/winevulkan/make_vulkan | 1 + dlls/winevulkan/vulkan.c | 126 ++++++++++++++++++++++++++++++++++++++- dlls/winevulkan/vulkan_private.h | 14 +++++ dlls/winevulkan/vulkan_thunks.c | 6 -- dlls/winevulkan/vulkan_thunks.h | 1 + 5 files changed, 141 insertions(+), 7 deletions(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 5657b70..3b045db 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -90,6 +90,7 @@ FUNCTION_OVERRIDES = {
# Instance functions "vkDestroyInstance" : {"dispatch" : True, "driver" : True, "thunk" : False }, + "vkEnumeratePhysicalDevices" : {"dispatch" : True, "driver" : False, "thunk" : False}, }
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 0f48d97..a2223cf 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -58,6 +58,69 @@ static BOOL wine_vk_init(void) return TRUE; }
+/* Helper function which stores wrapped physical devices in the instance object. */ +static VkResult wine_vk_instance_load_physical_devices(struct VkInstance_T *instance) +{ + VkResult res; + struct VkPhysicalDevice_T **tmp_phys_devs = NULL; + uint32_t num_phys_devs = 0; + unsigned int i; + + res = instance->funcs.p_vkEnumeratePhysicalDevices(instance->instance, &num_phys_devs, NULL); + if (res != VK_SUCCESS) + { + ERR("Failed to enumerate physical devices, res=%d\n", res); + return res; + } + + /* Don't bother with any of the rest if the system just lacks devices. */ + if (num_phys_devs == 0) + return VK_SUCCESS; + + tmp_phys_devs = heap_calloc(num_phys_devs, sizeof(*tmp_phys_devs)); + if (!tmp_phys_devs) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + res = instance->funcs.p_vkEnumeratePhysicalDevices(instance->instance, &num_phys_devs, tmp_phys_devs); + if (res != VK_SUCCESS) + goto err; + + instance->phys_devs = heap_calloc(num_phys_devs, sizeof(*instance->phys_devs)); + if (!instance->phys_devs) + { + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err; + } + + /* Wrap each native physical device handle into a dispatchable object for the ICD loader. */ + for (i = 0; i < num_phys_devs; i++) + { + struct VkPhysicalDevice_T *phys_dev = heap_alloc(sizeof(*phys_dev)); + if (!phys_dev) + { + ERR("Unable to allocate memory for physical device!\n"); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto err; + } + + phys_dev->base.loader_magic = VULKAN_ICD_MAGIC_VALUE; + phys_dev->instance = instance; + phys_dev->phys_dev = tmp_phys_devs[i]; + + instance->phys_devs[i] = phys_dev; + instance->num_phys_devs = i + 1; + } + instance->num_phys_devs = num_phys_devs; + + heap_free(tmp_phys_devs); + return VK_SUCCESS; + +err: + heap_free(tmp_phys_devs); + + return res; +} + /* Helper function used for freeing an instance structure. This function supports full * and partial object cleanups and can thus be used for vkCreateInstance failures. */ @@ -66,6 +129,17 @@ static void wine_vk_instance_free(struct VkInstance_T *instance) if (!instance) return;
+ if (instance->phys_devs) + { + unsigned int i; + + for (i = 0; i < instance->num_phys_devs; i++) + { + heap_free(&instance->phys_devs[i]); + } + heap_free(instance->phys_devs); + } + if (instance->instance) vk_funcs->p_vkDestroyInstance(instance->instance, NULL /* allocator */);
@@ -83,7 +157,7 @@ static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_ if (allocator) FIXME("Support for allocation callbacks not implemented yet\n");
- object = heap_alloc(sizeof(*object)); + object = heap_alloc_zero(sizeof(*object)); if (!object) { ERR("Failed to allocate memory for instance\n"); @@ -108,6 +182,18 @@ static VkResult WINAPI wine_vkCreateInstance(const VkInstanceCreateInfo *create_ ALL_VK_INSTANCE_FUNCS() #undef USE_VK_FUNC
+ /* Cache physical devices for vkEnumeratePhysicalDevices within the instance as + * each vkPhysicalDevice is a dispatchable object, which means we need to wrap + * the native physical device and present those the application. + * Cleanup happens as part of wine_vkDestroyInstance. + */ + res = wine_vk_instance_load_physical_devices(object); + if (res != VK_SUCCESS) + { + ERR("Failed to cache physical devices, res=%d\n", res); + goto err; + } + *instance = object; TRACE("Done, instance=%p native_instance=%p\n", object, object->instance); return VK_SUCCESS; @@ -134,6 +220,44 @@ static VkResult WINAPI wine_vkEnumerateInstanceExtensionProperties(const char *l return vk_funcs->p_vkEnumerateInstanceExtensionProperties(layer_name, count, properties); }
+VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *device_count, + VkPhysicalDevice *devices) +{ + VkResult res; + unsigned int i, num_copies; + + TRACE("%p %p %p\n", instance, device_count, devices); + + if (!devices) + { + *device_count = instance->num_phys_devs; + return VK_SUCCESS; + } + + if (*device_count < instance->num_phys_devs) + { + /* Incomplete is a type of success used to signal the application + * that not all devices got copied. + */ + num_copies = *device_count; + res = VK_INCOMPLETE; + } + else + { + num_copies = instance->num_phys_devs; + res = VK_SUCCESS; + } + + for (i = 0; i < num_copies; i++) + { + devices[i] = instance->phys_devs[i]; + } + *device_count = num_copies; + + TRACE("Returning %u devices\n", *device_count); + return res; +} + static PFN_vkVoidFunction WINAPI wine_vkGetInstanceProcAddr(VkInstance instance, const char *name) { void *func; diff --git a/dlls/winevulkan/vulkan_private.h b/dlls/winevulkan/vulkan_private.h index 16aa0ce..8ef4b92 100644 --- a/dlls/winevulkan/vulkan_private.h +++ b/dlls/winevulkan/vulkan_private.h @@ -52,7 +52,21 @@ struct VkInstance_T { struct wine_vk_base base; struct vulkan_instance_funcs funcs; + + /* We cache devices as we need to wrap them as they are + * dispatchable objects. + */ + uint32_t num_phys_devs; + struct VkPhysicalDevice_T **phys_devs; + VkInstance instance; /* native instance */ };
+struct VkPhysicalDevice_T +{ + struct wine_vk_base base; + struct VkInstance_T *instance; /* parent */ + VkPhysicalDevice phys_dev; /* native physical device */ +}; + #endif /* __WINE_VULKAN_PRIVATE_H */ diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index c1c0b07..ae4f773 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -28,12 +28,6 @@ static VkResult WINAPI wine_vkEnumerateDeviceLayerProperties(VkPhysicalDevice ph return VK_ERROR_OUT_OF_HOST_MEMORY; }
-static VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) -{ - FIXME("stub: %p, %p, %p\n", instance, pPhysicalDeviceCount, pPhysicalDevices); - return VK_ERROR_OUT_OF_HOST_MEMORY; -} - static void WINAPI wine_vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) { FIXME("stub: %p, %p\n", physicalDevice, pFeatures); diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 087fa17..26e114a 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -8,6 +8,7 @@ void *wine_vk_get_instance_proc_addr(const char *name) DECLSPEC_HIDDEN;
/* Functions for which we have custom implementations outside of the thunks. */ void WINAPI wine_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) DECLSPEC_HIDDEN; +VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) DECLSPEC_HIDDEN;
/* For use by vkInstance and children */ struct vulkan_instance_funcs