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:
parent
15078357dc
commit
4e22e4bc3a
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,15 +6,16 @@ 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)
|
||||||
: m_factory (pFactory),
|
: m_factory (pFactory),
|
||||||
m_window (hWnd),
|
m_window (hWnd),
|
||||||
m_desc (*pDesc),
|
m_desc (*pDesc),
|
||||||
m_descFs (*pFullscreenDesc),
|
m_descFs (*pFullscreenDesc),
|
||||||
m_monitor (nullptr) {
|
m_presenter (pPresenter),
|
||||||
|
m_monitor (nullptr) {
|
||||||
// Initialize frame statistics
|
// Initialize frame statistics
|
||||||
m_stats.PresentCount = 0;
|
m_stats.PresentCount = 0;
|
||||||
m_stats.PresentRefreshCount = 0;
|
m_stats.PresentRefreshCount = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user