diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index ddb82b14..f07bb804 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -1671,26 +1671,27 @@ namespace dxvk { - WineDXGISwapChainFactory::WineDXGISwapChainFactory(IUnknown* pContainer) - : m_container(pContainer) { + WineDXGISwapChainFactory::WineDXGISwapChainFactory( + IDXGIVkPresentDevice* pDevice) + : m_device(pDevice) { } ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() { - return m_container->AddRef(); + return m_device->AddRef(); } ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() { - return m_container->Release(); + return m_device->Release(); } HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface( REFIID riid, void** ppvObject) { - return m_container->QueryInterface(riid, ppvObject); + return m_device->QueryInterface(riid, ppvObject); } @@ -1703,15 +1704,13 @@ namespace dxvk { IDXGISwapChain1** ppSwapChain) { InitReturnPtr(ppSwapChain); - try { - *ppSwapChain = ref(new DxgiSwapChain( - pFactory, m_container, hWnd, - pDesc, pFullscreenDesc)); - return S_OK; - } catch (const DxvkError& e) { - Logger::err(e.message()); + if (!ppSwapChain || !pDesc || !hWnd) return DXGI_ERROR_INVALID_CALL; - } + + return CreateDxvkSwapChainForHwnd( + pFactory, m_device, hWnd, pDesc, + pFullscreenDesc, pRestrictToOutput, + ppSwapChain); } @@ -1728,7 +1727,7 @@ namespace dxvk { m_d3d11Device (this, FeatureLevel, FeatureFlags), m_d3d11Presenter(this, &m_d3d11Device), m_d3d11Interop (this, &m_d3d11Device), - m_wineFactory (this) { + m_wineFactory (&m_d3d11Presenter) { for (uint32_t i = 0; i < m_frameEvents.size(); i++) m_frameEvents[i] = new DxvkEvent(); } diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index 774e0e0e..4077864e 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -399,7 +399,8 @@ namespace dxvk { public: - WineDXGISwapChainFactory(IUnknown* pContainer); + WineDXGISwapChainFactory( + IDXGIVkPresentDevice* pDevice); ULONG STDMETHODCALLTYPE AddRef(); @@ -419,7 +420,7 @@ namespace dxvk { private: - IUnknown* m_container; + IDXGIVkPresentDevice* m_device; }; diff --git a/src/dxgi/dxgi_factory.cpp b/src/dxgi/dxgi_factory.cpp index d522d3f1..e6e681ed 100644 --- a/src/dxgi/dxgi_factory.cpp +++ b/src/dxgi/dxgi_factory.cpp @@ -110,30 +110,22 @@ namespace dxvk { IDXGISwapChain1** ppSwapChain) { InitReturnPtr(ppSwapChain); - if (ppSwapChain == nullptr || pDesc == nullptr || hWnd == nullptr || pDevice == nullptr) + if (!ppSwapChain || !pDesc || !hWnd || !pDevice) return DXGI_ERROR_INVALID_CALL; - // If necessary, set up a default set of - // fullscreen parameters for the swap chain - DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc; + Com dxvkDevice; - if (pFullscreenDesc != nullptr) { - fullscreenDesc = *pFullscreenDesc; - } else { - fullscreenDesc.RefreshRate = { 0, 0 }; - fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - fullscreenDesc.Windowed = TRUE; + if (SUCCEEDED(pDevice->QueryInterface( + __uuidof(IDXGIVkPresentDevice), + reinterpret_cast(&dxvkDevice)))) { + return CreateDxvkSwapChainForHwnd( + this, dxvkDevice.ptr(), hWnd, pDesc, + pFullscreenDesc, pRestrictToOutput, + ppSwapChain); } - try { - *ppSwapChain = ref(new DxgiSwapChain(this, - pDevice, hWnd, pDesc, &fullscreenDesc)); - return S_OK; - } catch (const DxvkError& e) { - Logger::err(e.message()); - return E_FAIL; - } + Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type"); + return DXGI_ERROR_UNSUPPORTED; } diff --git a/src/dxgi/dxgi_swapchain.cpp b/src/dxgi/dxgi_swapchain.cpp index d56eb972..a0a20d93 100644 --- a/src/dxgi/dxgi_swapchain.cpp +++ b/src/dxgi/dxgi_swapchain.cpp @@ -6,15 +6,16 @@ namespace dxvk { DxgiSwapChain::DxgiSwapChain( IDXGIFactory* pFactory, - IUnknown* pDevice, + IDXGIVkSwapChain* pPresenter, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc) - : m_factory (pFactory), - m_window (hWnd), - m_desc (*pDesc), - m_descFs (*pFullscreenDesc), - m_monitor (nullptr) { + : m_factory (pFactory), + m_window (hWnd), + m_desc (*pDesc), + m_descFs (*pFullscreenDesc), + m_presenter (pPresenter), + m_monitor (nullptr) { // Initialize frame statistics m_stats.PresentCount = 0; m_stats.PresentRefreshCount = 0; @@ -22,20 +23,10 @@ namespace dxvk { m_stats.SyncQPCTime.QuadPart = 0; m_stats.SyncGPUTime.QuadPart = 0; - // Adjust initial back buffer size. If zero, these - // shall be set to the current window size. - GetWindowClientSize(m_window, - m_desc.Width ? nullptr : &m_desc.Width, - m_desc.Height ? nullptr : &m_desc.Height); - - // Create presenter, which also serves as an interface to the device - if (FAILED(CreatePresenter(pDevice, &m_presenter))) - throw DxvkError("DXGI: Failed to create presenter"); - if (FAILED(m_presenter->GetAdapter(__uuidof(IDXGIAdapter), reinterpret_cast(&m_adapter)))) throw DxvkError("DXGI: Failed to get adapter for present device"); - // Set initial window mode and fullscreen state + // Apply initial window mode and fullscreen state if (!m_descFs.Windowed && FAILED(EnterFullscreenMode(nullptr))) throw DxvkError("DXGI: Failed to set initial fullscreen state"); } @@ -674,21 +665,6 @@ namespace dxvk { } - HRESULT DxgiSwapChain::CreatePresenter( - IUnknown* pDevice, - IDXGIVkSwapChain** ppSwapChain) { - Com presentDevice; - - // Retrieve a device pointer that allows us to - // communicate with the underlying D3D device - if (SUCCEEDED(pDevice->QueryInterface(__uuidof(IDXGIVkPresentDevice), - reinterpret_cast(&presentDevice)))) - return presentDevice->CreateSwapChainForHwnd(m_window, &m_desc, ppSwapChain); - - return E_INVALIDARG; - } - - HRESULT DxgiSwapChain::GetOutputFromMonitor( HMONITOR Monitor, IDXGIOutput** ppOutput) { @@ -709,4 +685,53 @@ namespace dxvk { return DXGI_ERROR_NOT_FOUND; } + + HRESULT CreateDxvkSwapChainForHwnd( + IDXGIFactory* pFactory, + IDXGIVkPresentDevice* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain) { + // Make sure the back buffer size is not zero + DXGI_SWAP_CHAIN_DESC1 desc = *pDesc; + + GetWindowClientSize(hWnd, + desc.Width ? nullptr : &desc.Width, + desc.Height ? nullptr : &desc.Height); + + // If necessary, set up a default set of + // fullscreen parameters for the swap chain + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc; + + if (pFullscreenDesc) { + fsDesc = *pFullscreenDesc; + } else { + fsDesc.RefreshRate = { 0, 0 }; + fsDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + fsDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + fsDesc.Windowed = TRUE; + } + + // Create presenter for the device + Com presenter; + + HRESULT hr = pDevice->CreateSwapChainForHwnd( + hWnd, &desc, &presenter); + + if (FAILED(hr)) + return hr; + + try { + // Create actual swap chain object + *ppSwapChain = ref(new DxgiSwapChain( + pFactory, presenter.ptr(), hWnd, &desc, &fsDesc)); + return S_OK; + } catch (const DxvkError& e) { + Logger::err(e.message()); + return DXGI_ERROR_UNSUPPORTED; + } + } + } diff --git a/src/dxgi/dxgi_swapchain.h b/src/dxgi/dxgi_swapchain.h index 5e7f2eed..8e7f7aa0 100644 --- a/src/dxgi/dxgi_swapchain.h +++ b/src/dxgi/dxgi_swapchain.h @@ -22,7 +22,7 @@ namespace dxvk { DxgiSwapChain( IDXGIFactory* pFactory, - IUnknown* pDevice, + IDXGIVkSwapChain* pPresenter, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc); @@ -199,14 +199,20 @@ namespace dxvk { UINT Count, VkSampleCountFlagBits* pCount) const; - HRESULT CreatePresenter( - IUnknown* pDevice, - IDXGIVkSwapChain** ppSwapChain); - HRESULT GetOutputFromMonitor( - HMONITOR Monitor, - IDXGIOutput** ppOutput); + HMONITOR Monitor, + IDXGIOutput** ppOutput); }; + + HRESULT CreateDxvkSwapChainForHwnd( + IDXGIFactory* pFactory, + IDXGIVkPresentDevice* pDevice, + HWND hWnd, + const DXGI_SWAP_CHAIN_DESC1* pDesc, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, + IDXGIOutput* pRestrictToOutput, + IDXGISwapChain1** ppSwapChain); + }