[PATCH 3/4] d3d12: Use VkPhysicalDevice corresponding to IDXGIAdapter.

Józef Kucia jkucia at codeweavers.com
Tue Mar 12 10:30:20 CDT 2019


Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
---
 dlls/d3d12/Makefile.in  |   2 +-
 dlls/d3d12/d3d12_main.c | 197 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 174 insertions(+), 25 deletions(-)

diff --git a/dlls/d3d12/Makefile.in b/dlls/d3d12/Makefile.in
index ba51960f2c74..5b92997ecdef 100644
--- a/dlls/d3d12/Makefile.in
+++ b/dlls/d3d12/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = d3d12.dll
 IMPORTLIB = d3d12
-IMPORTS   = dxgi dxguid gdi32 user32
+IMPORTS   = dxgi dxguid gdi32 user32 uuid
 EXTRALIBS = $(VKD3D_LIBS)
 EXTRAINCL = $(VKD3D_CFLAGS)
 
diff --git a/dlls/d3d12/d3d12_main.c b/dlls/d3d12/d3d12_main.c
index dace4142ab63..9eef3ad92ddf 100644
--- a/dlls/d3d12/d3d12_main.c
+++ b/dlls/d3d12/d3d12_main.c
@@ -36,6 +36,10 @@
 
 #include <vkd3d.h>
 
+#include "initguid.h"
+#include "wine/wined3d.h"
+#include "wine/winedxgi.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(d3d12);
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
@@ -118,14 +122,13 @@ static const struct vulkan_funcs *get_vk_funcs(void)
     return vk_funcs;
 }
 
-static HRESULT d3d12_get_adapter(IUnknown **adapter, LUID *luid)
+static HRESULT d3d12_get_adapter(IWineDXGIAdapter **wine_adapter, IUnknown *adapter)
 {
-    DXGI_ADAPTER_DESC adapter_desc;
+    IDXGIAdapter *dxgi_adapter = NULL;
     IDXGIFactory4 *factory = NULL;
-    IDXGIAdapter *dxgi_adapter;
     HRESULT hr;
 
-    if (!*adapter)
+    if (!adapter)
     {
         if (FAILED(hr = CreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory)))
         {
@@ -138,37 +141,153 @@ static HRESULT d3d12_get_adapter(IUnknown **adapter, LUID *luid)
             WARN("Failed to enumerate primary adapter, hr %#x.\n", hr);
             goto done;
         }
+
+        adapter = (IUnknown *)dxgi_adapter;
     }
-    else if (FAILED(hr = IUnknown_QueryInterface(*adapter, &IID_IDXGIAdapter, (void **)&dxgi_adapter)))
-    {
+
+    if (FAILED(hr = IUnknown_QueryInterface(adapter, &IID_IWineDXGIAdapter, (void **)wine_adapter)))
         WARN("Invalid adapter %p, hr %#x.\n", adapter, hr);
+
+done:
+    if (dxgi_adapter)
+        IDXGIAdapter_Release(dxgi_adapter);
+    if (factory)
+        IDXGIFactory4_Release(factory);
+
+    return hr;
+}
+
+static BOOL check_vk_instance_extension(const struct vulkan_funcs *vk_funcs, const char *name)
+{
+    VkExtensionProperties *properties;
+    BOOL ret = FALSE;
+    unsigned int i;
+    uint32_t count;
+
+    if (vk_funcs->p_vkEnumerateInstanceExtensionProperties(NULL, &count, NULL) < 0)
+        return FALSE;
+
+    if (!(properties = heap_calloc(count, sizeof(*properties))))
+        return FALSE;
+
+    if (vk_funcs->p_vkEnumerateInstanceExtensionProperties(NULL, &count, properties) >= 0)
+    {
+        for (i = 0; i < count; ++i)
+        {
+            if (!strcmp(properties[i].extensionName, name))
+            {
+                ret = TRUE;
+                break;
+            }
+        }
+    }
+
+    heap_free(properties);
+    return ret;
+}
+
+static VkPhysicalDevice d3d12_get_vk_physical_device(struct vkd3d_instance *instance,
+        const struct vulkan_funcs *vk_funcs, const struct wine_dxgi_adapter_info *adapter_info)
+{
+    PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2 = NULL;
+    PFN_vkGetPhysicalDeviceProperties pfn_vkGetPhysicalDeviceProperties;
+    PFN_vkEnumeratePhysicalDevices pfn_vkEnumeratePhysicalDevices;
+    VkPhysicalDevice vk_physical_device = VK_NULL_HANDLE;
+    VkPhysicalDeviceIDProperties id_properties;
+    VkPhysicalDeviceProperties2 properties2;
+    VkPhysicalDeviceProperties properties;
+    VkPhysicalDevice *vk_physical_devices;
+    VkInstance vk_instance;
+    unsigned int i;
+    uint32_t count;
+    VkResult vr;
+
+    vk_instance = vkd3d_instance_get_vk_instance(instance);
+
+    pfn_vkEnumeratePhysicalDevices = vk_funcs->p_vkGetInstanceProcAddr(vk_instance, "vkEnumeratePhysicalDevices");
+
+    pfn_vkGetPhysicalDeviceProperties = vk_funcs->p_vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties");
+    if (check_vk_instance_extension(vk_funcs, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
+        pfn_vkGetPhysicalDeviceProperties2 = vk_funcs->p_vkGetInstanceProcAddr(vk_instance, "vkGetPhysicalDeviceProperties2KHR");
+
+    if ((vr = pfn_vkEnumeratePhysicalDevices(vk_instance, &count, NULL)) < 0)
+    {
+        WARN("Failed to get device count, vr %d.\n", vr);
+        return VK_NULL_HANDLE;
+    }
+    if (!count)
+    {
+        WARN("No physical device available.\n");
+        return VK_NULL_HANDLE;
+    }
+
+    if (!(vk_physical_devices = heap_calloc(count, sizeof(*vk_physical_devices))))
+        return VK_NULL_HANDLE;
+
+    if ((vr = pfn_vkEnumeratePhysicalDevices(vk_instance, &count, vk_physical_devices)) < 0)
         goto done;
+
+    if (!IsEqualGUID(&adapter_info->driver_uuid, &GUID_NULL) && pfn_vkGetPhysicalDeviceProperties2)
+    {
+        TRACE("Matching adapters by UUIDs.\n");
+
+        for (i = 0; i < count; ++i)
+        {
+            memset(&id_properties, 0, sizeof(id_properties));
+            id_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
+
+            properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+            properties2.pNext = &id_properties;
+
+            pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices[i], &properties2);
+
+            if (!memcmp(id_properties.driverUUID, &adapter_info->driver_uuid, VK_UUID_SIZE)
+                    && !memcmp(id_properties.deviceUUID, &adapter_info->device_uuid, VK_UUID_SIZE))
+            {
+                vk_physical_device = vk_physical_devices[i];
+                break;
+            }
+        }
     }
 
-    if (SUCCEEDED(hr = IDXGIAdapter_GetDesc(dxgi_adapter, &adapter_desc)))
+    if (!vk_physical_device)
     {
-        *adapter = (IUnknown *)dxgi_adapter;
-        *luid = adapter_desc.AdapterLuid;
+        WARN("Matching adapters by PCI IDs.\n");
+
+        for (i = 0; i < count; ++i)
+        {
+            pfn_vkGetPhysicalDeviceProperties(vk_physical_devices[i], &properties);
+
+            if (properties.vendorID == adapter_info->vendor_id && properties.deviceID == adapter_info->device_id)
+            {
+                vk_physical_device = vk_physical_devices[i];
+                break;
+            }
+        }
     }
-    else
+
+    if (!vk_physical_device)
     {
-        IDXGIAdapter_Release(dxgi_adapter);
+        FIXME("Could not find Vulkan physical device for DXGI adapter.\n");
+        vk_physical_device = vk_physical_devices[0];
     }
 
 done:
-    if (factory)
-        IDXGIFactory4_Release(factory);
-
-    return hr;
+    heap_free(vk_physical_devices);
+    return vk_physical_device;
 }
 
 HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_feature_level,
         REFIID iid, void **device)
 {
+    struct vkd3d_optional_instance_extensions_info optional_extensions_info;
     struct vkd3d_instance_create_info instance_create_info;
     struct vkd3d_device_create_info device_create_info;
+    struct wine_dxgi_adapter_info adapter_info;
+    VkPhysicalDevice vk_physical_device;
     const struct vulkan_funcs *vk_funcs;
-    LUID adapter_luid;
+    struct vkd3d_instance *instance;
+    IWineDXGIAdapter *wine_adapter;
     HRESULT hr;
 
     static const char * const instance_extensions[] =
@@ -176,6 +295,10 @@ HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_fe
         VK_KHR_SURFACE_EXTENSION_NAME,
         VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
     };
+    static const char * const optional_instance_extensions[] =
+    {
+        VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+    };
     static const char * const device_extensions[] =
     {
         VK_KHR_SWAPCHAIN_EXTENSION_NAME,
@@ -190,12 +313,22 @@ HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_fe
         return E_FAIL;
     }
 
-    /* FIXME: Get VkPhysicalDevice for IDXGIAdapter. */
-    if (FAILED(hr = d3d12_get_adapter(&adapter, &adapter_luid)))
+    if (FAILED(hr = d3d12_get_adapter(&wine_adapter, adapter)))
         return hr;
 
-    memset(&instance_create_info, 0, sizeof(instance_create_info));
+    if (FAILED(hr = IWineDXGIAdapter_get_adapter_info(wine_adapter, &adapter_info)))
+    {
+        WARN("Failed to get adapter info, hr %#x.\n", hr);
+        goto done;
+    }
+
+    optional_extensions_info.type = VKD3D_STRUCTURE_TYPE_OPTIONAL_INSTANCE_EXTENSIONS_INFO;
+    optional_extensions_info.next = NULL;
+    optional_extensions_info.extensions = optional_instance_extensions;
+    optional_extensions_info.extension_count = ARRAY_SIZE(optional_instance_extensions);
+
     instance_create_info.type = VKD3D_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+    instance_create_info.next = &optional_extensions_info;
     instance_create_info.pfn_signal_event = d3d12_signal_event;
     instance_create_info.pfn_create_thread = d3d12_create_thread;
     instance_create_info.pfn_join_thread = d3d12_join_thread;
@@ -205,17 +338,33 @@ HRESULT WINAPI D3D12CreateDevice(IUnknown *adapter, D3D_FEATURE_LEVEL minimum_fe
     instance_create_info.instance_extensions = instance_extensions;
     instance_create_info.instance_extension_count = ARRAY_SIZE(instance_extensions);
 
-    memset(&device_create_info, 0, sizeof(device_create_info));
+    if (FAILED(hr = vkd3d_create_instance(&instance_create_info, &instance)))
+    {
+        WARN("Failed to create vkd3d instance, hr %#x.\n", hr);
+        goto done;
+    }
+
+    if (!(vk_physical_device = d3d12_get_vk_physical_device(instance, vk_funcs, &adapter_info)))
+        goto done_instance;
+
     device_create_info.type = VKD3D_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+    device_create_info.next = NULL;
     device_create_info.minimum_feature_level = minimum_feature_level;
-    device_create_info.instance_create_info = &instance_create_info;
+    device_create_info.instance = instance;
+    device_create_info.instance_create_info = NULL;
+    device_create_info.vk_physical_device = vk_physical_device;
     device_create_info.device_extensions = device_extensions;
     device_create_info.device_extension_count = ARRAY_SIZE(device_extensions);
-    device_create_info.parent = adapter;
-    device_create_info.adapter_luid = adapter_luid;
+    device_create_info.parent = (IUnknown *)wine_adapter;
+    device_create_info.adapter_luid = adapter_info.luid;
 
     hr = vkd3d_create_device(&device_create_info, iid, device);
-    IUnknown_Release(adapter);
+
+done_instance:
+    vkd3d_instance_decref(instance);
+
+done:
+    IWineDXGIAdapter_Release(wine_adapter);
     return hr;
 }
 
-- 
2.19.2




More information about the wine-devel mailing list