<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta content="text/html;charset=UTF-8" http-equiv="Content-Type"></head><body ><div style="font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt;"><div>I think it would make more sense to fill in the LUID on the WineVulkan side instead and make your DXGI read that.<br></div><div><br></div><div>That would avoid breaking DXVK, and makes more sense as a concept imo.<br></div><div><br></div><div>Cheers<br></div><div> - Josh 🐸<br></div><div data-zbluepencil-ignore="true" style="" class="zmail_extra"><div><br></div><div id="Zm-_Id_-Sgn1">---- On Fri, 06 Mar 2020 23:23:21 +0000 <b>Brendan Shanks <<a target="_blank" href="mailto:bshanks@codeweavers.com">bshanks@codeweavers.com</a>></b> wrote ----<br></div><div><br></div><blockquote style="border-left: 1px solid rgb(204, 204, 204); padding-left: 6px; margin: 0px 0px 0px 5px;"><div>--- <br>Red Dead Redemption 2 relies on the deviceLUID returned by <br>vkGetPhysicalDeviceProperties2() matching up with the LUID reported by <br>other Windows APIs. This patch uses DXGI to enumerate adapters, and uses <br>the LUID of the D3D adapter matching the UUID provided through Vulkan. <br> <br>The patch works, but I could see problems arising in case EnumAdapters() <br>was backed by Vulkan and called vkGetPhysicalDeviceProperties2() itself. <br> <br>Would it be preferable to cache the UUID/LUID pairs in wine_vk_init()? <br>Or should DXGI not be used at all, in favor of reading these out of the <br>registry (with changes needed to wined3d)? <br> <br> <br> dlls/winevulkan/Makefile.in     |  2 +- <br> dlls/winevulkan/make_vulkan     |  2 + <br> dlls/winevulkan/vulkan.c        | 89 +++++++++++++++++++++++++++++++++ <br> dlls/winevulkan/vulkan_thunks.c | 10 +--- <br> dlls/winevulkan/vulkan_thunks.h |  4 ++ <br> 5 files changed, 98 insertions(+), 9 deletions(-) <br> <br>diff --git a/dlls/winevulkan/Makefile.in b/dlls/winevulkan/Makefile.in <br>index e0bca6fad7..c112581e1e 100644 <br>--- a/dlls/winevulkan/Makefile.in <br>+++ b/dlls/winevulkan/Makefile.in <br>@@ -1,6 +1,6 @@ <br> MODULE    = winevulkan.dll <br> IMPORTLIB = winevulkan <br>-IMPORTS   = user32 gdi32 <br>+IMPORTS   = dxgi user32 gdi32 <br> <br> C_SRCS = \ <br>     vulkan.c \ <br>diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan <br>index 3593410041..1879d640e0 100755 <br>--- a/dlls/winevulkan/make_vulkan <br>+++ b/dlls/winevulkan/make_vulkan <br>@@ -165,6 +165,8 @@ FUNCTION_OVERRIDES = { <br> "vkGetPhysicalDeviceExternalFenceProperties" : {"dispatch" : False, "driver" : False, "thunk" : False}, <br> "vkGetPhysicalDeviceExternalSemaphoreProperties" : {"dispatch" : False, "driver" : False, "thunk" : False}, <br> "vkGetPhysicalDeviceImageFormatProperties2" : {"dispatch" : True, "driver" : False, "thunk" : True, "private_thunk" : True}, <br>+    "vkGetPhysicalDeviceProperties2" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True}, <br>+    "vkGetPhysicalDeviceProperties2KHR" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True}, <br> <br> # Device functions <br> "vkAllocateCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : False}, <br>diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c <br>index 59472bcef8..2ef39ada79 100644 <br>--- a/dlls/winevulkan/vulkan.c <br>+++ b/dlls/winevulkan/vulkan.c <br>@@ -19,10 +19,16 @@ <br> <br> #include <stdarg.h> <br> <br>+#define COBJMACROS <br> #include "windef.h" <br> #include "winbase.h" <br> #include "winuser.h" <br> <br>+#include "initguid.h" <br>+#include "dxgi.h" <br>+#include "wine/wined3d.h" <br>+#include "wine/winedxgi.h" <br>+ <br> #include "vulkan_private.h" <br> <br> WINE_DEFAULT_DEBUG_CHANNEL(vulkan); <br>@@ -1261,6 +1267,89 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDev <br> properties->externalSemaphoreFeatures = 0; <br> } <br> <br>+static BOOL get_luid_for_device_uuid(const UUID *uuid, LUID *luid) <br>+{ <br>+    UINT i = 0; <br>+    BOOL found = FALSE; <br>+    IDXGIFactory *factory = NULL; <br>+    IDXGIAdapter *adapter = NULL; <br>+ <br>+    if (FAILED(CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory))) return FALSE; <br>+ <br>+    while (!found && IDXGIFactory_EnumAdapters(factory, i, &adapter) != DXGI_ERROR_NOT_FOUND) <br>+    { <br>+        IWineDXGIAdapter *wine_adapter = NULL; <br>+        if (SUCCEEDED(IUnknown_QueryInterface(adapter, &IID_IWineDXGIAdapter, (void **)&wine_adapter))) <br>+        { <br>+            struct wine_dxgi_adapter_info adapter_info; <br>+            if (SUCCEEDED(IWineDXGIAdapter_get_adapter_info(wine_adapter, &adapter_info))) <br>+            { <br>+                if (IsEqualGUID(uuid, &adapter_info.device_uuid)) <br>+                { <br>+                    *luid = adapter_info.luid; <br>+                    found = TRUE; <br>+                } <br>+            } <br>+ <br>+            IWineDXGIAdapter_Release(wine_adapter); <br>+        } <br>+ <br>+        IDXGIAdapter_Release(adapter); <br>+        i++; <br>+    } <br>+ <br>+    if (factory) IDXGIFactory_Release(factory); <br>+    return found; <br>+} <br>+ <br>+void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physical_device, <br>+        VkPhysicalDeviceProperties2 *properties) <br>+{ <br>+    VkPhysicalDeviceIDProperties *idprops; <br>+ <br>+    TRACE("%p, %p\n", physical_device, properties); <br>+    thunk_vkGetPhysicalDeviceProperties2(physical_device, properties); <br>+ <br>+    if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES))) <br>+    { <br>+        UUID *deviceUUID = (UUID *)idprops->deviceUUID; <br>+        LUID *luid = (LUID *)idprops->deviceLUID; <br>+        if (get_luid_for_device_uuid(deviceUUID, luid)) <br>+        { <br>+            idprops->deviceNodeMask = 1; <br>+            idprops->deviceLUIDValid = VK_TRUE; <br>+        } <br>+        else <br>+        { <br>+            WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID)); <br>+        } <br>+    } <br>+} <br>+ <br>+void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physical_device, <br>+        VkPhysicalDeviceProperties2 *properties) <br>+{ <br>+    VkPhysicalDeviceIDProperties *idprops; <br>+ <br>+    TRACE("%p, %p\n", physical_device, properties); <br>+    thunk_vkGetPhysicalDeviceProperties2KHR(physical_device, properties); <br>+ <br>+    if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES))) <br>+    { <br>+        UUID *deviceUUID = (UUID *)idprops->deviceUUID; <br>+        LUID *luid = (LUID *)idprops->deviceLUID; <br>+        if (get_luid_for_device_uuid(deviceUUID, luid)) <br>+        { <br>+            idprops->deviceNodeMask = 1; <br>+            idprops->deviceLUIDValid = VK_TRUE; <br>+        } <br>+        else <br>+        { <br>+            WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID)); <br>+        } <br>+    } <br>+} <br>+ <br> BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) <br> { <br> TRACE("%p, %u, %p\n", hinst, reason, reserved); <br>diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c <br>index fecf9ab502..89878f189a 100644 <br>--- a/dlls/winevulkan/vulkan_thunks.c <br>+++ b/dlls/winevulkan/vulkan_thunks.c <br>@@ -4268,34 +4268,28 @@ void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, <br> #endif <br> } <br> <br>-void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) <br>+void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) <br> { <br> #if defined(USE_STRUCT_CONVERSION) <br> VkPhysicalDeviceProperties2_host pProperties_host; <br>-    TRACE("%p, %p\n", physicalDevice, pProperties); <br>- <br> convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host); <br> physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, &pProperties_host); <br> <br> convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties); <br> #else <br>-    TRACE("%p, %p\n", physicalDevice, pProperties); <br> physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, pProperties); <br> #endif <br> } <br> <br>-static void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) <br>+void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) <br> { <br> #if defined(USE_STRUCT_CONVERSION) <br> VkPhysicalDeviceProperties2_host pProperties_host; <br>-    TRACE("%p, %p\n", physicalDevice, pProperties); <br>- <br> convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host); <br> physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, &pProperties_host); <br> <br> convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties); <br> #else <br>-    TRACE("%p, %p\n", physicalDevice, pProperties); <br> physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, pProperties); <br> #endif <br> } <br>diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h <br>index 01c1efb277..9896112176 100644 <br>--- a/dlls/winevulkan/vulkan_thunks.h <br>+++ b/dlls/winevulkan/vulkan_thunks.h <br>@@ -64,11 +64,15 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice <br> void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) DECLSPEC_HIDDEN; <br> VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties); <br> VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; <br>+void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties); <br>+void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN; <br> VkResult WINAPI wine_vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence); <br> <br> /* Private thunks */ <br> VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; <br> VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN; <br>+void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN; <br>+void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN; <br> <br> typedef struct VkAcquireNextImageInfoKHR_host <br> { <br>-- <br>2.24.1 <br> <br> <br></div></blockquote></div><div><br></div></div><br></body></html>