From 4fd74ca8444da6491d5ec5f5e2b569c09cba2b3a Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 23 Dec 2019 21:24:13 -0800 Subject: Disabled SetRenderTarget(0, nullptr, nullptr) usage (fixed https://github.com/DiligentGraphics/DiligentCore/issues/81) --- .../GraphicsEngine/include/DeviceContextBase.h | 144 ++++++++------------- Graphics/GraphicsEngine/include/SwapChainBase.h | 42 ------ Graphics/GraphicsEngine/interface/APIInfo.h | 2 +- Graphics/GraphicsEngine/interface/DeviceContext.h | 26 +--- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 6 +- .../src/DeviceContextD3D11Impl.cpp | 66 +++------- .../GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp | 31 ----- .../GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp | 18 ++- .../src/DeviceContextD3D12Impl.cpp | 51 ++------ .../GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp | 29 ----- .../GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp | 28 ++-- .../include/DeviceContextGLImpl.h | 10 ++ .../src/DeviceContextGLImpl.cpp | 60 +++++---- .../src/EngineFactoryOpenGL.cpp | 3 - .../GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp | 15 +-- .../src/DeviceContextVkImpl.cpp | 26 ++-- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 30 ----- .../GraphicsEngineVulkan/src/SwapChainVkImpl.cpp | 32 ++--- 18 files changed, 180 insertions(+), 439 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.h b/Graphics/GraphicsEngine/include/DeviceContextBase.h index a9bba8bd..dee85899 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.h +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.h @@ -30,12 +30,10 @@ #include "DeviceContext.h" #include "DeviceObjectBase.h" -#include "Defines.h" #include "ResourceMapping.h" #include "Sampler.h" #include "ObjectBase.h" #include "DebugUtilities.h" -#include "SwapChain.h" #include "ValidatedCast.h" #include "GraphicsAccessories.h" #include "TextureBase.h" @@ -165,19 +163,10 @@ public: virtual void GenerateMips(ITextureView* pTexView) override = 0; - /// Sets the strong pointer to the swap chain - virtual void SetSwapChain(ISwapChain* pSwapChain) override final { m_pSwapChain = pSwapChain; } - virtual void ResolveTextureSubresource(ITexture* pSrcTexture, ITexture* pDstTexture, const ResolveTextureSubresourceAttribs& ResolveAttribs) override = 0; - /// Returns the swap chain - ISwapChain* GetSwapChain() { return m_pSwapChain; } - - /// Returns true if currently bound frame buffer is the default frame buffer - inline bool IsDefaultFBBound() { return m_IsDefaultFramebufferBound; } - /// Returns currently bound pipeline state and blend factors inline void GetPipelineState(IPipelineState** ppPSO, float* BlendFactors, Uint32& StencilRef); @@ -194,6 +183,10 @@ public: bool IsDeferred() const { return m_bIsDeferred; } + /// Checks if a texture is bound as a render target or depth-stencil buffer and + /// resets render targets if it is. + bool UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage); + protected: inline bool SetBlendFactors(const float* BlendFactors, int Dummy); @@ -210,10 +203,6 @@ protected: /// Checks if the texture is currently bound as depth-stencil buffer. bool CheckIfBoundAsDepthStencil(TextureImplType* pTexture); - /// Checks if the texture is bound as a render target or depth-stencil buffer and - /// resets render targets if it is. - bool UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage); - #ifdef DEVELOPMENT // clang-format off @@ -248,10 +237,6 @@ protected: /// Strong reference to the device. RefCntAutoPtr m_pDevice; - /// Strong reference to the swap chain. Swap chain holds - /// weak reference to the immediate context. - RefCntAutoPtr m_pSwapChain; - /// Vertex streams. Every stream holds strong reference to the buffer VertexStreamInfo m_VertexStreams[MaxBufferSlots]; @@ -298,9 +283,6 @@ protected: Uint32 m_FramebufferHeight = 0; /// Number of array slices in the currently bound framebuffer Uint32 m_FramebufferSlices = 0; - /// Flag indicating if default render target & depth-stencil - /// buffer are currently bound - bool m_IsDefaultFramebufferBound = false; /// Strong references to the bound depth stencil view. /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() @@ -411,7 +393,6 @@ template inline void DeviceContextBase::InvalidateState() { DeviceContextBase::ClearStateCache(); - m_IsDefaultFramebufferBound = false; } template @@ -541,33 +522,17 @@ template inline bool DeviceContextBase:: SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil) { + if (NumRenderTargets == 0 && pDepthStencil == nullptr) + { + ResetRenderTargets(); + return false; + } + bool bBindRenderTargets = false; m_FramebufferWidth = 0; m_FramebufferHeight = 0; m_FramebufferSlices = 0; - ITextureView* pDefaultRTV = nullptr; - bool IsDefaultFrambuffer = NumRenderTargets == 0 && pDepthStencil == nullptr; - bBindRenderTargets = (m_IsDefaultFramebufferBound != IsDefaultFrambuffer); - m_IsDefaultFramebufferBound = IsDefaultFrambuffer; - if (m_IsDefaultFramebufferBound) - { - VERIFY(m_pSwapChain, "Swap chain is not initialized in the device context"); - - pDefaultRTV = m_pSwapChain->GetCurrentBackBufferRTV(); - pDepthStencil = m_pSwapChain->GetDepthBufferDSV(); - if (pDefaultRTV != nullptr) - { - NumRenderTargets = 1; - ppRenderTargets = &pDefaultRTV; - } - - const auto& SwapChainDesc = m_pSwapChain->GetDesc(); - m_FramebufferWidth = SwapChainDesc.Width; - m_FramebufferHeight = SwapChainDesc.Height; - m_FramebufferSlices = 1; - } - if (NumRenderTargets != m_NumBoundRenderTargets) { bBindRenderTargets = true; @@ -764,29 +729,42 @@ bool DeviceContextBase::UnbindTextureFromFr if (pTexture == nullptr) return false; - if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_RENDER_TARGET) && !pTexture->CheckState(RESOURCE_STATE_DEPTH_WRITE)) - return false; + const auto& TexDesc = pTexture->GetDesc(); bool bResetRenderTargets = false; - if (CheckIfBoundAsRenderTarget(pTexture)) + if (TexDesc.BindFlags & BIND_RENDER_TARGET) { - if (bShowMessage) + if (CheckIfBoundAsRenderTarget(pTexture)) { - LOG_INFO_MESSAGE("Texture '", pTexture->GetDesc().Name, - "' is currently bound as render target and will be unset along with all " - "other render targets and depth-stencil buffer. " - "Call SetRenderTargets() to reset the render targets."); - } + if (bShowMessage) + { + LOG_INFO_MESSAGE("Texture '", TexDesc.Name, + "' is currently bound as render target and will be unset along with all " + "other render targets and depth-stencil buffer. " + "Call SetRenderTargets() to reset the render targets.\n" + "To silence this message, explicitly unbind the texture with " + "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); + } - bResetRenderTargets = true; + bResetRenderTargets = true; + } } - else if (CheckIfBoundAsDepthStencil(pTexture)) + + if (TexDesc.BindFlags & BIND_DEPTH_STENCIL) { - LOG_INFO_MESSAGE("Texture '", pTexture->GetDesc().Name, - "' is currently bound as depth buffer and will be unset along with " - "all render targets. Call SetRenderTargets() to reset the render targets."); + if (CheckIfBoundAsDepthStencil(pTexture)) + { + if (bShowMessage) + { + LOG_INFO_MESSAGE("Texture '", TexDesc.Name, + "' is currently bound as depth buffer and will be unset along with " + "all render targets. Call SetRenderTargets() to reset the render targets.\n" + "To silence this message, explicitly unbind the texture with " + "SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_NONE)"); + } - bResetRenderTargets = true; + bResetRenderTargets = true; + } } if (bResetRenderTargets) @@ -808,11 +786,10 @@ void DeviceContextBase::ResetRenderTargets( VERIFY(m_pBoundRenderTargets[rt] == nullptr, "Non-null render target found"); } #endif - m_NumBoundRenderTargets = 0; - m_FramebufferWidth = 0; - m_FramebufferHeight = 0; - m_FramebufferSlices = 0; - m_IsDefaultFramebufferBound = false; + m_NumBoundRenderTargets = 0; + m_FramebufferWidth = 0; + m_FramebufferHeight = 0; + m_FramebufferSlices = 0; m_pBoundDepthStencil.Release(); } @@ -1188,41 +1165,22 @@ inline void DeviceContextBase:: TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN}; TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN; - Uint32 NumBoundRTVs = 0; - if (m_IsDefaultFramebufferBound) + + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) { - if (m_pSwapChain) - { - BoundRTVFormats[0] = m_pSwapChain->GetDesc().ColorBufferFormat; - BoundDSVFormat = m_pSwapChain->GetDesc().DepthBufferFormat; - NumBoundRTVs = 1; - } + if (auto* pRT = m_pBoundRenderTargets[rt].RawPtr()) + BoundRTVFormats[rt] = pRT->GetDesc().Format; else - { - LOG_WARNING_MESSAGE("Failed to get bound render targets and depth-stencil buffer: " - "swap chain is not initialized in the device context"); - return; - } + BoundRTVFormats[rt] = TEX_FORMAT_UNKNOWN; } - else - { - NumBoundRTVs = m_NumBoundRenderTargets; - for (Uint32 rt = 0; rt < NumBoundRTVs; ++rt) - { - if (auto* pRT = m_pBoundRenderTargets[rt].RawPtr()) - BoundRTVFormats[rt] = pRT->GetDesc().Format; - else - BoundRTVFormats[rt] = TEX_FORMAT_UNKNOWN; - } - BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; - } + BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; const auto& PSODesc = m_pPipelineState->GetDesc(); const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; - if (GraphicsPipeline.NumRenderTargets != NumBoundRTVs) + if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) { - LOG_WARNING_MESSAGE("Number of currently bound render targets (", NumBoundRTVs, + LOG_WARNING_MESSAGE("Number of currently bound render targets (", m_NumBoundRenderTargets, ") does not match the number of outputs specified by the PSO '", PSODesc.Name, "' (", Uint32{GraphicsPipeline.NumRenderTargets}, ")."); } @@ -1234,7 +1192,7 @@ inline void DeviceContextBase:: "' (", GetTextureFormatAttribs(GraphicsPipeline.DSVFormat).Name, ")."); } - for (Uint32 rt = 0; rt < NumBoundRTVs; ++rt) + for (Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt) { auto BoundFmt = BoundRTVFormats[rt]; auto PSOFmt = GraphicsPipeline.RTVFormats[rt]; diff --git a/Graphics/GraphicsEngine/include/SwapChainBase.h b/Graphics/GraphicsEngine/include/SwapChainBase.h index 46766e65..1a4558f7 100644 --- a/Graphics/GraphicsEngine/include/SwapChainBase.h +++ b/Graphics/GraphicsEngine/include/SwapChainBase.h @@ -101,48 +101,6 @@ protected: return false; } - template - 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 pBoundRTVs = {}; - RefCntAutoPtr 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 RefCntAutoPtr m_pRenderDevice; diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 4f75eaaa..6fe95f42 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -26,7 +26,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240045 +#define DILIGENT_API_VERSION 240046 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 098b7402..9a9b9396 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -773,7 +773,7 @@ public: virtual void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32 RTWidth, Uint32 RTHeight) = 0; - /// Binds one or more render targets and the depth-stencil buffer to the pipeline. It also + /// Binds one or more render targets and the depth-stencil buffer to the context. It also /// sets the viewport to match the first non-null render target or depth-stencil buffer. /// \param [in] NumRenderTargets - Number of render targets to bind. @@ -789,10 +789,6 @@ public: /// and depth-stencil views. Thus these views (and consequently referenced textures) /// cannot be released until they are unbound from the context.\n /// Any render targets not defined by this call are set to nullptr.\n\n - /// You can set the default render target and depth stencil using the - /// following call: - /// - /// pContext->SetRenderTargets(0, nullptr, nullptr); /// /// \remarks When StateTransitionMode is Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION, the method will /// transition all render targets in known states to Diligent::RESOURCE_STATE_REDER_TARGET, @@ -1129,25 +1125,7 @@ public: /// The texture must be created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag. virtual void GenerateMips(ITextureView* pTextureView) = 0; - - /// Sets the swap chain in the device context. - - /// The swap chain is used by the device context to work with the - /// default framebuffer. Specifically, if the swap chain is set in the context, - /// the following commands can be used: - /// * SetRenderTargets(0, nullptr, nullptr) - to bind the default back buffer & depth buffer - /// * SetViewports(1, nullptr, 0, 0) - to set the viewport to match the size of the back buffer - /// * ClearRenderTarget(nullptr, color) - to clear the default back buffer - /// * ClearDepthStencil(nullptr, ...) - to clear the default depth buffer - /// The swap chain is automatically initialized for immediate and all deferred contexts - /// by factory functions EngineFactoryD3D11Impl::CreateSwapChainD3D11(), - /// EngineFactoryD3D12Impl::CreateSwapChainD3D12(), and EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL(). - /// However, when the engine is initialized by attaching to existing d3d11/d3d12 device or OpenGL/GLES context, the - /// swap chain needs to be set manually if the device context will be using any of the commands above.\n - /// Device context keeps strong reference to the swap chain. - virtual void SetSwapChain(ISwapChain* pSwapChain) = 0; - - + /// Finishes the current frame and releases dynamic resources allocated by the context. /// For immediate context, this method is called automatically by ISwapChain::Present() of the primary diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 6bff6a93..9dd2dd8c 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1236,10 +1236,8 @@ namespace Diligent /// Default stencil value, which is used as optimized stencil clear value in D3D12 Uint8 DefaultStencilValue = 0; - /// Indicates if this is a primary swap chain. The back buffer and depth-stencil - /// buffer of the primary swap are set by SetRenderTargets(0, nullptr, nullptr) - /// call. Also, when Present() is called for the primary swap chain, the engine - /// releases stale resources. There must only be one primary swap chain. + /// Indicates if this is a primary swap chain. When Present() is called + /// for the primary swap chain, the engine releases stale resources. bool IsPrimary = true; SwapChainDesc()noexcept{} diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index c3962a0a..676c6d73 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -32,7 +32,6 @@ #include "D3D11TypeConversions.h" #include "TextureViewD3D11Impl.h" #include "PipelineStateD3D11Impl.h" -#include "SwapChainD3D11.h" #include "ShaderResourceBindingD3D11Impl.h" #include "EngineD3D11Defines.h" #include "CommandListD3D11Impl.h" @@ -914,20 +913,12 @@ void DeviceContextD3D11Impl::ClearDepthStencil(ITextureView* pV { if (pView == nullptr) { - if (m_pSwapChain) + if (m_pBoundDepthStencil == nullptr) { - pView = m_pSwapChain->GetDepthBufferDSV(); - if (pView == nullptr) - { - LOG_WARNING_MESSAGE("Depth buffer is not initialized in the swap chain. Clear operation will be ignored."); - return; - } - } - else - { - LOG_ERROR("Failed to clear default depth stencil buffer: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearDepthStencil(nullptr, ...) is invalid because no depth-stencil buffer is currently bound."); return; } + pView = m_pBoundDepthStencil; } #ifdef DEVELOPMENT @@ -949,15 +940,14 @@ void DeviceContextD3D11Impl::ClearRenderTarget(ITextureView* pView, const float* { if (pView == nullptr) { - if (m_pSwapChain != nullptr) - { - pView = m_pSwapChain->GetCurrentBackBufferRTV(); - } - else + if (m_NumBoundRenderTargets != 1) { - LOG_ERROR("Failed to clear default render target: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearRenderTarget(nullptr, ...) semantic is only allowed when single render target is bound to the context. ", + m_NumBoundRenderTargets, " render ", + (m_NumBoundRenderTargets != 1 ? "targets are" : "target is"), " currently bound"); return; } + pView = m_pBoundRenderTargets[0]; } #ifdef DEVELOPMENT @@ -1294,45 +1284,21 @@ void DeviceContextD3D11Impl::CommitRenderTargets() ID3D11RenderTargetView* pd3d11RTs[MaxD3D11RTs]; ID3D11DepthStencilView* pd3d11DSV = nullptr; - if (m_IsDefaultFramebufferBound) + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) { - if (m_pSwapChain) - { - NumRenderTargets = 1; - auto* pSwapChainD3D11 = m_pSwapChain.RawPtr(); - auto* pBackBufferViewD3D11 = pSwapChainD3D11->GetCurrentBackBufferRTV(); - pd3d11RTs[0] = static_cast(pBackBufferViewD3D11->GetD3D11View()); - VERIFY_EXPR(pd3d11RTs[0] != nullptr); - if (auto* pDepthBufferViewD3D11 = pSwapChainD3D11->GetDepthBufferDSV()) - { - pd3d11DSV = static_cast(pDepthBufferViewD3D11->GetD3D11View()); - VERIFY_EXPR(pd3d11DSV != nullptr); - } - } - else - { - LOG_ERROR("Failed to commit default render target and depth stencil: swap chain is not initialized in the device context"); - return; - } + auto* pViewD3D11 = m_pBoundRenderTargets[rt].RawPtr(); + pd3d11RTs[rt] = pViewD3D11 != nullptr ? static_cast(pViewD3D11->GetD3D11View()) : nullptr; } - else - { - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) - { - auto* pViewD3D11 = m_pBoundRenderTargets[rt].RawPtr(); - pd3d11RTs[rt] = pViewD3D11 != nullptr ? static_cast(pViewD3D11->GetD3D11View()) : nullptr; - } - if (m_pBoundDepthStencil != nullptr) - { - pd3d11DSV = static_cast(m_pBoundDepthStencil->GetD3D11View()); - } + if (m_pBoundDepthStencil != nullptr) + { + pd3d11DSV = static_cast(m_pBoundDepthStencil->GetD3D11View()); } auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd]; if (NumCommittedPixelShaderUAVs > 0) { - m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRenderTargets, pd3d11RTs, pd3d11DSV, + m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV, 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr); auto CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd]; @@ -1347,7 +1313,7 @@ void DeviceContextD3D11Impl::CommitRenderTargets() } else { - m_pd3d11DeviceContext->OMSetRenderTargets(NumRenderTargets, pd3d11RTs, pd3d11DSV); + m_pd3d11DeviceContext->OMSetRenderTargets(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV); } } diff --git a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp index 161ab79c..bfc22eaa 100644 --- a/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp @@ -286,39 +286,8 @@ void EngineFactoryD3D11Impl::CreateSwapChainD3D11(IRenderDevice* pDev auto* pDeviceContextD3D11 = ValidatedCast(pImmediateContext); auto& RawMemAllocator = GetRawAllocator(); - if (pDeviceContextD3D11->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* pSwapChainD3D11 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D11Impl instance", SwapChainD3D11Impl)(SCDesc, FSDesc, pDeviceD3D11, pDeviceContextD3D11, pNativeWndHandle); pSwapChainD3D11->QueryInterface(IID_SwapChain, reinterpret_cast(ppSwapChain)); - - if (SCDesc.IsPrimary) - { - pDeviceContextD3D11->SetSwapChain(pSwapChainD3D11); - // Bind default render target - pDeviceContextD3D11->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - // Set default viewport - pDeviceContextD3D11->SetViewports(1, nullptr, 0, 0); - - auto NumDeferredCtx = pDeviceD3D11->GetNumDeferredContexts(); - for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) - { - if (auto pDeferredCtx = pDeviceD3D11->GetDeferredContext(ctx)) - { - auto* pDeferredCtxD3D11 = pDeferredCtx.RawPtr(); - pDeferredCtxD3D11->SetSwapChain(pSwapChainD3D11); - // Do not bind default render target and viewport to be - // consistent with D3D12 - //// Bind default render target - //pDeferredCtxD3D11->SetRenderTargets( 0, nullptr, nullptr ); - //// Set default viewport - //pDeferredCtxD3D11->SetViewports( 1, nullptr, 0, 0 ); - } - } - } } catch (const std::runtime_error&) { diff --git a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp index 003c70c4..305a0b93 100644 --- a/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/SwapChainD3D11Impl.cpp @@ -157,9 +157,14 @@ void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) VERIFY(pDeviceContext, "Immediate context has been released"); if (pDeviceContext) { - auto* pImmediateCtxD3D11 = pDeviceContext.RawPtr(); - ITextureView* pBackBufferRTVs[] = {m_pRenderTargetView}; - bool RebindRenderTargets = UnbindRenderTargets(pImmediateCtxD3D11, pBackBufferRTVs, 1, m_pDepthStencilView); + auto* pImmediateCtxD3D11 = pDeviceContext.RawPtr(); + auto* pCurrentBackBuffer = ValidatedCast(m_pRenderTargetView->GetTexture()); + auto RenderTargetsReset = pImmediateCtxD3D11->UnbindTextureFromFramebuffer(pCurrentBackBuffer, false); + if (RenderTargetsReset) + { + LOG_INFO_MESSAGE_ONCE("Resizing the swap chain requires back and depth-stencil buffers to be unbound from the device context. " + "An application should use SetRenderTargets() to restore them."); + } // Swap chain cannot be resized until all references are released m_pRenderTargetView.Release(); @@ -197,13 +202,6 @@ void SwapChainD3D11Impl::UpdateSwapChain(bool CreateNew) } CreateRTVandDSV(); - - if (m_SwapChainDesc.IsPrimary && RebindRenderTargets) - { - // 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/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 5d35eb82..73238d21 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -25,7 +25,6 @@ #include #include "RenderDeviceD3D12Impl.h" #include "DeviceContextD3D12Impl.h" -#include "SwapChainD3D12.h" #include "PipelineStateD3D12Impl.h" #include "CommandContext.h" #include "TextureD3D12Impl.h" @@ -618,20 +617,12 @@ void DeviceContextD3D12Impl::ClearDepthStencil(ITextureView* pV } else { - if (m_pSwapChain) + if (m_pBoundDepthStencil == nullptr) { - pViewD3D12 = ValidatedCast(m_pSwapChain.RawPtr()->GetDepthBufferDSV()); - if (pViewD3D12 == nullptr) - { - LOG_WARNING_MESSAGE("Depth buffer is not initialized in the swap chain. Clear operation will be ignored."); - return; - } - } - else - { - LOG_ERROR("Failed to clear default depth stencil buffer: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearDepthStencil(nullptr, ...) is invalid because no depth-stencil buffer is currently bound."); return; } + pViewD3D12 = m_pBoundDepthStencil; } auto* pTextureD3D12 = ValidatedCast(pViewD3D12->GetTexture()); @@ -661,15 +652,14 @@ void DeviceContextD3D12Impl::ClearRenderTarget(ITextureView* pView, const float* } else { - if (m_pSwapChain) + if (m_NumBoundRenderTargets != 1) { - pViewD3D12 = ValidatedCast(m_pSwapChain.RawPtr()->GetCurrentBackBufferRTV()); - } - else - { - LOG_ERROR("Failed to clear default render target: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearRenderTarget(nullptr, ...) semantic is only allowed when single render target is bound to the context. ", + m_NumBoundRenderTargets, " render ", + (m_NumBoundRenderTargets != 1 ? "targets are" : "target is"), " currently bound"); return; } + pViewD3D12 = m_pBoundRenderTargets[0]; } static constexpr float Zero[4] = {0.f, 0.f, 0.f, 0.f}; @@ -930,27 +920,10 @@ void DeviceContextD3D12Impl::CommitRenderTargets(RESOURCE_STATE_TRANSITION_MODE ITextureViewD3D12* ppRTVs[MaxD3D12RTs]; // Do not initialize with zeroes! ITextureViewD3D12* pDSV = nullptr; - if (m_IsDefaultFramebufferBound) - { - if (m_pSwapChain) - { - NumRenderTargets = 1; - auto* pSwapChainD3D12 = m_pSwapChain.RawPtr(); - ppRTVs[0] = ValidatedCast(pSwapChainD3D12->GetCurrentBackBufferRTV()); - pDSV = ValidatedCast(pSwapChainD3D12->GetDepthBufferDSV()); - } - else - { - LOG_WARNING_MESSAGE("Failed to bind default render targets and depth-stencil buffer: swap chain is not initialized in the device context"); - return; - } - } - else - { - for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) - ppRTVs[rt] = m_pBoundRenderTargets[rt].RawPtr(); - pDSV = m_pBoundDepthStencil.RawPtr(); - } + + for (Uint32 rt = 0; rt < NumRenderTargets; ++rt) + ppRTVs[rt] = m_pBoundRenderTargets[rt].RawPtr(); + pDSV = m_pBoundDepthStencil.RawPtr(); auto& CmdCtx = GetCmdContext(); diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp index 0526f672..28c62a1c 100644 --- a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp @@ -391,37 +391,8 @@ void EngineFactoryD3D12Impl::CreateSwapChainD3D12(IRenderDevice* pDev auto* pDeviceContextD3D12 = ValidatedCast(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(ppSwapChain)); - - if (SCDesc.IsPrimary) - { - 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 (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx)) - { - auto* pDeferredCtxD3D12 = pDeferredCtx.RawPtr(); - 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 - } - } - } } catch (const std::runtime_error&) { diff --git a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp index fe9d135f..74cedd1c 100644 --- a/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/SwapChainD3D12Impl.cpp @@ -177,11 +177,18 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) try { auto* pImmediateCtxD3D12 = pDeviceContext.RawPtr(); + bool RenderTargetsReset = false; + for (Uint32 i = 0; i < m_pBackBufferRTV.size() && !RenderTargetsReset; ++i) + { + auto* pCurrentBackBuffer = ValidatedCast(m_pBackBufferRTV[i]->GetTexture()); + RenderTargetsReset = pImmediateCtxD3D12->UnbindTextureFromFramebuffer(pCurrentBackBuffer, false); + } - std::vector 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(m_pBackBufferRTV.size()), m_pDepthBufferDSV); + if (RenderTargetsReset) + { + LOG_INFO_MESSAGE_ONCE("Resizing the swap chain requires back and depth-stencil buffers to be unbound from the device context. " + "An application should use SetRenderTargets() to restore them."); + } // All references to the swap chain must be released before it can be resized m_pBackBufferRTV.clear(); @@ -196,9 +203,11 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) m_pSwapChain.Release(); m_pRenderDevice.RawPtr()->LockCmdQueueAndRun( 0, - [this](ICommandQueueD3D12* pCmdQueue) { + [this](ICommandQueueD3D12* pCmdQueue) // + { CreateDXGISwapChain(pCmdQueue->GetD3D12CommandQueue()); - }); + } // + ); } else { @@ -212,13 +221,6 @@ void SwapChainD3D12Impl::UpdateSwapChain(bool CreateNew) } InitBuffersAndViews(); - - if (m_SwapChainDesc.IsPrimary && RebindRenderTargets) - { - // Set default render target and viewport - pDeviceContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pDeviceContext->SetViewports(1, nullptr, 0, 0); - } } catch (const std::runtime_error&) { diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h index 899c6d68..38c982ca 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.h @@ -36,6 +36,7 @@ namespace Diligent { class RenderDeviceGLImpl; +class ISwapChainGL; struct DeviceContextGLImplTraits { @@ -212,6 +213,11 @@ public: void CommitRenderTargets(); + void SetSwapChain(ISwapChainGL* pSwapChain); + + virtual void ResetRenderTargets() override final; + + protected: friend class BufferGLImpl; friend class TextureBaseGL; @@ -230,6 +236,10 @@ private: std::vector m_BoundWritableTextures; std::vector m_BoundWritableBuffers; + RefCntAutoPtr m_pSwapChain; + + bool m_IsDefaultFBOBound = false; + GLObjectWrappers::GLFrameBufferObj m_DefaultFBO; }; diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index 746701f2..7b8624a2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -194,6 +194,7 @@ void DeviceContextGLImpl::InvalidateState() m_ContextState.Invalidate(); m_BoundWritableTextures.clear(); m_BoundWritableBuffers.clear(); + m_IsDefaultFBOBound = false; } void DeviceContextGLImpl::SetIndexBuffer(IBuffer* pIndexBuffer, Uint32 ByteOffset, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) @@ -307,15 +308,19 @@ void DeviceContextGLImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U } } +void DeviceContextGLImpl::SetSwapChain(ISwapChainGL* pSwapChain) +{ + m_pSwapChain = pSwapChain; +} + void DeviceContextGLImpl::CommitRenderTargets() { - if (!m_IsDefaultFramebufferBound && m_NumBoundRenderTargets == 0 && !m_pBoundDepthStencil) + if (!m_IsDefaultFBOBound && m_NumBoundRenderTargets == 0 && !m_pBoundDepthStencil) return; - if (m_IsDefaultFramebufferBound) + if (m_IsDefaultFBOBound) { - auto* pSwapChainGL = m_pSwapChain.RawPtr(); - GLuint DefaultFBOHandle = pSwapChainGL->GetDefaultFBO(); + GLuint DefaultFBOHandle = m_pSwapChain->GetDefaultFBO(); if (m_DefaultFBO != DefaultFBOHandle) { m_DefaultFBO = GLObjectWrappers::GLFrameBufferObj(true, GLObjectWrappers::GLFBOCreateReleaseHelper(DefaultFBOHandle)); @@ -366,26 +371,34 @@ void DeviceContextGLImpl::SetRenderTargets(Uint32 NumRen { if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil)) { - if (!m_IsDefaultFramebufferBound) + if (m_NumBoundRenderTargets == 1 && m_pBoundRenderTargets[0] && m_pBoundRenderTargets[0]->GetTexture()->GetGLHandle() == 0) { - if (m_NumBoundRenderTargets == 1 && m_pBoundRenderTargets[0] && m_pBoundRenderTargets[0]->GetTexture()->GetGLHandle() == 0) - { - DEV_CHECK_ERR(!m_pBoundDepthStencil || m_pBoundDepthStencil->GetTexture()->GetGLHandle() == 0, - "Attempting to bind texture '", m_pBoundDepthStencil->GetTexture()->GetDesc().Name, - "' as depth buffer with the default framebuffer's color buffer: color buffer of the default framebuffer " - "can only be bound with the default framebuffer's depth buffer and cannot be combined with any other depth buffer in OpenGL backend."); - m_IsDefaultFramebufferBound = true; - } - else if (m_NumBoundRenderTargets == 0 && m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture()->GetGLHandle() == 0) - { - m_IsDefaultFramebufferBound = true; - } + DEV_CHECK_ERR(!m_pBoundDepthStencil || m_pBoundDepthStencil->GetTexture()->GetGLHandle() == 0, + "Attempting to bind texture '", m_pBoundDepthStencil->GetTexture()->GetDesc().Name, + "' as depth buffer with the default framebuffer's color buffer: color buffer of the default framebuffer " + "can only be bound with the default framebuffer's depth buffer and cannot be combined with any other depth buffer in OpenGL backend."); + m_IsDefaultFBOBound = true; + } + else if (m_NumBoundRenderTargets == 0 && m_pBoundDepthStencil && m_pBoundDepthStencil->GetTexture()->GetGLHandle() == 0) + { + m_IsDefaultFBOBound = true; + } + else + { + m_IsDefaultFBOBound = false; } CommitRenderTargets(); } } +void DeviceContextGLImpl::ResetRenderTargets() +{ + TDeviceContextBase::ResetRenderTargets(); + m_IsDefaultFBOBound = false; +} + + void DeviceContextGLImpl::BindProgramResources(Uint32& NewMemoryBarriers, IShaderResourceBinding* pResBinding) { if (!m_pPipelineState) @@ -925,10 +938,10 @@ void DeviceContextGLImpl::ClearDepthStencil(ITextureView* pView } else { - if (!m_IsDefaultFramebufferBound) + if (!m_pBoundDepthStencil) { - UNEXPECTED("Default depth stencil buffer being cleared is not bound to the pipeline"); - LOG_ERROR_MESSAGE("Default depth stencil buffer must be bound to the pipeline to be cleared"); + LOG_ERROR_MESSAGE("ClearDepthStencil(nullptr, ...) is invalid because no depth-stencil buffer is currently bound."); + return; } } Uint32 glClearFlags = 0; @@ -978,12 +991,13 @@ void DeviceContextGLImpl::ClearRenderTarget(ITextureView* pView, const float* RG } else { - if (m_IsDefaultFramebufferBound) + if (m_NumBoundRenderTargets == 1) RTIndex = 0; else { - UNEXPECTED("Default render target must be bound to the pipeline to be cleared"); - LOG_ERROR_MESSAGE("Default render target must be bound to the pipeline to be cleared"); + LOG_ERROR_MESSAGE("ClearRenderTarget(nullptr, ...) semantic is only allowed when single render target is bound to the context. ", + m_NumBoundRenderTargets, " render ", + (m_NumBoundRenderTargets != 1 ? "targets are" : "target is"), " currently bound"); } } diff --git a/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp b/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp index 14fbd670..1300ad68 100644 --- a/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/EngineFactoryOpenGL.cpp @@ -149,9 +149,6 @@ void EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL(const EngineGLCreateInf pSwapChainGL->QueryInterface(IID_SwapChain, reinterpret_cast(ppSwapChain)); pDeviceContextOpenGL->SetSwapChain(pSwapChainGL); - // Bind default framebuffer and viewport - pDeviceContextOpenGL->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pDeviceContextOpenGL->SetViewports(1, nullptr, 0, 0); } catch (const std::runtime_error&) { diff --git a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp index c47b8812..831fdb7e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/SwapChainGLImpl.cpp @@ -132,15 +132,14 @@ void SwapChainGLImpl::Resize(Uint32 NewWidth, Uint32 NewHeight) VERIFY(pDeviceContext, "Immediate context has been released"); if (pDeviceContext) { - auto* pImmediateCtxGL = pDeviceContext.RawPtr(); - bool bIsDefaultFBBound = pImmediateCtxGL->IsDefaultFBBound(); - - // To update the viewport is the only thing we need to do in OpenGL - if (bIsDefaultFBBound) + auto* pImmediateCtxGL = pDeviceContext.RawPtr(); + // Unbind the back buffer to be consistent with other backends + auto* pCurrentBackBuffer = ValidatedCast(m_pRenderTargetView->GetTexture()); + auto RenderTargetsReset = pImmediateCtxGL->UnbindTextureFromFramebuffer(pCurrentBackBuffer, false); + if (RenderTargetsReset) { - // Update framebuffer size and viewport - pImmediateCtxGL->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pImmediateCtxGL->SetViewports(1, nullptr, 0, 0); + LOG_INFO_MESSAGE_ONCE("Resizing the swap chain requires back and depth-stencil buffers to be unbound from the device context. " + "An application should use SetRenderTargets() to restore them."); } } } diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 6122ffda..a508b4e9 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -25,7 +25,6 @@ #include #include "RenderDeviceVkImpl.h" #include "DeviceContextVkImpl.h" -#include "SwapChainVk.h" #include "PipelineStateVkImpl.h" #include "TextureVkImpl.h" #include "BufferVkImpl.h" @@ -625,20 +624,12 @@ void DeviceContextVkImpl::ClearDepthStencil(ITextureView* pView } else { - if (m_pSwapChain) + if (m_pBoundDepthStencil == nullptr) { - pVkDSV = ValidatedCast(m_pSwapChain->GetDepthBufferDSV()); - if (pVkDSV == nullptr) - { - LOG_WARNING_MESSAGE("Depth buffer is not initialized in the swap chain. Clear operation will be ignored."); - return; - } - } - else - { - LOG_ERROR("Failed to clear default depth stencil buffer: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearDepthStencil(nullptr, ...) is invalid because no depth-stencil buffer is currently bound."); return; } + pVkDSV = m_pBoundDepthStencil; } EnsureVkCmdBuffer(); @@ -745,15 +736,14 @@ void DeviceContextVkImpl::ClearRenderTarget(ITextureView* pView, const float* RG } else { - if (m_pSwapChain) - { - pVkRTV = ValidatedCast(m_pSwapChain->GetCurrentBackBufferRTV()); - } - else + if (m_NumBoundRenderTargets != 1) { - LOG_ERROR("Failed to clear default render target: swap chain is not initialized in the device context"); + LOG_ERROR_MESSAGE("ClearRenderTarget(nullptr, ...) semantic is only allowed when single render target is bound to the context. ", + m_NumBoundRenderTargets, " render ", + (m_NumBoundRenderTargets != 1 ? "targets are" : "target is"), " currently bound"); return; } + pVkRTV = m_pBoundRenderTargets[0]; } static constexpr float Zero[4] = {0.f, 0.f, 0.f, 0.f}; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 18be491e..54c387c7 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -337,38 +337,8 @@ void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice, auto* pDeviceContextVk = ValidatedCast(pImmediateContext); auto& RawMemAllocator = GetRawAllocator(); - if (pDeviceContextVk->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* pSwapChainVk = NEW_RC_OBJ(RawMemAllocator, "SwapChainVkImpl instance", SwapChainVkImpl)(SCDesc, pDeviceVk, pDeviceContextVk, pNativeWndHandle); pSwapChainVk->QueryInterface(IID_SwapChain, reinterpret_cast(ppSwapChain)); - - if (SCDesc.IsPrimary) - { - pDeviceContextVk->SetSwapChain(pSwapChainVk); - // Bind default render target - pDeviceContextVk->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - // Set default viewport - pDeviceContextVk->SetViewports(1, nullptr, 0, 0); - - auto NumDeferredCtx = pDeviceVk->GetNumDeferredContexts(); - for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) - { - if (auto pDeferredCtx = pDeviceVk->GetDeferredContext(ctx)) - { - auto* pDeferredCtxVk = pDeferredCtx.RawPtr(); - pDeferredCtxVk->SetSwapChain(pSwapChainVk); - // 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 - } - } - } } catch (const std::runtime_error&) { diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp index 09905e5f..98be4ccb 100644 --- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp @@ -547,8 +547,6 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) } pImmediateCtxVk->Flush(); - // If present fails, default FB will be undbound by RecreateVulkanSwapchain(), so we need to check it now - bool IsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound(); if (!m_IsMinimized) { @@ -605,13 +603,6 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval) res = AcquireNextImage(pImmediateCtxVk); } DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next swap chain image"); - - if (m_SwapChainDesc.IsPrimary && IsDefaultFBBound) - { - // If default framebuffer is bound, we need to call SetRenderTargets() - // to bind new back buffer RTV - pImmediateCtxVk->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - } } } @@ -631,10 +622,17 @@ void SwapChainVkImpl::WaitForImageAcquiredFences() void SwapChainVkImpl::RecreateVulkanSwapchain(DeviceContextVkImpl* pImmediateCtxVk) { - std::vector pBackBufferRTVs(m_pBackBufferRTV.size()); - for (size_t i = 0; i < m_pBackBufferRTV.size(); ++i) - pBackBufferRTVs[i] = m_pBackBufferRTV[i]; - UnbindRenderTargets(pImmediateCtxVk, pBackBufferRTVs.data(), static_cast(m_pBackBufferRTV.size()), m_pDepthBufferDSV); + bool RenderTargetsReset = false; + for (Uint32 i = 0; i < m_pBackBufferRTV.size() && !RenderTargetsReset; ++i) + { + auto* pCurrentBackBuffer = ValidatedCast(m_pBackBufferRTV[i]->GetTexture()); + RenderTargetsReset = pImmediateCtxVk->UnbindTextureFromFramebuffer(pCurrentBackBuffer, false); + } + if (RenderTargetsReset) + { + LOG_INFO_MESSAGE_ONCE("Resizing the swap chain requires back and depth-stencil buffers to be unbound from the device context. " + "An application should use SetRenderTargets() to restore them."); + } RenderDeviceVkImpl* pDeviceVk = m_pRenderDevice.RawPtr(); @@ -678,19 +676,11 @@ void SwapChainVkImpl::Resize(Uint32 NewWidth, Uint32 NewHeight) { auto* pImmediateCtxVk = pDeviceContext.RawPtr(); // RecreateVulkanSwapchain() unbinds default FB - bool bIsDefaultFBBound = pImmediateCtxVk->IsDefaultFBBound(); RecreateVulkanSwapchain(pImmediateCtxVk); auto res = AcquireNextImage(pImmediateCtxVk); DEV_CHECK_ERR(res == VK_SUCCESS, "Failed to acquire next image for the just resized swap chain"); (void)res; - - if (m_SwapChainDesc.IsPrimary && bIsDefaultFBBound) - { - // Set default render target and viewport - pDeviceContext->SetRenderTargets(0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION); - pDeviceContext->SetViewports(1, nullptr, 0, 0); - } } catch (const std::runtime_error&) { -- cgit v1.2.3