Needed by Orbiter Space Flight Simulator and Train Simulator Classic.
-- v6: d3d9/tests: Add Direct3DCreate9On12() tests. d3d9: Implement Direct3DCreate9On12().
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/Makefile.in | 1 + include/d3d9on12.h | 84 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 include/d3d9on12.h
diff --git a/include/Makefile.in b/include/Makefile.in index 391ce3c190b..b8d37606048 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -138,6 +138,7 @@ SOURCES = \ d3d8types.h \ d3d9.h \ d3d9caps.h \ + d3d9on12.h \ d3d9types.h \ d3dcaps.h \ d3dcommon.idl \ diff --git a/include/d3d9on12.h b/include/d3d9on12.h new file mode 100644 index 00000000000..72293f439bd --- /dev/null +++ b/include/d3d9on12.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2024 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _WINE_D3D9ON12_H_ +#define _WINE_D3D9ON12_H_ + +#include "d3d9.h" +#include "d3d12.h" + +#define MAX_D3D9ON12_QUEUES 2 + +typedef struct D3D9ON12_ARGS +{ + BOOL Enable9On12; + IUnknown *pD3D12Device; + IUnknown *ppD3D12Queues[MAX_D3D9ON12_QUEUES]; + UINT NumQueues; + UINT NodeMask; +} D3D9ON12_ARGS; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef IDirect3D9 * (__stdcall *PFN_Direct3DCreate9On12)(UINT sdk_version, D3D9ON12_ARGS *override_list, UINT override_entries); +IDirect3D9 * __stdcall Direct3DCreate9On12(UINT,D3D9ON12_ARGS *,UINT); + +DEFINE_GUID(IID_IDirect3DDevice9On12, 0xe7fda234, 0xb589, 0x4049, 0x94, 0x0d, 0x88, 0x78, 0x97, 0x75, 0x31, 0xc8); +typedef struct IDirect3DDevice9On12 *LPDIRECT3DDEVICE9ON12, *PDIRECT3DDEVICE9ON12; + +#undef INTERFACE +#define INTERFACE IDirect3DDevice9On12 +DECLARE_INTERFACE_(IDirect3DDevice9On12, IUnknown) +{ + /* IUnknown methods */ + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void **ppv) PURE; + STDMETHOD_(ULONG, AddRef)(THIS) PURE; + STDMETHOD_(ULONG, Release)(THIS) PURE; + /* IDirect3DDevice9On12 methods */ + STDMETHOD(GetD3D12Device)(THIS_ REFIID riid, void **out) PURE; + STDMETHOD(UnwrapUnderlyingResource)(THIS_ IDirect3DResource9 *resource, ID3D12CommandQueue *queue, REFIID riid, void **out) PURE; + STDMETHOD(ReturnUnderlyingResource)(THIS_ IDirect3DResource9 *resource, UINT num_sync, UINT64 *signal_values, ID3D12Fence **fences) PURE; +}; + +#if !defined(__cplusplus) || defined(CINTERFACE) +/* IUnknown methods */ +#define IDirect3DDevice9On12_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#define IDirect3DDevice9On12_AddRef(p) (p)->lpVtbl->AddRef(p) +#define IDirect3DDevice9On12_Release(p) (p)->lpVtbl->Release(p) +/* IDirect3DDevice9On12 methods */ +#define IDirect3DDevice9On12_GetD3D12Device(p,a,b) (p)->lpVtbl->GetD3D12Device(p,a,b) +#define IDirect3DDevice9On12_UnwrapUnderlyingResource(p,a,b,c,d) (p)->lpVtbl->UnwrapUnderlyingResource(p,a,b,c,d) +#define IDirect3DDevice9On12_ReturnUnderlyingResource(p,a,b,c,d) (p)->lpVtbl->ReturnUnderlyingResource(p,a,b,c,d) +#else +/* IUnknown methods */ +#define IDirect3DDevice9On12_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#define IDirect3DDevice9On12_AddRef(p) (p)->AddRef() +#define IDirect3DDevice9On12_Release(p) (p)->Release() +/* IDirect3DDevice9On12 methods */ +#define IDirect3DDevice9On12_GetD3D12Device(p,a,b) (p)->GetD3D12Device(a,b) +#define IDirect3DDevice9On12_UnwrapUnderlyingResource(p,a,b,c,d) (p)->UnwrapUnderlyingResource(a,b,c,d) +#define IDirect3DDevice9On12_ReturnUnderlyingResource(p,a,b,c,d) (p)->ReturnUnderlyingResource(a,b,c,d) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _WINE_D3D9ON12_H_ */
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed by Orbiter Space Flight Simulator and Train Simulator Classic. --- dlls/d3d9/Makefile.in | 1 + dlls/d3d9/d3d9.spec | 1 + dlls/d3d9/d3d9_main.c | 29 +++++++++ dlls/d3d9/d3d9_private.h | 11 ++++ dlls/d3d9/d3d9on12.c | 127 +++++++++++++++++++++++++++++++++++++++ dlls/d3d9/device.c | 18 ++++++ 6 files changed, 187 insertions(+) create mode 100644 dlls/d3d9/d3d9on12.c
diff --git a/dlls/d3d9/Makefile.in b/dlls/d3d9/Makefile.in index 5a717b11863..84380258c32 100644 --- a/dlls/d3d9/Makefile.in +++ b/dlls/d3d9/Makefile.in @@ -5,6 +5,7 @@ IMPORTS = dxguid uuid wined3d SOURCES = \ buffer.c \ d3d9_main.c \ + d3d9on12.c \ device.c \ directx.c \ query.c \ diff --git a/dlls/d3d9/d3d9.spec b/dlls/d3d9/d3d9.spec index a33cba51e77..11ad26b64c6 100644 --- a/dlls/d3d9/d3d9.spec +++ b/dlls/d3d9/d3d9.spec @@ -12,3 +12,4 @@ @ stdcall DebugSetMute() @ stdcall Direct3DCreate9(long) @ stdcall Direct3DCreate9Ex(long ptr) +@ stdcall Direct3DCreate9On12(long ptr long) diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c index 5bdf05409aa..5f0c177eedd 100644 --- a/dlls/d3d9/d3d9_main.c +++ b/dlls/d3d9/d3d9_main.c @@ -75,6 +75,35 @@ HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9E return D3D_OK; }
+IDirect3D9 * WINAPI DECLSPEC_HOTPATCH Direct3DCreate9On12(UINT sdk_version, D3D9ON12_ARGS *override_list, UINT override_entries) +{ + struct d3d9 *object; + + TRACE("sdk_version %#x, override_list %p, override_entries %#x.\n", sdk_version, override_list, override_entries); + + if (!(object = calloc(1, sizeof(*object)))) + return NULL; + + if (!d3d9_init(object, TRUE)) + { + WARN("Failed to initialize d3d9.\n"); + free(object); + return NULL; + } + if (!d3d9on12_init(&object->d3d9on12, override_list, override_entries)) + { + WARN("Failed to initialize d3d9on12.\n"); + free(object->d3d9on12); + return NULL; + } + SetLastError(ERROR_SUCCESS); + + TRACE("Created d3d9 object %p.\n", object); + if (object->d3d9on12) TRACE("Created d3d9on12 object %p.\n", object->d3d9on12); + + return (IDirect3D9 *)&object->IDirect3D9Ex_iface; +} + /* The callback is called on any error encountered during validation, including * improper IDirect3DShaderValidator9 method calls. * - "file" and "line" are passed through directly from Instruction(). "line" diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index a5f059c5aef..fd782f0eb47 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -34,6 +34,7 @@ #include "wine/debug.h"
#include "d3d9.h" +#include "d3d9on12.h" #include "wine/wined3d.h"
#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256 @@ -57,10 +58,19 @@ unsigned int wined3dmapflags_from_d3dmapflags(unsigned int flags, unsigned int u void present_parameters_from_wined3d_swapchain_desc(D3DPRESENT_PARAMETERS *present_parameters, const struct wined3d_swapchain_desc *swapchain_desc, DWORD presentation_interval);
+struct d3d9on12 +{ + IDirect3DDevice9On12 IDirect3DDevice9On12_iface; + LONG refcount; + struct D3D9ON12_ARGS *override_list; + UINT override_entries; +}; + struct d3d9 { IDirect3D9Ex IDirect3D9Ex_iface; LONG refcount; + struct d3d9on12 *d3d9on12; struct wined3d *wined3d; struct wined3d_output **wined3d_outputs; unsigned int wined3d_output_count; @@ -70,6 +80,7 @@ struct d3d9 void d3d9_caps_from_wined3dcaps(const struct d3d9 *d3d9, unsigned int adapter_ordinal, D3DCAPS9 *caps, const struct wined3d_caps *wined3d_caps); BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended); +BOOL d3d9on12_init(struct d3d9on12 **d3d9on12, D3D9ON12_ARGS *override_list, UINT override_entries);
struct fvf_declaration { diff --git a/dlls/d3d9/d3d9on12.c b/dlls/d3d9/d3d9on12.c new file mode 100644 index 00000000000..b895f0b98db --- /dev/null +++ b/dlls/d3d9/d3d9on12.c @@ -0,0 +1,127 @@ +/* + * IDirect3DDevice9On12 implementation + * + * Copyright (C) 2024 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "d3d9_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3d9); + +static inline struct d3d9on12 *impl_from_IDirect3DDevice9On12( IDirect3DDevice9On12 *iface ) +{ + return CONTAINING_RECORD( iface, struct d3d9on12, IDirect3DDevice9On12_iface ); +} + +static HRESULT WINAPI d3d9on12_QueryInterface( IDirect3DDevice9On12 *iface, REFIID iid, void **out ) +{ + struct d3d9on12 *d3d9on12 = impl_from_IDirect3DDevice9On12(iface); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IDirect3DDevice9On12 )) + { + IDirect3DDevice9On12_AddRef( &d3d9on12->IDirect3DDevice9On12_iface ); + *out = &d3d9on12->IDirect3DDevice9On12_iface; + return S_OK; + } + + WARN( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid) ); + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d9on12_AddRef( IDirect3DDevice9On12 *iface ) +{ + struct d3d9on12 *d3d9on12 = impl_from_IDirect3DDevice9On12(iface); + ULONG refcount = InterlockedIncrement(&d3d9on12->refcount); + TRACE( "%p increasing refcount to %lu.\n", iface, refcount ); + return refcount; +} + +static ULONG WINAPI d3d9on12_Release( IDirect3DDevice9On12 *iface ) +{ + struct d3d9on12 *d3d9on12 = impl_from_IDirect3DDevice9On12(iface); + ULONG refcount = InterlockedDecrement(&d3d9on12->refcount); + + TRACE( "%p decreasing refcount to %lu.\n", iface, refcount ); + + if (!refcount) + free( d3d9on12 ); + + return refcount; +} + +static HRESULT WINAPI d3d9on12_GetD3D12Device( IDirect3DDevice9On12 *iface, REFIID iid, void **out ) +{ + FIXME( "iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out ); + + if (!out) return E_INVALIDARG; + + *out = NULL; + return E_NOINTERFACE; +} + +static HRESULT WINAPI d3d9on12_UnwrapUnderlyingResource( IDirect3DDevice9On12 *iface, IDirect3DResource9 *resource, ID3D12CommandQueue *queue, REFIID iid, void **out ) +{ + FIXME( "iface %p, resource %p, queue %p, iid %s, out %p stub!\n", iface, resource, queue, debugstr_guid(iid), out ); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d9on12_ReturnUnderlyingResource( IDirect3DDevice9On12 *iface, IDirect3DResource9 *resource, UINT num_sync, UINT64 *signal_values, ID3D12Fence **fences ) +{ + FIXME( "iface %p, resource %p, num_sync %#x, signal_values %p, fences %p stub!\n", iface, resource, num_sync, signal_values, fences ); + return E_NOTIMPL; +} + +static const struct IDirect3DDevice9On12Vtbl d3d9on12_vtbl = +{ + /* IUnknown */ + d3d9on12_QueryInterface, + d3d9on12_AddRef, + d3d9on12_Release, + /* IDirect3DDevice9On12 */ + d3d9on12_GetD3D12Device, + d3d9on12_UnwrapUnderlyingResource, + d3d9on12_ReturnUnderlyingResource, +}; + +BOOL d3d9on12_init( struct d3d9on12 **d3d9on12, D3D9ON12_ARGS *override_list, UINT override_entries ) +{ + struct d3d9on12 *object; + + if (!override_entries || !override_list || !override_list->Enable9On12) + { + *d3d9on12 = NULL; + return TRUE; + } + + if (!(object = calloc( 1, sizeof(*object) ))) + return FALSE; + + FIXME( "ignoring override_list %p\n", override_list ); + + object->IDirect3DDevice9On12_iface.lpVtbl = &d3d9on12_vtbl; + object->refcount = 1; + object->override_list = NULL; + object->override_entries = override_entries; + + *d3d9on12 = object; + return TRUE; +} diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 1267dc8fca1..669bc8845f5 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -623,6 +623,24 @@ static HRESULT WINAPI d3d9_device_QueryInterface(IDirect3DDevice9Ex *iface, REFI return S_OK; }
+ if (IsEqualGUID(riid, &IID_IDirect3DDevice9On12)) + { + struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + + if (!device->d3d_parent->d3d9on12) + { + WARN("IDirect3D9 instance wasn't created with D3D9On12 enabled, returning E_NOINTERFACE %p.\n", device->d3d_parent->d3d9on12); + *out = NULL; + return E_NOINTERFACE; + } + + FIXME("pD3D12Device value is not being checked if it matches the d3d9 device\n"); + + IDirect3DDevice9On12_AddRef(iface); + *out = &device->d3d_parent->d3d9on12->IDirect3DDevice9On12_iface; + return S_OK; + } + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
*out = NULL;
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- dlls/d3d9/tests/Makefile.in | 1 + dlls/d3d9/tests/d3d9on12.c | 278 ++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 dlls/d3d9/tests/d3d9on12.c
diff --git a/dlls/d3d9/tests/Makefile.in b/dlls/d3d9/tests/Makefile.in index 17d0a451fbc..a0e38cc39a8 100644 --- a/dlls/d3d9/tests/Makefile.in +++ b/dlls/d3d9/tests/Makefile.in @@ -3,6 +3,7 @@ IMPORTS = d3d9 user32 gdi32
SOURCES = \ d3d9ex.c \ + d3d9on12.c \ device.c \ stateblock.c \ visual.c diff --git a/dlls/d3d9/tests/d3d9on12.c b/dlls/d3d9/tests/d3d9on12.c new file mode 100644 index 00000000000..828214de009 --- /dev/null +++ b/dlls/d3d9/tests/d3d9on12.c @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2024 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "wine/test.h" +#include <d3d9.h> +#include <initguid.h> +#include <d3d9on12.h> +#include <dxgi1_4.h> + +static HMODULE d3d9_handle = 0; +static HMODULE d3d12_handle = 0; +static HMODULE dxgi_handle = 0; + +static IDirect3D9 * (WINAPI *pDirect3DCreate9On12)(UINT sdk_version, D3D9ON12_ARGS *override_list, UINT override_entries); +static HRESULT (WINAPI *pCreateDXGIFactory2)(UINT flags, REFIID iid, void **factory); +static HRESULT (WINAPI *pD3D12CreateDevice)(IUnknown *adapter, D3D_FEATURE_LEVEL feature_level, REFIID iid, void **device); + +DEFINE_GUID(IID_IDeadbeef, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xee, 0xee, 0xee, 0xee, 0xef); + +#define create_d3d9on12_device(out_d3d9, window, override_list, override_entries, out_device) \ + create_d3d9on12_device_(__LINE__, out_d3d9, window, override_list, override_entries, out_device) +static HRESULT create_d3d9on12_device_(unsigned int line, IDirect3D9 **out_d3d9, HWND window, D3D9ON12_ARGS *override_list, + UINT override_entries, IDirect3DDevice9 **out_device) +{ + IDirect3DDevice9On12 *d3d9on12 = (void *)0xdeadbeef; + IDirect3DDevice9 *device = (void *)0xdeadbeef; + IDirect3D9 *d3d9 = (void *)0xdeadbeef; + D3DPRESENT_PARAMETERS present_parameters; + HRESULT hr; + + memset(&present_parameters, 0, sizeof(present_parameters)); + present_parameters.Windowed = TRUE; + present_parameters.hDeviceWindow = window; + present_parameters.SwapEffect = D3DSWAPEFFECT_COPY; + present_parameters.BackBufferWidth = 640; + present_parameters.BackBufferHeight = 480; + present_parameters.EnableAutoDepthStencil = FALSE; + present_parameters.AutoDepthStencilFormat = D3DFMT_D16; + + SetLastError(0xdeadbeef); + d3d9 = pDirect3DCreate9On12(D3D_SDK_VERSION, override_list, override_entries); + ok_(__FILE__, line)(d3d9 != NULL, "got NULL d3d9 object\n"); + ok_(__FILE__, line)(GetLastError() == ERROR_SUCCESS || broken(GetLastError() == ERROR_TOO_MANY_POSTS), + "Direct3DCreate9On12 GetLastError returned %#lx\n", GetLastError()); + + hr = IDirect3D9_QueryInterface(d3d9, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok_(__FILE__, line)(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + ok_(__FILE__, line)(d3d9on12 == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9on12); + + hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device); + + *out_d3d9 = d3d9; + *out_device = device; + + return hr; +} + +static void test_d3d9on12(void) +{ + IDirect3DDevice9On12 *d3d9on12_2 = (void *)0xdeadbeef; + IDirect3DDevice9On12 *d3d9on12 = (void *)0xdeadbeef; + IDirect3DDevice9 *device = (void *)0xdeadbeef; + IDirect3D9 *d3d9 = (void *)0xdeadbeef; + IDXGIAdapter *adapter = (void *)0xdeadbeef; + IDXGIFactory4 *factory = (void *)0xdeadbeef; + ID3D12Device *d3d12device = (void *)0xdeadbeef; + ID3D12Device *d3d12device_2 = (void *)0xdeadbeef; + D3D9ON12_ARGS override_list; + UINT override_entries = 0; + HRESULT hr; + HWND window = CreateWindowA("d3d9_test_wc", "d3d9_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION, + 0, 0, 640, 480, 0, 0, 0, 0); + + SetLastError(0xdeadbeef); + d3d9 = pDirect3DCreate9On12(D3D_SDK_VERSION, NULL, override_entries); + ok(d3d9 != NULL, "got NULL d3d9 object\n"); + ok(GetLastError() == ERROR_SUCCESS, "Direct3DCreate9On12 GetLastError returned %#lx\n", GetLastError()); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + ok(d3d9on12 == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + override_list.Enable9On12 = TRUE; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + ok(d3d9on12 == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + override_entries = 1; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + ok(d3d9on12 == NULL, "QueryInterface returned interface %p, expected NULL\n", d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + override_list.Enable9On12 = TRUE; + override_list.NodeMask = 0xdeadbeef; + override_entries = 1; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirect3DDevice9On12_QueryInterface(d3d9on12, &IID_IDirect3DDevice9On12, (void **)&d3d9on12_2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IDirect3DDevice9On12_Release(d3d9on12_2); + IDirect3DDevice9On12_Release(d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + override_list.Enable9On12 = TRUE; + override_entries = 1; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDirect3DDevice9On12_GetD3D12Device(d3d9on12, NULL, NULL); + ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); + hr = IDirect3DDevice9On12_GetD3D12Device(d3d9on12, &IID_IDeadbeef, NULL); + ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr); + IDirect3DDevice9On12_Release(d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + memset(&override_list, 0, sizeof(override_list)); + override_list.Enable9On12 = TRUE; + override_entries = 0xdeadbeef; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IDirect3DDevice9On12_Release(d3d9on12); + IDirect3DDevice9_Release(device); + IDirect3D9_Release(d3d9); + + hr = pCreateDXGIFactory2(0, &IID_IDXGIFactory4, (void **)&factory); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IDXGIFactory4_EnumAdapters(factory, 0, &adapter); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IDXGIFactory4_Release(factory); + + hr = pD3D12CreateDevice((IUnknown *)adapter, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, (void **)&d3d12device); + IDXGIAdapter_Release(adapter); + + memset(&override_list, 0, sizeof(override_list)); + override_list.Enable9On12 = TRUE; + override_list.pD3D12Device = (IUnknown *)d3d12device; + override_entries = 1; + d3d9on12 = (void *)0xdeadbeef; + hr = create_d3d9on12_device(&d3d9, window, &override_list, override_entries, &device); + if (FAILED(hr)) + { + skip("Failed to create a regular Direct3DDevice9, skipping d3d9on12 tests\n"); + goto out; + } + + hr = IDirect3DDevice9_QueryInterface(device, &IID_IDirect3DDevice9On12, (void **)&d3d9on12); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IDirect3DDevice9On12_GetD3D12Device(d3d9on12, &IID_ID3D12Device, (void **)&d3d12device_2); + todo_wine + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine + ok(override_list.pD3D12Device == (IUnknown *)d3d12device_2, "GetD3D12Device returned device %p, expected %p\n", d3d12device_2, override_list.pD3D12Device); + d3d12device_2 = (void *)0xdeadbeef; + hr = IDirect3DDevice9On12_GetD3D12Device(d3d9on12, &IID_IDeadbeef, (void **)&d3d12device_2); + ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr); + ok(d3d12device_2 == NULL, "GetD3D12Device returned device %p, expected NULL\n", d3d12device_2); + + IDirect3DDevice9On12_Release(d3d9on12); + IDirect3DDevice9_Release(device); +out: + IDirect3D9_Release(d3d9); + DestroyWindow(window); +} + +START_TEST(d3d9on12) +{ + d3d9_handle = LoadLibraryA("d3d9.dll"); + if (!d3d9_handle) + { + skip("Could not load d3d9.dll\n"); + return; + } + dxgi_handle = LoadLibraryA("dxgi.dll"); + if (!dxgi_handle) + { + skip("Could not load dxgi.dll\n"); + return; + } + d3d12_handle = LoadLibraryA("d3d12.dll"); + if (!d3d12_handle) + { + skip("Could not load d3d12.dll\n"); + return; + } + + pDirect3DCreate9On12 = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9On12"); + if (!pDirect3DCreate9On12) + { + win_skip("Direct3DCreate9On12 is not supported, skipping d3d9on12 tests\n"); + return; + } + pCreateDXGIFactory2 = (void *)GetProcAddress(dxgi_handle, "CreateDXGIFactory2"); + if (!pCreateDXGIFactory2) + { + win_skip("CreateDXGIFactory2 is not supported, skipping d3d9on12 tests\n"); + return; + } + pD3D12CreateDevice = (void *)GetProcAddress(d3d12_handle, "D3D12CreateDevice"); + if (!pD3D12CreateDevice) + { + win_skip("D3D12CreateDevice is not supported, skipping d3d9on12 tests\n"); + return; + } + + test_d3d9on12(); +}
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=144013
Your paranoid android.
=== w11pro64_amd (64 bit report) ===
d3d9: d3d9on12.c:98: Test failed: Direct3DCreate9On12 GetLastError returned 0xdeadbeef
=== debian11b (64 bit WoW report) ===
comctl32: button.c:801: Test failed: [0] expected uItemState 16, got 80 button.c:801: Test failed: [0] expected uItemState 16, got 80 button.c:810: Test failed: [0] expected uItemState 0, got 64 button.c:810: Test failed: [0] expected uItemState 0, got 64 button.c:819: Test failed: [0] expected uItemState 0, got 64 button.c:819: Test failed: [0] expected uItemState 0, got 64 button.c:834: Test failed: expected state 0, got 0200 button.c:838: Test failed: [0] expected uItemState 1, got 65 button.c:838: Test failed: [0] expected uItemState 1, got 65 button.c:847: Test failed: expected state 0x0004, got 0204 button.c:854: Test failed: [0] expected uItemState 0, got 64 button.c:854: Test failed: [0] expected uItemState 0, got 64 button.c:863: Test failed: expected state 0, got 0200 button.c:898: Test failed: [0] expected uItemState 0, got 64 button.c:898: Test failed: [0] expected uItemState 0, got 64 button.c:898: Test failed: [0] expected uItemState 0, got 64 button.c:898: Test failed: [0] expected uItemState 0, got 64 button.c:998: Test failed: BCN_DROPDOWN from the button: the msg sequence is not complete: expected 0000 - actual 0084
d3dx10_34: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011C3790. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011A4A80. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011C3690. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D1A90. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011A4A80.
d3dx10_35: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011B5D90. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001195C60. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D54C0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011D5690. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011D2AE0.
d3dx10_36: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239E40. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BC740. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011BC910. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BC740. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011C3440.
d3dx10_37: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011BB840. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011B6010. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BB560. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011A49E0.
d3dx10_38: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001195C50. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 0000000001195C50. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D5700. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011BF400. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011BF400.
d3dx10_39: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011B6030. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BCAB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4690. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011A4B40. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011958C0.
d3dx10_40: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011B6030. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011BCAB0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011A4690. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011A4B40. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011958C0.
d3dx10_41: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001195B70. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E34F0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011E36C0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 0000000001192690. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001192860.
d3dx10_42: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 00000000011E3AE0. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011E3AE0. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D4A10. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011E3AE0. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 00000000011BE6C0.
d3dx10_43: d3dx10.c:4380: Test succeeded inside todo block: Got unexpected effect 0000000001239C70. d3dx10.c:4470: Test succeeded inside todo block: Got unexpected effect 00000000011C1820. d3dx10.c:4480: Test succeeded inside todo block: Got unexpected effect 00000000011D76B0. d3dx10.c:4589: Test succeeded inside todo block: Got unexpected effect 00000000011A4A10. d3dx10.c:4599: Test succeeded inside todo block: Got unexpected effect 0000000001195BC0.
On Wed Mar 13 04:15:09 2024 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 6 of the diff](/wine/wine/-/merge_requests/4915/diffs?diff_id=104781&start_sha=3872d99a3a2ca99bacd19fba7f5bd67bf8b07e9e#ec31c16bcfaa0f6fc89bf1bab9e29d2507abc6bb_117_117)
ATM it's not used so I've removed it.
On Wed Mar 13 04:15:08 2024 +0000, Mohamad Al-Jaf wrote:
changed this line in [version 6 of the diff](/wine/wine/-/merge_requests/4915/diffs?diff_id=104781&start_sha=3872d99a3a2ca99bacd19fba7f5bd67bf8b07e9e#ec31c16bcfaa0f6fc89bf1bab9e29d2507abc6bb_109_109)
I didn't think it would make a difference which gets checked first, but in any case I've changed it so `override_entries` is now being checked first.
On Wed Mar 13 04:22:37 2024 +0000, Jan Sikorski wrote:
Sorry for the long silence. A couple of nits above, but generally that looks fine to me. My understanding is that we could in principle have a client that calls Microsoft's d3d9on12.dll instead of returning our d3d9, is that right? The games just go through `Direct3DCreate9On12` but then only use the D3D9 interface?
Thanks for the review. That's my understanding for the former as well, d3d9on12.dll maps the D3D9 API calls to D3D12 so it should work with VKD3D. For the latter, the games indeed appear to be only using the D3D9 interface.
On Thu Mar 14 18:35:03 2024 +0000, Mohamad Al-Jaf wrote:
I've put them into a separate file, this makes it easier to organize the d3d12 and dxgi modules and their respective functions.
I don't think this seems necessary. I'd just put them in device.c.
Why is d3d9on12 a separate object, rather than being an interface on the d3d9 object?
Making the header an IDL would be an improvement, although I won't insist on it.
On Thu Mar 14 18:35:03 2024 +0000, Zebediah Figura wrote:
I don't think this seems necessary. I'd just put them in device.c.
Having them in a separate test makes it possible to run the testbot on d3d9on12 functions only, which might be helpful when dealing with test failures as it makes it clear what and where the test is failing, especially since a lot of test messages in Wine are generic, like "Got hr", which would require navigating the test file to the specific line(s) it failed at. Plus, the bigger tests take longer to execute, and when dealing with debugging flaky tests, this can add up rather quickly.
It's also nice to organize all the required modules and functions in one file especially since they're only used for this specific function, but that's just my opinion; I find big files hard to navigate.
I'll wait for a consensus on this matter before pushing an update. I'm open to putting it anywhere.
On Fri Mar 15 04:06:32 2024 +0000, Zebediah Figura wrote:
Why is d3d9on12 a separate object, rather than being an interface on the d3d9 object?
It was based on the way struct d3d9 is currently written, though I suppose it's more correct to do as you suggest. Does this make a difference or is it just a matter of style?
On Fri Mar 15 04:06:43 2024 +0000, Zebediah Figura wrote:
Making the header an IDL would be an improvement, although I won't insist on it.
I ran into an issue when I was trying to make it into an IDL and I didn't think it was worth pursuing.
On Fri Mar 15 04:06:10 2024 +0000, Mohamad Al-Jaf wrote:
Having them in a separate test makes it possible to run the testbot on d3d9on12 functions only, which might be helpful when dealing with test failures as it makes it clear what and where the test is failing, especially since a lot of test messages in Wine are generic, like "Got hr", which would require navigating the test file to the specific line(s) it failed at. Plus, the bigger tests take longer to execute, and when dealing with debugging flaky tests, this can add up rather quickly. It's also nice to organize all the required modules and functions in one file especially since they're only used for this specific function, but that's just my opinion; I find big files hard to navigate. I'll wait for a consensus on this matter before pushing an update. I'm open to putting it anywhere.
You can apply that same argument to any given test. If you're interested in running only one test on the testbot just comment out or if (0) all the others.
On Fri Mar 15 04:06:32 2024 +0000, Mohamad Al-Jaf wrote:
It was based on the way struct d3d9 is currently written, though I suppose it's more correct to do as you suggest. Does this make a difference or is it just a matter of style?
Generally speaking, if you can get another interface via QueryInterface(), that other interface belongs to the same object. Interface querying is supposed to be transitive, reflexive, and symmetric, and while you *can* do that with two separate objects [and it's necessary for aggregation] it's strongly implies that you should be using multiple interfaces on the same object.
On Fri Mar 15 04:06:43 2024 +0000, Mohamad Al-Jaf wrote:
I ran into an issue when I was trying to make it into an IDL and I didn't think it was worth pursuing.
What issue?
On Fri Mar 15 19:02:25 2024 +0000, Zebediah Figura wrote:
What issue?
It was an issue with importing d3d9.h. It would fail to build:
`error: Unable to open include file stdlib.h`
The file d3d9.h is needed for the interfaces IDirect3D9 and IDirect3DResource9. I added a forward declaration for them.