From 528cacca5f0dd2d67275d09c41ca3aabfa9d2a9b Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Fri, 28 Feb 2020 01:27:41 +0000 Subject: [PATCH] [d3d9] Only have a single implicit swapchain I am naive to think that this API is in any way sane, and that iSwapChains actually does what you would expect. Swapchains created by CreateAdditionalSwapchain[Ex] are not tracked in that figure... There can only ever be one. Great API. Very cool. This also adds and consolidates some missing thread synchronization on the swapchain functions (that should have already had it). (note: m_implicitSwapchain always exists, so we don't need to lock if that's all we call.) --- src/d3d9/d3d9_device.cpp | 105 ++++++++++++++---------------------- src/d3d9/d3d9_device.h | 6 +-- src/d3d9/d3d9_swapchain.cpp | 15 ++++-- 3 files changed, 53 insertions(+), 73 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 71c68a12..441e258c 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -161,12 +161,10 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->GetDisplayMode(pMode); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->GetDisplayMode(pMode); } @@ -270,21 +268,24 @@ namespace dxvk { InitReturnPtr(pSwapChain); - auto* swapchain = GetInternalSwapchain(iSwapChain); - - if (unlikely(swapchain == nullptr || pSwapChain == nullptr)) + if (unlikely(pSwapChain == nullptr)) return D3DERR_INVALIDCALL; - *pSwapChain = static_cast(ref(swapchain)); + // This only returns the implicit swapchain... + + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; + + *pSwapChain = static_cast(m_implicitSwapchain.ref()); return D3D_OK; } UINT STDMETHODCALLTYPE D3D9DeviceEx::GetNumberOfSwapChains() { - D3D9DeviceLock lock = LockDevice(); + // This only counts the implicit swapchain... - return UINT(m_swapchains.size()); + return 1; } @@ -325,31 +326,23 @@ namespace dxvk { UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - InitReturnPtr(ppBackBuffer); - - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->GetBackBuffer(iBackBuffer, Type, ppBackBuffer); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->GetBackBuffer(iBackBuffer, Type, ppBackBuffer); } HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->GetRasterStatus(pRasterStatus); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->GetRasterStatus(pRasterStatus); } HRESULT STDMETHODCALLTYPE D3D9DeviceEx::SetDialogBoxMode(BOOL bEnableDialogs) { - D3D9DeviceLock lock = LockDevice(); - - return GetInternalSwapchain(0)->SetDialogBoxMode(bEnableDialogs); + return m_implicitSwapchain->SetDialogBoxMode(bEnableDialogs); } @@ -357,18 +350,18 @@ namespace dxvk { UINT iSwapChain, DWORD Flags, const D3DGAMMARAMP* pRamp) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - swapchain->SetGammaRamp(Flags, pRamp); + m_implicitSwapchain->SetGammaRamp(Flags, pRamp); } void STDMETHODCALLTYPE D3D9DeviceEx::GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - swapchain->GetGammaRamp(pRamp); + m_implicitSwapchain->GetGammaRamp(pRamp); } @@ -818,12 +811,10 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9DeviceEx::GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->GetFrontBufferData(pDestSurface); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->GetFrontBufferData(pDestSurface); } @@ -3215,12 +3206,10 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9DeviceEx::WaitForVBlank(UINT iSwapChain) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->WaitForVBlank(); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->WaitForVBlank(); } @@ -3268,9 +3257,7 @@ namespace dxvk { HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags) { - D3D9DeviceLock lock = LockDevice(); - - return GetInternalSwapchain(0)->Present( + return m_implicitSwapchain->Present( pSourceRect, pDestRect, hDestWindowOverride, @@ -3429,12 +3416,10 @@ namespace dxvk { UINT iSwapChain, D3DDISPLAYMODEEX* pMode, D3DDISPLAYROTATION* pRotation) { - D3D9DeviceLock lock = LockDevice(); + if (unlikely(iSwapChain != 0)) + return D3DERR_INVALIDCALL; - if (auto* swapchain = GetInternalSwapchain(iSwapChain)) - return swapchain->GetDisplayModeEx(pMode, pRotation); - - return D3DERR_INVALIDCALL; + return m_implicitSwapchain->GetDisplayModeEx(pMode, pRotation); } @@ -3449,14 +3434,12 @@ namespace dxvk { if (ppSwapChain == nullptr || pPresentationParameters == nullptr) return D3DERR_INVALIDCALL; - for (uint32_t i = 0; i < m_swapchains.size(); i++) - GetInternalSwapchain(i)->Invalidate(pPresentationParameters->hDeviceWindow); + m_implicitSwapchain->Invalidate(pPresentationParameters->hDeviceWindow); try { auto* swapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode); *ppSwapChain = ref(swapchain); - m_swapchains.push_back(swapchain); swapchain->AddRefPrivate(); } catch (const DxvkError & e) { @@ -3732,14 +3715,6 @@ namespace dxvk { } - D3D9SwapChainEx* D3D9DeviceEx::GetInternalSwapchain(UINT index) { - if (unlikely(index >= m_swapchains.size())) - return nullptr; - - return m_swapchains[index].ptr(); - } - - bool D3D9DeviceEx::ShouldRecord() { return m_recorder != nullptr && !m_recorder->IsApplying(); } @@ -6646,10 +6621,10 @@ namespace dxvk { } } - if (auto* implicitSwapchain = GetInternalSwapchain(0)) - implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode); + if (m_implicitSwapchain != nullptr) + m_implicitSwapchain->Reset(pPresentationParameters, pFullscreenDisplayMode); else - m_swapchains.emplace_back(new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode)); + m_implicitSwapchain = new D3D9SwapChainEx(this, pPresentationParameters, pFullscreenDisplayMode); if (pPresentationParameters->EnableAutoDepthStencil) { D3D9_COMMON_TEXTURE_DESC desc; @@ -6673,7 +6648,7 @@ namespace dxvk { SetDepthStencilSurface(m_autoDepthStencil.ptr()); } - SetRenderTarget(0, GetInternalSwapchain(0)->GetBackBuffer(0)); + SetRenderTarget(0, m_implicitSwapchain->GetBackBuffer(0)); // Force this if we end up binding the same RT to make scissor change go into effect. BindViewportAndScissor(); diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index 3b0d3e7c..bc4ce408 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -1002,9 +1002,7 @@ namespace dxvk { Com m_autoDepthStencil; - std::vector< - Com> m_swapchains; + Com m_implicitSwapchain; std::unordered_map< D3D9SamplerKey, @@ -1058,8 +1056,6 @@ namespace dxvk { D3D9UPBufferSlice AllocUpBuffer(VkDeviceSize size); - D3D9SwapChainEx* GetInternalSwapchain(UINT index); - bool ShouldRecord(); HRESULT CreateShaderModule( diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 00e804e3..0a92ab93 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -89,7 +89,7 @@ namespace dxvk { HWND hDestWindowOverride, const RGNDATA* pDirtyRegion, DWORD dwFlags) { - auto lock = m_parent->LockDevice(); + D3D9DeviceLock lock = m_parent->LockDevice(); uint32_t presentInterval = m_presentParams.PresentationInterval; @@ -152,7 +152,7 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) { - auto lock = m_parent->LockDevice(); + D3D9DeviceLock lock = m_parent->LockDevice(); // This function can do absolutely everything! // Copies the front buffer between formats with an implicit resolve. @@ -331,6 +331,9 @@ namespace dxvk { UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) { + // Could be doing a device reset... + D3D9DeviceLock lock = m_parent->LockDevice(); + if (unlikely(ppBackBuffer == nullptr)) return D3DERR_INVALIDCALL; @@ -454,7 +457,7 @@ namespace dxvk { void D3D9SwapChainEx::Reset( D3DPRESENT_PARAMETERS* pPresentParams, D3DDISPLAYMODEEX* pFullscreenDisplayMode) { - auto lock = m_parent->LockDevice(); + D3D9DeviceLock lock = m_parent->LockDevice(); this->SynchronizePresent(); this->NormalizePresentParameters(pPresentParams); @@ -516,6 +519,8 @@ namespace dxvk { void D3D9SwapChainEx::SetGammaRamp( DWORD Flags, const D3DGAMMARAMP* pRamp) { + D3D9DeviceLock lock = m_parent->LockDevice(); + if (unlikely(pRamp == nullptr)) return; @@ -546,6 +551,8 @@ namespace dxvk { void D3D9SwapChainEx::GetGammaRamp(D3DGAMMARAMP* pRamp) { + D3D9DeviceLock lock = m_parent->LockDevice(); + if (likely(pRamp != nullptr)) *pRamp = m_ramp; } @@ -565,6 +572,8 @@ namespace dxvk { HRESULT D3D9SwapChainEx::SetDialogBoxMode(bool bEnableDialogs) { + D3D9DeviceLock lock = m_parent->LockDevice(); + // https://docs.microsoft.com/en-us/windows/win32/api/d3d9/nf-d3d9-idirect3ddevice9-setdialogboxmode // The MSDN documentation says this will error out under many weird conditions. // However it doesn't appear to error at all in any of my tests of these