From: Kang Kang <kk1987@gmail.com> On Windows the WARP adapter is always present, so applications call IDXGIFactory4::EnumWarpAdapter() without checking the result and immediately dereference the returned adapter pointer. The stub returned E_NOTIMPL without touching *adapter, crashing such applications on startup; the 3DMark DX12 benchmarks (Time Spy, Speed Way, Steel Nomad, Solar Bay) are affected. Return the first adapter instead, matching what D3D11CreateDevice() does for D3D_DRIVER_TYPE_WARP. Enumerating a proper software adapter with DXGI_ADAPTER_FLAG_SOFTWARE set would require wined3d support and is left for the future. --- dlls/dxgi/factory.c | 16 ++++++++++++++-- dlls/dxgi/tests/dxgi.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/dlls/dxgi/factory.c b/dlls/dxgi/factory.c index 7837bffaca3..c6bb47fa9dd 100644 --- a/dlls/dxgi/factory.c +++ b/dlls/dxgi/factory.c @@ -448,9 +448,21 @@ static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumAdapterByLuid(IWineDXGIFactory static HRESULT STDMETHODCALLTYPE dxgi_factory_EnumWarpAdapter(IWineDXGIFactory *iface, REFIID iid, void **adapter) { - FIXME("iface %p, iid %s, adapter %p stub!\n", iface, debugstr_guid(iid), adapter); + IDXGIAdapter1 *adapter_object; + HRESULT hr; - return E_NOTIMPL; + FIXME("iface %p, iid %s, adapter %p semi-stub, returning a hardware adapter.\n", + iface, debugstr_guid(iid), adapter); + + if (!adapter) + return DXGI_ERROR_INVALID_CALL; + + if (FAILED(hr = dxgi_factory_EnumAdapters1(iface, 0, &adapter_object))) + return hr; + + hr = IDXGIAdapter1_QueryInterface(adapter_object, iid, adapter); + IDXGIAdapter1_Release(adapter_object); + return hr; } static HRESULT STDMETHODCALLTYPE dxgi_factory_CheckFeatureSupport(IWineDXGIFactory *iface, diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 518fe47cbd8..83392a072ac 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -1151,6 +1151,40 @@ static void test_adapter_luid(void) ok(!refcount, "Factory has %lu references left.\n", refcount); } +static void test_enum_warp_adapter(void) +{ + DXGI_ADAPTER_DESC1 desc; + IDXGIFactory4 *factory4; + IDXGIAdapter1 *adapter; + ULONG refcount; + HRESULT hr; + + if (!pCreateDXGIFactory2 + || FAILED(hr = pCreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory4))) + { + skip("DXGI 1.4 is not available.\n"); + return; + } + + hr = IDXGIFactory4_EnumWarpAdapter(factory4, &IID_IDXGIAdapter1, NULL); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + + hr = IDXGIFactory4_EnumWarpAdapter(factory4, &IID_IDXGIAdapter1, (void **)&adapter); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDXGIAdapter1_GetDesc1(adapter, &desc); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine ok(desc.Flags == DXGI_ADAPTER_FLAG_SOFTWARE, + "Got unexpected flags %#x.\n", desc.Flags); + todo_wine ok(desc.VendorId == 0x1414, "Got unexpected vendor ID %#x.\n", desc.VendorId); + todo_wine ok(desc.DeviceId == 0x008c, "Got unexpected device ID %#x.\n", desc.DeviceId); + + refcount = IDXGIAdapter1_Release(adapter); + ok(!refcount, "Adapter has %lu references left.\n", refcount); + refcount = IDXGIFactory4_Release(factory4); + ok(!refcount, "Factory has %lu references left.\n", refcount); +} + static void test_query_video_memory_info(void) { DXGI_QUERY_VIDEO_MEMORY_INFO memory_info; @@ -8723,6 +8757,7 @@ START_TEST(dxgi) queue_test(test_adapter_desc); queue_test(test_adapter_luid); + queue_test(test_enum_warp_adapter); queue_test(test_query_video_memory_info); queue_test(test_check_interface_support); queue_test(test_create_surface); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11395