--- Red Dead Redemption 2 relies on the deviceLUID returned by vkGetPhysicalDeviceProperties2() matching up with the LUID reported by other Windows APIs. This patch uses DXGI to enumerate adapters, and uses the LUID of the D3D adapter matching the UUID provided through Vulkan.
The patch works, but I could see problems arising in case EnumAdapters() was backed by Vulkan and called vkGetPhysicalDeviceProperties2() itself.
Would it be preferable to cache the UUID/LUID pairs in wine_vk_init()? Or should DXGI not be used at all, in favor of reading these out of the registry (with changes needed to wined3d)?
dlls/winevulkan/Makefile.in | 2 +- dlls/winevulkan/make_vulkan | 2 + dlls/winevulkan/vulkan.c | 89 +++++++++++++++++++++++++++++++++ dlls/winevulkan/vulkan_thunks.c | 10 +--- dlls/winevulkan/vulkan_thunks.h | 4 ++ 5 files changed, 98 insertions(+), 9 deletions(-)
diff --git a/dlls/winevulkan/Makefile.in b/dlls/winevulkan/Makefile.in index e0bca6fad7..c112581e1e 100644 --- a/dlls/winevulkan/Makefile.in +++ b/dlls/winevulkan/Makefile.in @@ -1,6 +1,6 @@ MODULE = winevulkan.dll IMPORTLIB = winevulkan -IMPORTS = user32 gdi32 +IMPORTS = dxgi user32 gdi32
C_SRCS = \ vulkan.c \ diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan index 3593410041..1879d640e0 100755 --- a/dlls/winevulkan/make_vulkan +++ b/dlls/winevulkan/make_vulkan @@ -165,6 +165,8 @@ FUNCTION_OVERRIDES = { "vkGetPhysicalDeviceExternalFenceProperties" : {"dispatch" : False, "driver" : False, "thunk" : False}, "vkGetPhysicalDeviceExternalSemaphoreProperties" : {"dispatch" : False, "driver" : False, "thunk" : False}, "vkGetPhysicalDeviceImageFormatProperties2" : {"dispatch" : True, "driver" : False, "thunk" : True, "private_thunk" : True}, + "vkGetPhysicalDeviceProperties2" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True}, + "vkGetPhysicalDeviceProperties2KHR" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True},
# Device functions "vkAllocateCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : False}, diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c index 59472bcef8..2ef39ada79 100644 --- a/dlls/winevulkan/vulkan.c +++ b/dlls/winevulkan/vulkan.c @@ -19,10 +19,16 @@
#include <stdarg.h>
+#define COBJMACROS #include "windef.h" #include "winbase.h" #include "winuser.h"
+#include "initguid.h" +#include "dxgi.h" +#include "wine/wined3d.h" +#include "wine/winedxgi.h" + #include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan); @@ -1261,6 +1267,89 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDev properties->externalSemaphoreFeatures = 0; }
+static BOOL get_luid_for_device_uuid(const UUID *uuid, LUID *luid) +{ + UINT i = 0; + BOOL found = FALSE; + IDXGIFactory *factory = NULL; + IDXGIAdapter *adapter = NULL; + + if (FAILED(CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory))) return FALSE; + + while (!found && IDXGIFactory_EnumAdapters(factory, i, &adapter) != DXGI_ERROR_NOT_FOUND) + { + IWineDXGIAdapter *wine_adapter = NULL; + if (SUCCEEDED(IUnknown_QueryInterface(adapter, &IID_IWineDXGIAdapter, (void **)&wine_adapter))) + { + struct wine_dxgi_adapter_info adapter_info; + if (SUCCEEDED(IWineDXGIAdapter_get_adapter_info(wine_adapter, &adapter_info))) + { + if (IsEqualGUID(uuid, &adapter_info.device_uuid)) + { + *luid = adapter_info.luid; + found = TRUE; + } + } + + IWineDXGIAdapter_Release(wine_adapter); + } + + IDXGIAdapter_Release(adapter); + i++; + } + + if (factory) IDXGIFactory_Release(factory); + return found; +} + +void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physical_device, + VkPhysicalDeviceProperties2 *properties) +{ + VkPhysicalDeviceIDProperties *idprops; + + TRACE("%p, %p\n", physical_device, properties); + thunk_vkGetPhysicalDeviceProperties2(physical_device, properties); + + if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES))) + { + UUID *deviceUUID = (UUID *)idprops->deviceUUID; + LUID *luid = (LUID *)idprops->deviceLUID; + if (get_luid_for_device_uuid(deviceUUID, luid)) + { + idprops->deviceNodeMask = 1; + idprops->deviceLUIDValid = VK_TRUE; + } + else + { + WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID)); + } + } +} + +void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physical_device, + VkPhysicalDeviceProperties2 *properties) +{ + VkPhysicalDeviceIDProperties *idprops; + + TRACE("%p, %p\n", physical_device, properties); + thunk_vkGetPhysicalDeviceProperties2KHR(physical_device, properties); + + if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES))) + { + UUID *deviceUUID = (UUID *)idprops->deviceUUID; + LUID *luid = (LUID *)idprops->deviceLUID; + if (get_luid_for_device_uuid(deviceUUID, luid)) + { + idprops->deviceNodeMask = 1; + idprops->deviceLUIDValid = VK_TRUE; + } + else + { + WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID)); + } + } +} + BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { TRACE("%p, %u, %p\n", hinst, reason, reserved); diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c index fecf9ab502..89878f189a 100644 --- a/dlls/winevulkan/vulkan_thunks.c +++ b/dlls/winevulkan/vulkan_thunks.c @@ -4268,34 +4268,28 @@ void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, #endif }
-void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) +void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) { #if defined(USE_STRUCT_CONVERSION) VkPhysicalDeviceProperties2_host pProperties_host; - TRACE("%p, %p\n", physicalDevice, pProperties); - convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host); physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, &pProperties_host);
convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties); #else - TRACE("%p, %p\n", physicalDevice, pProperties); physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, pProperties); #endif }
-static void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) +void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) { #if defined(USE_STRUCT_CONVERSION) VkPhysicalDeviceProperties2_host pProperties_host; - TRACE("%p, %p\n", physicalDevice, pProperties); - convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host); physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, &pProperties_host);
convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties); #else - TRACE("%p, %p\n", physicalDevice, pProperties); physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, pProperties); #endif } diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h index 01c1efb277..9896112176 100644 --- a/dlls/winevulkan/vulkan_thunks.h +++ b/dlls/winevulkan/vulkan_thunks.h @@ -64,11 +64,15 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties); VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; +void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties); +void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN; VkResult WINAPI wine_vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence);
/* Private thunks */ VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; +void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN; +void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
typedef struct VkAcquireNextImageInfoKHR_host {