Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- dlls/dxgi/tests/dxgi.c | 4 +-- dlls/wined3d/Makefile.in | 2 +- dlls/wined3d/directx.c | 66 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_main.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 02cf744be3..b42b76186c 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -777,7 +777,7 @@ static void test_adapter_luid(void) ok(hr == DXGI_ERROR_NOT_FOUND, "Got unexpected hr %#x.\n", hr);
/* Older versions of WARP aren't enumerated by IDXGIFactory_EnumAdapters(). */ - todo_wine ok(found_adapter_count == 1 || broken(is_null_luid_adapter), + ok(found_adapter_count == 1 || broken(is_null_luid_adapter), "Found %u adapters for LUID %08x:%08x.\n", found_adapter_count, device_adapter_desc.AdapterLuid.HighPart, device_adapter_desc.AdapterLuid.LowPart); @@ -796,7 +796,7 @@ static void test_adapter_luid(void)
hr = IDXGIFactory4_EnumAdapterByLuid(factory4, device_adapter_desc.AdapterLuid, &IID_IDXGIAdapter, (void **)&adapter); - todo_wine ok(hr == S_OK, "Failed to enum adapter by LUID, hr %#x.\n", hr); + ok(hr == S_OK, "Failed to enum adapter by LUID, hr %#x.\n", hr); if (SUCCEEDED(hr)) { hr = IDXGIAdapter_GetDesc(adapter, &desc); diff --git a/dlls/wined3d/Makefile.in b/dlls/wined3d/Makefile.in index 39fed381d9..9f95ace137 100644 --- a/dlls/wined3d/Makefile.in +++ b/dlls/wined3d/Makefile.in @@ -1,6 +1,6 @@ MODULE = wined3d.dll IMPORTLIB = wined3d -IMPORTS = opengl32 user32 gdi32 advapi32 +IMPORTS = opengl32 user32 gdi32 advapi32 setupapi
C_SRCS = \ adapter_gl.c \ diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 544c76ed5c..ee7b75a38c 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -26,6 +26,10 @@
#include "wined3d_private.h" #include "winternl.h" +#include "initguid.h" +#include "devguid.h" +#include "devpkey.h" +#include "setupapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
@@ -43,6 +47,8 @@ enum wined3d_driver_model /* The d3d device ID */ static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
+DEFINE_DEVPROPKEY(DEVPROPKEY_DISPLAY_ADAPTER_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2); + /********************************************************** * Utility functions follow **********************************************************/ @@ -100,6 +106,7 @@ ULONG CDECL wined3d_decref(struct wined3d *wined3d) { wined3d_adapter_cleanup(&wined3d->adapters[i]); } + heap_free(wined3d->adapters); heap_free(wined3d); }
@@ -739,6 +746,7 @@ HRESULT CDECL wined3d_get_output_desc(const struct wined3d *wined3d, unsigned in return hr;
memcpy(desc->device_name, adapter->device_name, sizeof(desc->device_name)); + SetRect(&desc->desktop_rect, 0, 0, mode.width, mode.height); OffsetRect(&desc->desktop_rect, adapter->monitor_position.x, adapter->monitor_position.y); /* FIXME: We should get this from EnumDisplayDevices() when the adapters @@ -2529,18 +2537,12 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, unsigned int o adapter->ordinal = ordinal;
display_device.cb = sizeof(display_device); - EnumDisplayDevicesW(NULL, ordinal, &display_device, 0); + /* FIXME: EnumDisplayDevicesW is a stub. It doesn't support multiple displays and adapters. + * Use the first device name for now. */ + EnumDisplayDevicesW(NULL, 0, &display_device, 0); TRACE("Display device: %s.\n", debugstr_w(display_device.DeviceName)); strcpyW(adapter->device_name, display_device.DeviceName);
- if (!AllocateLocallyUniqueId(&adapter->luid)) - { - ERR("Failed to set adapter LUID (%#x).\n", GetLastError()); - return FALSE; - } - TRACE("Allocated LUID %08x:%08x for adapter %p.\n", - adapter->luid.HighPart, adapter->luid.LowPart, adapter); - adapter->formats = NULL;
if (wined3d_creation_flags & WINED3D_NO3D) @@ -2557,17 +2559,55 @@ const struct wined3d_parent_ops wined3d_null_parent_ops =
HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) { + HDEVINFO devinfo; + SP_DEVINFO_DATA devinfo_data = {sizeof(SP_DEVINFO_DATA)}; + DEVPROPTYPE property_type; + UINT i = 0, adapter_count = 0; + BOOL ret = E_FAIL; + wined3d->ref = 1; wined3d->flags = flags;
TRACE("Initialising adapters.\n");
- if (!wined3d_adapter_init(&wined3d->adapters[0], 0, flags)) + devinfo = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT); + if (devinfo == INVALID_HANDLE_VALUE) { - WARN("Failed to initialise adapter.\n"); + ERR("Failed to get adapter list.\n"); return E_FAIL; } - wined3d->adapter_count = 1;
- return WINED3D_OK; + while (SetupDiEnumDeviceInfo(devinfo, i++, &devinfo_data)) + adapter_count++; + + wined3d->adapters = heap_alloc_zero(sizeof(struct wined3d_adapter) * adapter_count); + if (!wined3d->adapters) + { + ret = E_OUTOFMEMORY; + goto fail; + } + + for (i = 0; SetupDiEnumDeviceInfo(devinfo, i, &devinfo_data); ++i) + { + property_type = DEVPROP_TYPE_UINT64; + if (!SetupDiGetDevicePropertyW(devinfo, &devinfo_data, &DEVPROPKEY_DISPLAY_ADAPTER_LUID, &property_type, + (BYTE *)&wined3d->adapters[i].luid, sizeof(LUID), NULL, 0)) + { + WARN("Failed to get adapter %u luid.\n", i); + goto fail; + } + + if (!wined3d_adapter_init(&wined3d->adapters[i], i, flags)) + { + WARN("Failed to initialise adapter %u.\n", i); + goto fail; + } + } + + wined3d->adapter_count = adapter_count; + + ret = WINED3D_OK; +fail: + SetupDiDestroyDeviceInfoList(devinfo); + return ret; } diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index ca83d0ae0d..c6d10e97bf 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -97,7 +97,7 @@ struct wined3d * CDECL wined3d_create(DWORD flags) struct wined3d *object; HRESULT hr;
- if (!(object = heap_alloc_zero(FIELD_OFFSET(struct wined3d, adapters[1])))) + if (!(object = heap_alloc_zero(sizeof(struct wined3d)))) { ERR("Failed to allocate wined3d object memory.\n"); return NULL; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6e39db4fa8..8190327cce 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2840,7 +2840,7 @@ struct wined3d LONG ref; DWORD flags; UINT adapter_count; - struct wined3d_adapter adapters[1]; + struct wined3d_adapter *adapters; };
HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) DECLSPEC_HIDDEN;
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=45797
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) 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)
On Tue, Dec 18, 2018 at 5:21 PM Zhiyi Zhang zzhang@codeweavers.com wrote:
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
dlls/dxgi/tests/dxgi.c | 4 +-- dlls/wined3d/Makefile.in | 2 +- dlls/wined3d/directx.c | 66 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_main.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-)
In my opinion, we shouldn't use SetupAPI directly in wined3d. Wined3d should get LUIDs from OpenGL. Device UUIDs, driver UUIDs and LUIDs are also exposed by OpenGL, see EXT_external_objects and EXT_external_objects_win32. If it's problematic to implement those extensions, we could also consider extending WGL_WINE_query_renderer.
On Thu, 20 Dec 2018 at 01:33, Józef Kucia joseph.kucia@gmail.com wrote:
On Tue, Dec 18, 2018 at 5:21 PM Zhiyi Zhang zzhang@codeweavers.com wrote:
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
dlls/dxgi/tests/dxgi.c | 4 +-- dlls/wined3d/Makefile.in | 2 +- dlls/wined3d/directx.c | 66 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_main.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-)
In my opinion, we shouldn't use SetupAPI directly in wined3d. Wined3d should get LUIDs from OpenGL. Device UUIDs, driver UUIDs and LUIDs are also exposed by OpenGL, see EXT_external_objects and EXT_external_objects_win32. If it's problematic to implement those extensions, we could also consider extending WGL_WINE_query_renderer.
Well, maybe. There also exist Win32 builds of wined3d though, and setupapi would have the advantage of working there as well, while we wouldn't necessarily be able to rely on any particular OpenGL extension being available. Note that I haven't really looked at the patch, but one concern I'd have would be making sure we only enumerate adapters that are available to the current session/seat.
On Thu, Dec 20, 2018 at 9:02 PM Henri Verbeet hverbeet@gmail.com wrote:
Well, maybe. There also exist Win32 builds of wined3d though, and setupapi would have the advantage of working there as well, while we wouldn't necessarily be able to rely on any particular OpenGL extension being available.
The "DEVPROPKEY_DISPLAY_ADAPTER_LUID" property seems to be available only on Windows 10. The OpenGL extension should also work on older Windows versions.
On Fri, 21 Dec 2018 at 11:32, Józef Kucia joseph.kucia@gmail.com wrote:
On Thu, Dec 20, 2018 at 9:02 PM Henri Verbeet hverbeet@gmail.com wrote:
Well, maybe. There also exist Win32 builds of wined3d though, and setupapi would have the advantage of working there as well, while we wouldn't necessarily be able to rely on any particular OpenGL extension being available.
The "DEVPROPKEY_DISPLAY_ADAPTER_LUID" property seems to be available only on Windows 10. The OpenGL extension should also work on older Windows versions.
That's true.
On Wed, Dec 26, 2018 at 1:49 PM Henri Verbeet hverbeet@gmail.com wrote:
On Fri, 21 Dec 2018 at 11:32, Józef Kucia joseph.kucia@gmail.com wrote:
On Thu, Dec 20, 2018 at 9:02 PM Henri Verbeet hverbeet@gmail.com wrote:
Well, maybe. There also exist Win32 builds of wined3d though, and setupapi would have the advantage of working there as well, while we wouldn't necessarily be able to rely on any particular OpenGL extension being available.
The "DEVPROPKEY_DISPLAY_ADAPTER_LUID" property seems to be available only on Windows 10. The OpenGL extension should also work on older Windows versions.
That's true.
The best option might be to use the EXT_external_objects_win32 extension, and fallback to setupapi when the extension is not available.
On 16/01/2019 19:05, Józef Kucia wrote:
On Wed, Dec 26, 2018 at 1:49 PM Henri Verbeet hverbeet@gmail.com wrote:
On Fri, 21 Dec 2018 at 11:32, Józef Kucia joseph.kucia@gmail.com wrote:
On Thu, Dec 20, 2018 at 9:02 PM Henri Verbeet hverbeet@gmail.com wrote:
Well, maybe. There also exist Win32 builds of wined3d though, and setupapi would have the advantage of working there as well, while we wouldn't necessarily be able to rely on any particular OpenGL extension being available.
The "DEVPROPKEY_DISPLAY_ADAPTER_LUID" property seems to be available only on Windows 10. The OpenGL extension should also work on older Windows versions.
That's true.
The best option might be to use the EXT_external_objects_win32 extension, and fallback to setupapi when the extension is not available.
The problem is that opengl doesn't have a proper way to enumerate
graphics cards. There are vendor specific extensions like WGL_NV_gpu_affinity
and WGL_AMD_gpu_association but they are usually unavailable on consumer
products, let alone not portable.
We could use the EXT_external_objects_win32 but then it will only report
UUID and LUID for the primary graphics card, which is sort of useless because
using setupapi will also fallback to reporting a default graphics card if Vulkan
enumeration failed.
And as a kind of related topic. I think I found a way to implement EnumDisplayDevices
by using xrandr 1.4.0 protocol[1]. Turns out I missed this path because somehow www.x.org puts
an xrandr 1.2 on its front page and I didn't read carefully enough to know there is more.
I plan to implement EnumDisplayDevices as follows:
winex11.drv init -> libxrandr enumerates adapters and monitors -> stores info via setupapi
-> EnumDisplayDevices gets the info via setupapi. And also listen monitor/gpu change
notify from libxrandr to refresh the info.
Having a working EnumDisplayDevices won't help much here though. As the adapters in libxrandr
might not be opengl/vulkan-capable. And I haven't found a way to uniquely identify a libxrandr adapter to
opengl/vulkan adapter (VK_EXT_pci_bus_info[2] might be a way to go, but it's not widely available yet).
Even if we could, native opengl uses the one adapter on the DISPLAY anyway. So not much use for opengl.
Thus will stay with using vulkan to enumerate d3d adapters for now. As for reporting different
adapters count using vulkan and libxrandr, it's not a problem because Windows doesn't report
the same either.
[1]: https://lists.x.org/archives/xorg-devel/2012-July/032350.html
[2]: https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/VkPhys...
On Mon, Jan 28, 2019 at 9:09 AM Zhiyi Zhang zzhang@codeweavers.com wrote:
The problem is that opengl doesn't have a proper way to enumerate
graphics cards. There are vendor specific extensions like WGL_NV_gpu_affinity
and WGL_AMD_gpu_association but they are usually unavailable on consumer
products, let alone not portable.
In my opinion, if wined3d cannot use other graphics cards it shouldn't enumerate adapters for them. It's fine to enumerate a single graphics card and get information for it from EXT_external_objects_win32. It can change when we have Vulkan wined3d backend. Vulkan wined3d backend should naturally enumerate Vulkan physical devices.
D3D12 or DXGI may possibly enumerate additional adapters and match them with the adapter returned from wined3d using LUIDs.
On 12/20/18 6:02 AM, Józef Kucia wrote:
On Tue, Dec 18, 2018 at 5:21 PM Zhiyi Zhang zzhang@codeweavers.com wrote:
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
dlls/dxgi/tests/dxgi.c | 4 +-- dlls/wined3d/Makefile.in | 2 +- dlls/wined3d/directx.c | 66 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_main.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-)
In my opinion, we shouldn't use SetupAPI directly in wined3d. Wined3d should get LUIDs from OpenGL. Device UUIDs, driver UUIDs and LUIDs are also exposed by OpenGL, see EXT_external_objects and EXT_external_objects_win32. If it's problematic to implement those extensions, we could also consider extending WGL_WINE_query_renderer.
Please correct me if I am wrong. It seems to me that OpenGL doesn't support enumerating the adapters. Yes, OpenGL can get the device UUIDs if the extensions exist. But it binds to current OpenGL context. Since we don't have a way to correlate DISPLAYs to adapters, I don't see a way to enumerate adapters via OpenGL.
On Wed, Dec 26, 2018 at 4:54 AM Zhiyi Zhang zzhang@codeweavers.com wrote:
On 12/20/18 6:02 AM, Józef Kucia wrote:
On Tue, Dec 18, 2018 at 5:21 PM Zhiyi Zhang zzhang@codeweavers.com wrote:
Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com
dlls/dxgi/tests/dxgi.c | 4 +-- dlls/wined3d/Makefile.in | 2 +- dlls/wined3d/directx.c | 66 +++++++++++++++++++++++++++------- dlls/wined3d/wined3d_main.c | 2 +- dlls/wined3d/wined3d_private.h | 2 +- 5 files changed, 58 insertions(+), 18 deletions(-)
In my opinion, we shouldn't use SetupAPI directly in wined3d. Wined3d should get LUIDs from OpenGL. Device UUIDs, driver UUIDs and LUIDs are also exposed by OpenGL, see EXT_external_objects and EXT_external_objects_win32. If it's problematic to implement those extensions, we could also consider extending WGL_WINE_query_renderer.
Please correct me if I am wrong. It seems to me that OpenGL doesn't support enumerating the adapters. Yes, OpenGL can get the device UUIDs if the extensions exist. But it binds to current OpenGL context. Since we don't have a way to correlate DISPLAYs to adapters, I don't see a way to enumerate adapters via OpenGL.
Sorry for jumping into the discussion late. Correct OpenGL doesn't have easy ways to do the enumeration and you are out of luck on older drivers not supporting the right extensions (though you could assume 1 card there).
There are various parts of Wine not well aware of adapters and monitors (e.g. user32). There will be applications (hopefully edge cases) which would be confused if different APIs report different devices.
Conceptually I would think all the adapter enumeration would have to live at the graphics driver level (winex11). Perhaps including the WineD3D OpenGL logic which "guesses" the adapter. (We need a way to share this logic with the Mac driver and wined3d on Windows) On systems with the right OpenGL / Vulkan extensions we may be able to do a better job. We would then have a nice unified view up to higher layers. Though easier said than done.
For inspiration you can look at MSDN about WDDM and the user mode driver model. Microsoft provides some clear information on how things work on Windows. Maybe some of these concepts make sense for us as well e.g. registry keys to locate drivers, features. E.g. https://docs.microsoft.com/en-us/windows-hardware/drivers/display/loading-an...
Thanks, Roderick