diff --git a/src/FNA3D_Driver_D3D11.c b/src/FNA3D_Driver_D3D11.c index 3cfdabf2..a41e768d 100644 --- a/src/FNA3D_Driver_D3D11.c +++ b/src/FNA3D_Driver_D3D11.c @@ -32,7 +32,12 @@ #include "FNA3D_Driver_D3D11_shaders.h" #include +#ifdef FNA3D_DXVK_NATIVE +#define DXVK_SDL2_IMPL +#include "dxvk_sdl2.h" +#else #include +#endif /* FNA3D_DXVK_NATIVE */ /* D3D11 Libraries */ @@ -4845,6 +4850,9 @@ static uint8_t D3D11_PrepareWindowAttributes(uint32_t *flags) D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0 }; + void* dxgi_dll; + void* factory; /* IDXGIFactory1 or IDXGIFactory2 */ + IDXGIAdapter1 *adapter; HRESULT res; #ifdef FNA3D_DXVK_NATIVE @@ -4882,8 +4890,32 @@ static uint8_t D3D11_PrepareWindowAttributes(uint32_t *flags) return 0; } + res = D3D11_PLATFORM_CreateDXGIFactory( + &dxgi_dll, + &factory + ); + if (FAILED(res)) + { + D3D11_PLATFORM_UnloadDXGI(dxgi_dll); + SDL_UnloadObject(module); + return 0; + } +#ifdef FNA3D_DXVK_NATIVE + res = dxvkInitWSI(factory); /* Defined by dxvk_sdl2.h */ + if (FAILED(res)) + { + IUnknown_Release((IUnknown*) factory); + D3D11_PLATFORM_UnloadDXGI(dxgi_dll); + SDL_UnloadObject(module); + } +#endif /* FNA3D_DXVK_NATIVE */ + D3D11_PLATFORM_GetDefaultAdapter( + factory, + &adapter + ); + res = D3D11CreateDeviceFunc( - NULL, + (IDXGIAdapter*) adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, @@ -4899,7 +4931,7 @@ static uint8_t D3D11_PrepareWindowAttributes(uint32_t *flags) { FNA3D_LogWarn("Creating device with feature level 11_1 failed. Lowering feature level.", res); res = D3D11CreateDeviceFunc( - NULL, + (IDXGIAdapter*) adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT, @@ -4912,6 +4944,8 @@ static uint8_t D3D11_PrepareWindowAttributes(uint32_t *flags) ); } + IUnknown_Release((IUnknown*) factory); + D3D11_PLATFORM_UnloadDXGI(dxgi_dll); D3D11_PLATFORM_UnloadD3D11(module); if (FAILED(res)) @@ -4922,6 +4956,10 @@ static uint8_t D3D11_PrepareWindowAttributes(uint32_t *flags) /* No window flags required */ SDL_SetHint(SDL_HINT_VIDEO_EXTERNAL_CONTEXT, "1"); +#ifdef FNA3D_DXVK_NATIVE + /* ... unless this is DXVK */ + *flags = SDL_WINDOW_VULKAN; +#endif /* FNA3D_DXVK_NATIVE */ return 1; } @@ -5120,6 +5158,10 @@ static FNA3D_Device* D3D11_CreateDevice( &renderer->factory ); ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL) +#ifdef FNA3D_DXVK_NATIVE + res = dxvkInitWSI(renderer->factory); /* Defined by dxvk_sdl2.h */ + ERROR_CHECK_RETURN("Could not initialize DXVK WSI", NULL) +#endif /* FNA3D_DXVK_NATIVE */ D3D11_PLATFORM_GetDefaultAdapter( renderer->factory, &renderer->adapter @@ -5552,6 +5594,21 @@ static void ResolveSwapChainModeDescription( DXGI_MODE_DESC* modeDescription, DXGI_MODE_DESC* swapChainDescription ) { +#ifdef FNA3D_DXVK_NATIVE + /* FIXME: We could do SDL_GetWindowDisplayIndex here, but eh */ + IDXGIOutput *output; + IDXGIAdapter_EnumOutputs( + adapter, + 0, + &output + ); + IDXGIOutput_FindClosestMatchingMode( + output, + modeDescription, + swapChainDescription, + device + ); +#else HMONITOR monitor; int iAdapter = 0, iOutput; IDXGIAdapter1* pAdapter; @@ -5579,6 +5636,7 @@ static void ResolveSwapChainModeDescription( } IDXGIAdapter1_Release(pAdapter); } +#endif /* FNA3D_DXVK_NATIVE */ } static void D3D11_PLATFORM_CreateSwapChain( @@ -5594,10 +5652,14 @@ static void D3D11_PLATFORM_CreateSwapChain( HWND dxgiHandle; HRESULT res; +#ifdef FNA3D_DXVK_NATIVE + dxgiHandle = (HWND) windowHandle; +#else SDL_SysWMinfo info; SDL_VERSION(&info.version); SDL_GetWindowWMInfo((SDL_Window*) windowHandle, &info); dxgiHandle = info.info.win.window; +#endif /* FNA3D_DXVK_NATIVE */ /* Initialize swapchain buffer descriptor */ swapchainBufferDesc.Width = 0; diff --git a/src/dxvk_sdl2.h b/src/dxvk_sdl2.h new file mode 100644 index 00000000..e1ca079b --- /dev/null +++ b/src/dxvk_sdl2.h @@ -0,0 +1,36 @@ +#ifndef DXVK_SDL2_H +#define DXVK_SDL2_H + +#include + +extern HRESULT dxvkInitWSI(void* factory); + +#endif /* DXVK_SDL2_H */ + +#ifdef DXVK_SDL2_IMPL + +#include + +/* TODO: Define static functions for WSI vtable */ + +static const DxvkCustomWsi dxvk_sdl2_wsi = { + NULL +}; + +HRESULT dxvkInitWSI(void* factory) +{ + IDxvkWsi *wsi; + HRESULT res = IDXGIFactory1_QueryInterface( + (IDXGIFactory1*) factory, + &IID_IDxvkWsi, + (void**) &wsi + ); + if (FAILED(res)) + { + return res; + } + + return IDxvkWsi_SetWSI(wsi, &dxvk_sdl2_wsi); +} + +#endif /* DXVK_SDL2_IMPL */ diff --git a/src/dxvk_wsi.h b/src/dxvk_wsi.h new file mode 100644 index 00000000..d8e74210 --- /dev/null +++ b/src/dxvk_wsi.h @@ -0,0 +1,110 @@ +/* TODO: Could be autogenerated by WIDL, but it's not... */ + +#ifdef _WIN32 +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif +#include +#include +#endif + +#ifndef COM_NO_WINDOWS_H +#include +#include +#endif + +#ifndef DXVK_WSI_H +#define DXVK_WSI_H + +#ifndef __IDxvkWsi_FWD_DEFINED__ +#define __IDxvkWsi_FWD_DEFINED__ +typedef interface IDxvkWsi IDxvkWsi; +#ifdef __cplusplus +interface IDxvkWsi; +#endif /* __cplusplus */ +#endif + +/* DXVK WSI Application Function Table */ +typedef struct DxvkCustomWsi +{ + /* TODO: vtable to pass to IDxvkWsi */ + LPVOID filler; +} DxvkCustomWsi; + +/***************************************************************************** + * IDxvkWsi interface + */ +#ifndef __IDxvkWsi_INTERFACE_DEFINED__ +#define __IDxvkWsi_INTERFACE_DEFINED__ + +DEFINE_GUID(IID_IDxvkWsi, 0x00000000, 0x0000, 0x0000, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00); +#if defined(__cplusplus) && !defined(CINTERFACE) +MIDL_INTERFACE("00000000-0000-0000-0000-000000000000") +IDxvkWsi : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE SetWSI( + DxvkWsi *wsi) = 0; +}; +#ifdef __CRT_UUID_DECL +__CRT_UUID_DECL(IDxvkWsi, 0x00000000, 0x0000, 0x0000, 0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00) +#endif +#else +typedef struct IDxvkWsiVtbl { + BEGIN_INTERFACE + + /*** IUnknown methods ***/ + HRESULT (STDMETHODCALLTYPE *QueryInterface)( + IDxvkWsi *This, + REFIID riid, + void **ppvObject); + + ULONG (STDMETHODCALLTYPE *AddRef)( + IDxvkWsi *This); + + ULONG (STDMETHODCALLTYPE *Release)( + IDxvkWsi *This); + + /*** IDxvkWsi methods ***/ + HRESULT (STDMETHODCALLTYPE *SetWSI)( + IDxvkWsi *This, + const DxvkCustomWsi *wsi); + + END_INTERFACE +} IDxvkWsiVtbl; + +interface IDxvkWsi { + CONST_VTBL IDxvkWsiVtbl* lpVtbl; +}; + +#ifdef COBJMACROS +#ifndef WIDL_C_INLINE_WRAPPERS +/*** IUnknown methods ***/ +#define IDxvkWsi_QueryInterface(This,riid,ppvObject) (This)->lpVtbl->QueryInterface(This,riid,ppvObject) +#define IDxvkWsi_AddRef(This) (This)->lpVtbl->AddRef(This) +#define IDxvkWsi_Release(This) (This)->lpVtbl->Release(This) +/*** IDxvkWsi methods ***/ +#define IDxvkWsi_SetWSI(This,wsi) (This)->lpVtbl->SetWSI(This,wsi) +#else +/*** IUnknown methods ***/ +static FORCEINLINE HRESULT IDxvkWsi_QueryInterface(IDxvkWsi* This,REFIID riid,void **ppvObject) { + return This->lpVtbl->QueryInterface(This,riid,ppvObject); +} +static FORCEINLINE ULONG IDxvkWsi_AddRef(IDxvkWsi* This) { + return This->lpVtbl->AddRef(This); +} +static FORCEINLINE ULONG IDxvkWsi_Release(IDxvkWsi* This) { + return This->lpVtbl->Release(This); +} +/*** IDxvkWsi methods ***/ +static FORCEINLINE HRESULT IDxvkWsi_SetWSI(IDxvkWsi* This,const DxvkCustomWsi *wsi) { + return This->lpVtbl->SetWSI(This,wsi); +} +#endif +#endif + +#endif + + +#endif /* __IDxvkWsi_INTERFACE_DEFINED__ */ + +#endif /* DXVK_WSI_H */