diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-08-13 05:00:42 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-08-13 05:00:42 +0000 |
| commit | 97b32f52cc123544a1352527c2509c804fd3d190 (patch) | |
| tree | 6fe5dc267b8a9087df2afe9bca871f9607438391 /Graphics | |
| parent | D3D11 backend: enabled multiple swap chain support (diff) | |
| download | DiligentCore-97b32f52cc123544a1352527c2509c804fd3d190.tar.gz DiligentCore-97b32f52cc123544a1352527c2509c804fd3d190.zip | |
D3D12 backend: enabled multiple swap chain support
Diffstat (limited to 'Graphics')
6 files changed, 101 insertions, 79 deletions
diff --git a/Graphics/GraphicsEngine/include/SwapChainBase.h b/Graphics/GraphicsEngine/include/SwapChainBase.h index 8b9aa86f..5a60c9ed 100644 --- a/Graphics/GraphicsEngine/include/SwapChainBase.h +++ b/Graphics/GraphicsEngine/include/SwapChainBase.h @@ -26,6 +26,8 @@ /// \file /// Implementation of the Diligent::SwapChainBase template class +#include <array> + #include "RenderDevice.h" #include "DeviceContext.h" #include "SwapChain.h" @@ -89,13 +91,55 @@ protected: return false; } - + + template<typename DeviceContextImplType> + bool UnbindRenderTargets(DeviceContextImplType* pImmediateCtx, + ITextureView* ppBackBufferRTVs[], + Uint32 NumBackBufferRTVs, + ITextureView* pDSV) + { + bool RebindRenderTargets = false; + bool UnbindRenderTargets = false; + if (m_SwapChainDesc.IsPrimary) + { + RebindRenderTargets = UnbindRenderTargets = pImmediateCtx->IsDefaultFBBound(); + } + else + { + std::array<ITextureView*, MaxRenderTargets> pBoundRTVs = {}; + RefCntAutoPtr<ITextureView> pBoundDSV; + Uint32 NumRenderTargets = 0; + pImmediateCtx->GetRenderTargets(NumRenderTargets, pBoundRTVs.data(), &pBoundDSV); + for (Uint32 i=0; i < NumRenderTargets; ++i) + { + for (Uint32 j=0; j < NumBackBufferRTVs; ++j) + { + if (pBoundRTVs[i] == ppBackBufferRTVs[j]) + UnbindRenderTargets = true; + } + } + if (pBoundDSV == pDSV) + UnbindRenderTargets = true; + + for (auto pRTV : pBoundRTVs) + { + if (pRTV != nullptr) + pRTV->Release(); + } + } + + if (UnbindRenderTargets) + pImmediateCtx->ResetRenderTargets(); + + return RebindRenderTargets; + } + /// Strong reference to the render device - Diligent::RefCntAutoPtr<IRenderDevice> m_pRenderDevice; + RefCntAutoPtr<IRenderDevice> m_pRenderDevice; /// Weak references to the immediate device context. The context holds /// the strong reference to the swap chain. - Diligent::RefCntWeakPtr<IDeviceContext> m_wpDeviceContext; + RefCntWeakPtr<IDeviceContext> m_wpDeviceContext; /// Swap chain description SwapChainDesc m_SwapChainDesc; diff --git a/Graphics/GraphicsEngine/interface/SwapChain.h b/Graphics/GraphicsEngine/interface/SwapChain.h index 5e780292..164608e1 100644 --- a/Graphics/GraphicsEngine/interface/SwapChain.h +++ b/Graphics/GraphicsEngine/interface/SwapChain.h @@ -54,6 +54,9 @@ public: /// \param [in] NewWidth - New swap chain width, in pixels /// \param [in] NewHeight - New swap chain height, in pixels + /// + /// \note When resizing non-primary swap chains, the engine unbinds the + /// swap chain buffers from the output. virtual void Resize( Uint32 NewWidth, Uint32 NewHeight ) = 0; /// Sets fullscreen mode (only supported on Win32 platform) diff --git a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp index 40a3eb16..87ffbdc5 100644 --- a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp @@ -315,7 +315,7 @@ void EngineFactoryD3D11Impl::CreateSwapChainD3D11(IRenderDevice* pDev if (pDeviceContextD3D11->GetSwapChain() != nullptr && SCDesc.IsPrimary) { LOG_ERROR_AND_THROW("Another swap chain labeled as primary has already been created. " - "There must be only one primary swap chain."); + "There must only be one primary swap chain."); } auto* pSwapChainD3D11 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D11Impl instance", SwapChainD3D11Impl) diff --git a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp index 225e3a98..0ffc8070 100644 --- a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp @@ -21,7 +21,6 @@ * of the possibility of such damages. */ -#include <array> #include "pch.h" #include "SwapChainD3D11Impl.h" #include "RenderDeviceD3D11Impl.h" @@ -144,38 +143,9 @@ void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) VERIFY(pDeviceContext, "Immediate context has been released"); if (pDeviceContext) { - auto *pImmediateCtxD3D11 = pDeviceContext.RawPtr<DeviceContextD3D11Impl>(); - bool RebindRenderTargets = false; - bool UnbindRenderTargets = false; - if (m_SwapChainDesc.IsPrimary) - { - RebindRenderTargets = UnbindRenderTargets = pImmediateCtxD3D11->IsDefaultFBBound(); - } - else - { - std::array<ITextureView*, MaxRenderTargets> pOrigRTVs = {}; - RefCntAutoPtr<ITextureView> pOrigDSV; - Uint32 NumRenderTargets = 0; - pImmediateCtxD3D11->GetRenderTargets(NumRenderTargets, pOrigRTVs.data(), &pOrigDSV); - for (Uint32 i=0; i < NumRenderTargets; ++i) - { - if (pOrigRTVs[i] == m_pRenderTargetView) - UnbindRenderTargets = true; - } - if (pOrigDSV == m_pDepthStencilView) - UnbindRenderTargets = true; - - RebindRenderTargets = NumRenderTargets == 1 && pOrigRTVs[0] == m_pRenderTargetView && pOrigDSV == m_pDepthStencilView; - - for(auto pRTV : pOrigRTVs) - { - if (pRTV != nullptr) - pRTV->Release(); - } - } - - if (UnbindRenderTargets) - pImmediateCtxD3D11->ResetRenderTargets(); + auto* pImmediateCtxD3D11 = pDeviceContext.RawPtr<DeviceContextD3D11Impl>(); + ITextureView* pBackBufferRTVs[] = {m_pRenderTargetView}; + bool RebindRenderTargets = UnbindRenderTargets(pImmediateCtxD3D11, pBackBufferRTVs, 1, m_pDepthStencilView); // Swap chain cannot be resized until all references are released m_pRenderTargetView.Release(); @@ -214,19 +184,11 @@ void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) CreateRTVandDSV(); - if (RebindRenderTargets) + if (m_SwapChainDesc.IsPrimary && RebindRenderTargets) { - if (m_SwapChainDesc.IsPrimary) - { - // Set default render target and viewport - pImmediateCtxD3D11->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pImmediateCtxD3D11->SetViewports(1, nullptr, 0, 0); - } - else - { - ITextureView* pRTVs[] = {GetCurrentBackBufferRTV()}; - pImmediateCtxD3D11->SetRenderTargets(1, pRTVs, GetDepthBufferDSV(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - } + // Set default render target and viewport + pImmediateCtxD3D11->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); + pImmediateCtxD3D11->SetViewports(1, nullptr, 0, 0); } } catch (const std::runtime_error &) diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp index 53ede9e3..3c20c1bc 100644 --- a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp @@ -367,29 +367,39 @@ void EngineFactoryD3D12Impl::CreateSwapChainD3D12(IRenderDevice* pDev try { - auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pDevice ); - auto *pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pImmediateContext); - auto &RawMemAllocator = GetRawAllocator(); - auto *pSwapChainD3D12 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D12Impl instance", SwapChainD3D12Impl)(SCDesc, FSDesc, pDeviceD3D12, pDeviceContextD3D12, pNativeWndHandle); + auto* pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pDevice ); + auto* pDeviceContextD3D12 = ValidatedCast<DeviceContextD3D12Impl>(pImmediateContext); + auto& RawMemAllocator = GetRawAllocator(); + + if (pDeviceContextD3D12->GetSwapChain() != nullptr && SCDesc.IsPrimary) + { + LOG_ERROR_AND_THROW("Another swap chain labeled as primary has already been created. " + "There must only be one primary swap chain."); + } + + auto* pSwapChainD3D12 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D12Impl instance", SwapChainD3D12Impl)(SCDesc, FSDesc, pDeviceD3D12, pDeviceContextD3D12, pNativeWndHandle); pSwapChainD3D12->QueryInterface( IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain) ); - pDeviceContextD3D12->SetSwapChain(pSwapChainD3D12); - // Bind default render target - pDeviceContextD3D12->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); - // Set default viewport - pDeviceContextD3D12->SetViewports( 1, nullptr, 0, 0 ); - - auto NumDeferredCtx = pDeviceD3D12->GetNumDeferredContexts(); - for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) + if (SCDesc.IsPrimary) { - if (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx)) + pDeviceContextD3D12->SetSwapChain(pSwapChainD3D12); + // Bind default render target + pDeviceContextD3D12->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); + // Set default viewport + pDeviceContextD3D12->SetViewports( 1, nullptr, 0, 0 ); + + auto NumDeferredCtx = pDeviceD3D12->GetNumDeferredContexts(); + for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) { - auto* pDeferredCtxD3D12 = pDeferredCtx.RawPtr<DeviceContextD3D12Impl>(); - pDeferredCtxD3D12->SetSwapChain(pSwapChainD3D12); - // We cannot bind default render target here because - // there is no guarantee that deferred context will be used - // in this frame. It is an error to bind - // RTV of an inactive buffer in the swap chain + if (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx)) + { + auto* pDeferredCtxD3D12 = pDeferredCtx.RawPtr<DeviceContextD3D12Impl>(); + pDeferredCtxD3D12->SetSwapChain(pSwapChainD3D12); + // We cannot bind default render target here because + // there is no guarantee that deferred context will be used + // in this frame. It is an error to bind + // RTV of an inactive buffer in the swap chain + } } } } diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp index c9e986b4..8658d649 100644 --- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp @@ -111,7 +111,7 @@ void SwapChainD3D12Impl::Present(Uint32 SyncInterval) #endif auto pDeviceContext = m_wpDeviceContext.Lock(); - if( !pDeviceContext ) + if (!pDeviceContext) { LOG_ERROR_MESSAGE( "Immediate context has been released" ); return; @@ -120,18 +120,20 @@ void SwapChainD3D12Impl::Present(Uint32 SyncInterval) auto* pImmediateCtxD3D12 = pDeviceContext.RawPtr<DeviceContextD3D12Impl>(); auto& CmdCtx = pImmediateCtxD3D12->GetCmdContext(); - auto* pBackBuffer = ValidatedCast<TextureD3D12Impl>( GetCurrentBackBufferRTV()->GetTexture() ); + auto* pBackBuffer = ValidatedCast<TextureD3D12Impl>(GetCurrentBackBufferRTV()->GetTexture()); CmdCtx.TransitionResource(pBackBuffer, RESOURCE_STATE_PRESENT); pImmediateCtxD3D12->Flush(); - auto *pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pImmediateCtxD3D12->GetDevice() ); - auto hr = m_pSwapChain->Present( SyncInterval, 0 ); VERIFY(SUCCEEDED(hr), "Present failed"); - pImmediateCtxD3D12->FinishFrame(); - pDeviceD3D12->ReleaseStaleResources(); + if (m_SwapChainDesc.IsPrimary) + { + pImmediateCtxD3D12->FinishFrame(); + auto* pDeviceD3D12 = ValidatedCast<RenderDeviceD3D12Impl>( pImmediateCtxD3D12->GetDevice() ); + pDeviceD3D12->ReleaseStaleResources(); + } #if 0 #if PLATFORM_UNIVERSAL_WINDOWS @@ -160,10 +162,11 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) try { - auto *pImmediateCtxD3D12 = pDeviceContext.RawPtr<DeviceContextD3D12Impl>(); - bool bIsDefaultFBBound = pImmediateCtxD3D12->IsDefaultFBBound(); - if(bIsDefaultFBBound) - pImmediateCtxD3D12->ResetRenderTargets(); + auto* pImmediateCtxD3D12 = pDeviceContext.RawPtr<DeviceContextD3D12Impl>(); + std::vector<ITextureView*> pBackBufferRTVs(m_pBackBufferRTV.size()); + for(size_t i=0; i < m_pBackBufferRTV.size(); ++i) + pBackBufferRTVs[i] = m_pBackBufferRTV[i]; + bool RebindRenderTargets = UnbindRenderTargets(pImmediateCtxD3D12, pBackBufferRTVs.data(), static_cast<Uint32>(m_pBackBufferRTV.size()), m_pDepthBufferDSV); // All references to the swap chain must be released before it can be resized m_pBackBufferRTV.clear(); @@ -196,7 +199,7 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) InitBuffersAndViews(); - if (bIsDefaultFBBound) + if (m_SwapChainDesc.IsPrimary && RebindRenderTargets) { // Set default render target and viewport pDeviceContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); |
