From: Roderick Colenbrander thunderbird2k@gmail.com
Doom and Wolfenstein II use vkGetDeviceProcAddr to load all their function pointers, while they are supposed to use vkGetInstanceProcAddr for the instance ones. For now we need to allow this broken behavior.
Signed-off-by: Roderick Colenbrander thunderbird2k@gmail.com Signed-off-by: Józef Kucia jkucia@codeweavers.com ---
For time being, it's a reasonable workaround to run major Vulkan titles. Depending on further developments, we may be able to drop the workaround, or we should activate it only for the affected apps (based on VkApplicationInfo).
--- dlls/winevulkan/vulkan.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index c0fc810a14a2..5062701e61d5 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -902,7 +902,26 @@ PFN_vkVoidFunction WINAPI wine_vkGetDeviceProcAddr(VkDevice device, const char * if (func) return func;
- TRACE("Function %s not found\n", debugstr_a(name)); + /* vkGetDeviceProcAddr was intended for loading device and subdevice functions. + * idTech 6 titles such as Doom and Wolfenstein II, however use it also for + * loading of instance functions. This is undefined behavior as the specification + * disallows using any of the returned function pointers outside of device / + * subdevice objects. The games don't actually use the function pointers and if they + * did, they would crash as VkInstance / VkPhysicalDevice parameters need unwrapping. + * Khronos clarified behavior in the Vulkan spec and expects drivers to get updated, + * however it would require both driver and game fixes. Since it are major titles + * it is not clear what will happen. At least for now we need the hack below. + * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323 + * https://github.com/KhronosGroup/Vulkan-Docs/issues/655 + */ + func = wine_vk_get_instance_proc_addr(name); + if (func) + { + WARN("Returning instance function '%s'.\n", debugstr_a(name)); + return func; + } + + TRACE("Function %s not found.\n", debugstr_a(name)); return NULL; }
Signed-off-by: Józef Kucia jkucia@codeweavers.com --- dlls/winevulkan/vulkan.c | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-)
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 5062701e61d5..b9326baef6a3 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -838,42 +838,27 @@ static VkResult WINAPI wine_vkEnumerateInstanceExtensionProperties(const char *l return res; }
-VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *device_count, +VkResult WINAPI wine_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *count, VkPhysicalDevice *devices) { - VkResult res; - unsigned int i, num_copies; + unsigned int i;
- TRACE("%p %p %p\n", instance, device_count, devices); + TRACE("%p %p %p\n", instance, count, devices);
if (!devices) { - *device_count = instance->num_phys_devs; + *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++) + *count = min(*count, instance->num_phys_devs); + for (i = 0; i < *count; i++) { devices[i] = instance->phys_devs[i]; } - *device_count = num_copies;
- TRACE("Returning %u devices\n", *device_count); - return res; + TRACE("Returning %u devices.\n", *count); + return *count < instance->num_phys_devs ? VK_INCOMPLETE : VK_SUCCESS; }
void WINAPI wine_vkFreeCommandBuffers(VkDevice device, VkCommandPool pool, uint32_t count,