[PATCH 2/3] winevulkan: Implement vkEnumeratePhysicalDevices.
Józef Kucia
joseph.kucia at gmail.com
Fri Mar 2 05:57:43 CST 2018
On Fri, Mar 2, 2018 at 7:13 AM, Roderick Colenbrander
<thunderbird2k at gmail.com> wrote:
> Signed-off-by: Roderick Colenbrander <thunderbird2k at gmail.com>
> ---
> dlls/winevulkan/make_vulkan | 1 +
> dlls/winevulkan/vulkan.c | 140 +++++++++++++++++++++++++++++++++++++++
> dlls/winevulkan/vulkan_private.h | 14 ++++
> dlls/winevulkan/vulkan_thunks.c | 6 --
> dlls/winevulkan/vulkan_thunks.h | 1 +
> 5 files changed, 156 insertions(+), 6 deletions(-)
>
> diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
> index 5657b70c4c..3b045db8a9 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 0f48d971e2..234be589ae 100644
> --- a/dlls/winevulkan/vulkan.c
> +++ b/dlls/winevulkan/vulkan.c
> @@ -58,6 +58,85 @@ 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)
> + {
> + instance->num_phys_devs = 0;
instance->phys_devs isn't initialized.
> + return VK_SUCCESS;
> + }
> +
> + tmp_phys_devs = heap_alloc(num_phys_devs * sizeof(*tmp_phys_devs));
> + if (!tmp_phys_devs)
> + return VK_ERROR_OUT_OF_HOST_MEMORY;
This leaves a lot of fields uninitialized in "instance". We don't want
to crash in wine_vk_instance_free().
> +
> + res = instance->funcs.p_vkEnumeratePhysicalDevices(instance->instance, &num_phys_devs, tmp_phys_devs);
> + if (res != VK_SUCCESS)
> + goto err;
> +
> + instance->phys_devs = heap_alloc(num_phys_devs * sizeof(*instance->phys_devs));
heap_calloc() may be more suitable.
> + 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++)
> + {
> + VkPhysicalDevice phys_dev = heap_alloc(sizeof(*phys_dev));
struct VkPhysicalDevice_T *
> + 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;
> + }
> + instance->num_phys_devs = num_phys_devs;
> +
> + heap_free(tmp_phys_devs);
> + return VK_SUCCESS;
> +
> +err:
> + if (tmp_phys_devs)
> + heap_free(tmp_phys_devs);
It's fine to call heap_free() with NULL.
> +
> + if (instance->phys_devs)
> + {
> + for (i = 0; i < instance->num_phys_devs; i++)
> + {
> + heap_free(instance->phys_devs[i]);
> + instance->phys_devs[i] = NULL;
> + }
> + heap_free(instance->phys_devs);
> + instance->num_phys_devs = 0;
> + instance->phys_devs = NULL;
> + }
> +
> + 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 +145,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);
> + }
It might crash because "phys_devs" is uninitialized. We probably want
to use heap_alloc_zero() to allocate "instance".
> +
> if (instance->instance)
> vk_funcs->p_vkDestroyInstance(instance->instance, NULL /* allocator */);
>
> @@ -108,6 +198,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 +236,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 %d 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 16aa0ce55c..8ef4b924a2 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 c1c0b079a5..ae4f773ef0 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 087fa17d0e..26e114ab74 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
> --
> 2.14.3
>
>
>
More information about the wine-devel
mailing list