1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[dxgi] Refactor swap chain creation

Cleans up constructor and moves a bunch of common code
to the new CreateDxvkSwapChainForHwnd function, which
can be called from both d3d11 and dxgi.

Also fixes potential issues with the current implementation
of the IWineDXGISwapChainFactory interface.
This commit is contained in:
Philip Rebohle 2018-12-21 15:53:29 +01:00
parent 15078357dc
commit 4e22e4bc3a
5 changed files with 97 additions and 74 deletions

View File

@ -1671,26 +1671,27 @@ namespace dxvk {
WineDXGISwapChainFactory::WineDXGISwapChainFactory(IUnknown* pContainer) WineDXGISwapChainFactory::WineDXGISwapChainFactory(
: m_container(pContainer) { IDXGIVkPresentDevice* pDevice)
: m_device(pDevice) {
} }
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() { ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::AddRef() {
return m_container->AddRef(); return m_device->AddRef();
} }
ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() { ULONG STDMETHODCALLTYPE WineDXGISwapChainFactory::Release() {
return m_container->Release(); return m_device->Release();
} }
HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface( HRESULT STDMETHODCALLTYPE WineDXGISwapChainFactory::QueryInterface(
REFIID riid, REFIID riid,
void** ppvObject) { void** ppvObject) {
return m_container->QueryInterface(riid, ppvObject); return m_device->QueryInterface(riid, ppvObject);
} }
@ -1703,15 +1704,13 @@ namespace dxvk {
IDXGISwapChain1** ppSwapChain) { IDXGISwapChain1** ppSwapChain) {
InitReturnPtr(ppSwapChain); InitReturnPtr(ppSwapChain);
try { if (!ppSwapChain || !pDesc || !hWnd)
*ppSwapChain = ref(new DxgiSwapChain(
pFactory, m_container, hWnd,
pDesc, pFullscreenDesc));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return DXGI_ERROR_INVALID_CALL; 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_d3d11Device (this, FeatureLevel, FeatureFlags),
m_d3d11Presenter(this, &m_d3d11Device), m_d3d11Presenter(this, &m_d3d11Device),
m_d3d11Interop (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++) for (uint32_t i = 0; i < m_frameEvents.size(); i++)
m_frameEvents[i] = new DxvkEvent(); m_frameEvents[i] = new DxvkEvent();
} }

View File

@ -399,7 +399,8 @@ namespace dxvk {
public: public:
WineDXGISwapChainFactory(IUnknown* pContainer); WineDXGISwapChainFactory(
IDXGIVkPresentDevice* pDevice);
ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE AddRef();
@ -419,7 +420,7 @@ namespace dxvk {
private: private:
IUnknown* m_container; IDXGIVkPresentDevice* m_device;
}; };

View File

@ -110,30 +110,22 @@ namespace dxvk {
IDXGISwapChain1** ppSwapChain) { IDXGISwapChain1** ppSwapChain) {
InitReturnPtr(ppSwapChain); InitReturnPtr(ppSwapChain);
if (ppSwapChain == nullptr || pDesc == nullptr || hWnd == nullptr || pDevice == nullptr) if (!ppSwapChain || !pDesc || !hWnd || !pDevice)
return DXGI_ERROR_INVALID_CALL; return DXGI_ERROR_INVALID_CALL;
// If necessary, set up a default set of Com<IDXGIVkPresentDevice> dxvkDevice;
// fullscreen parameters for the swap chain
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
if (pFullscreenDesc != nullptr) { if (SUCCEEDED(pDevice->QueryInterface(
fullscreenDesc = *pFullscreenDesc; __uuidof(IDXGIVkPresentDevice),
} else { reinterpret_cast<void**>(&dxvkDevice)))) {
fullscreenDesc.RefreshRate = { 0, 0 }; return CreateDxvkSwapChainForHwnd(
fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; this, dxvkDevice.ptr(), hWnd, pDesc,
fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; pFullscreenDesc, pRestrictToOutput,
fullscreenDesc.Windowed = TRUE; ppSwapChain);
} }
try { Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type");
*ppSwapChain = ref(new DxgiSwapChain(this, return DXGI_ERROR_UNSUPPORTED;
pDevice, hWnd, pDesc, &fullscreenDesc));
return S_OK;
} catch (const DxvkError& e) {
Logger::err(e.message());
return E_FAIL;
}
} }

View File

@ -6,7 +6,7 @@ namespace dxvk {
DxgiSwapChain::DxgiSwapChain( DxgiSwapChain::DxgiSwapChain(
IDXGIFactory* pFactory, IDXGIFactory* pFactory,
IUnknown* pDevice, IDXGIVkSwapChain* pPresenter,
HWND hWnd, HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc) const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc)
@ -14,6 +14,7 @@ namespace dxvk {
m_window (hWnd), m_window (hWnd),
m_desc (*pDesc), m_desc (*pDesc),
m_descFs (*pFullscreenDesc), m_descFs (*pFullscreenDesc),
m_presenter (pPresenter),
m_monitor (nullptr) { m_monitor (nullptr) {
// Initialize frame statistics // Initialize frame statistics
m_stats.PresentCount = 0; m_stats.PresentCount = 0;
@ -22,20 +23,10 @@ namespace dxvk {
m_stats.SyncQPCTime.QuadPart = 0; m_stats.SyncQPCTime.QuadPart = 0;
m_stats.SyncGPUTime.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<void**>(&m_adapter)))) if (FAILED(m_presenter->GetAdapter(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&m_adapter))))
throw DxvkError("DXGI: Failed to get adapter for present device"); 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))) if (!m_descFs.Windowed && FAILED(EnterFullscreenMode(nullptr)))
throw DxvkError("DXGI: Failed to set initial fullscreen state"); throw DxvkError("DXGI: Failed to set initial fullscreen state");
} }
@ -674,21 +665,6 @@ namespace dxvk {
} }
HRESULT DxgiSwapChain::CreatePresenter(
IUnknown* pDevice,
IDXGIVkSwapChain** ppSwapChain) {
Com<IDXGIVkPresentDevice> presentDevice;
// Retrieve a device pointer that allows us to
// communicate with the underlying D3D device
if (SUCCEEDED(pDevice->QueryInterface(__uuidof(IDXGIVkPresentDevice),
reinterpret_cast<void**>(&presentDevice))))
return presentDevice->CreateSwapChainForHwnd(m_window, &m_desc, ppSwapChain);
return E_INVALIDARG;
}
HRESULT DxgiSwapChain::GetOutputFromMonitor( HRESULT DxgiSwapChain::GetOutputFromMonitor(
HMONITOR Monitor, HMONITOR Monitor,
IDXGIOutput** ppOutput) { IDXGIOutput** ppOutput) {
@ -709,4 +685,53 @@ namespace dxvk {
return DXGI_ERROR_NOT_FOUND; 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<IDXGIVkSwapChain> 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;
}
}
} }

View File

@ -22,7 +22,7 @@ namespace dxvk {
DxgiSwapChain( DxgiSwapChain(
IDXGIFactory* pFactory, IDXGIFactory* pFactory,
IUnknown* pDevice, IDXGIVkSwapChain* pPresenter,
HWND hWnd, HWND hWnd,
const DXGI_SWAP_CHAIN_DESC1* pDesc, const DXGI_SWAP_CHAIN_DESC1* pDesc,
const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc); const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc);
@ -199,14 +199,20 @@ namespace dxvk {
UINT Count, UINT Count,
VkSampleCountFlagBits* pCount) const; VkSampleCountFlagBits* pCount) const;
HRESULT CreatePresenter(
IUnknown* pDevice,
IDXGIVkSwapChain** ppSwapChain);
HRESULT GetOutputFromMonitor( HRESULT GetOutputFromMonitor(
HMONITOR Monitor, HMONITOR Monitor,
IDXGIOutput** ppOutput); 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);
} }