Signed-off-by: Józef Kucia jkucia@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; }
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=49195
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)