diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-08 23:48:40 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-08 23:48:40 +0000 |
| commit | fd6ecbc3e52569119c4e0ff30236bd23f2757737 (patch) | |
| tree | 1cc09a201840841ecd4bb579dcd23e815fa7bc74 /Graphics | |
| parent | D3D12 backend: implemented render pass attachment state transitons (diff) | |
| download | DiligentCore-fd6ecbc3e52569119c4e0ff30236bd23f2757737.tar.gz DiligentCore-fd6ecbc3e52569119c4e0ff30236bd23f2757737.zip | |
Implemented unified render pass attachment state updates within subpasses and after the render pass ends
Diffstat (limited to 'Graphics')
13 files changed, 84 insertions, 71 deletions
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index a340bbd2..e5d9b90e 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -126,7 +126,7 @@ public: virtual void DILIGENT_CALL_TYPE NextSubpass() override = 0; - virtual void DILIGENT_CALL_TYPE EndRenderPass(bool UpdateResourceStates) override = 0; + virtual void DILIGENT_CALL_TYPE EndRenderPass() override = 0; /// Base implementation of IDeviceContext::UpdateBuffer(); validates input parameters. virtual void DILIGENT_CALL_TYPE UpdateBuffer(IBuffer* pBuffer, @@ -228,6 +228,9 @@ protected: /// Checks if the texture is currently bound as depth-stencil buffer. bool CheckIfBoundAsDepthStencil(TextureImplType* pTexture); + /// Updates the states of render pass attachments to match states within the gievn subpass + void UpdateAttachmentStates(Uint32 SubpassIndex); + bool ClearDepthStencil(ITextureView* pView); bool ClearRenderTarget(ITextureView* pView); @@ -329,6 +332,9 @@ protected: /// Current subpass index. Uint32 m_SubpassIndex = 0; + /// Render pass attachments transition mode. + RESOURCE_STATE_TRANSITION_MODE m_RenderPassAttachmentsTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE; + const bool m_bIsDeferred = false; #ifdef DILIGENT_DEBUG @@ -970,9 +976,11 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::BeginRenderP } } - m_pActiveRenderPass = pNewRenderPass; - m_pBoundFramebuffer = pNewFramebuffer; - m_SubpassIndex = 0; + m_pActiveRenderPass = pNewRenderPass; + m_pBoundFramebuffer = pNewFramebuffer; + m_SubpassIndex = 0; + m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode; + UpdateAttachmentStates(m_SubpassIndex); SetSubpassRenderTargets(); } @@ -982,36 +990,54 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::NextSubpass( VERIFY(m_pActiveRenderPass != nullptr, "There is no active render pass"); VERIFY(m_SubpassIndex + 1 < m_pActiveRenderPass->GetDesc().SubpassCount, "The render pass has reached the final subpass already"); ++m_SubpassIndex; + UpdateAttachmentStates(m_SubpassIndex); SetSubpassRenderTargets(); } template <typename BaseInterface, typename ImplementationTraits> -inline void DeviceContextBase<BaseInterface, ImplementationTraits>::EndRenderPass(bool UpdateResourceStates) +inline void DeviceContextBase<BaseInterface, ImplementationTraits>::UpdateAttachmentStates(Uint32 SubpassIndex) { - VERIFY(m_pActiveRenderPass != nullptr, "There is no active render pass"); - VERIFY(m_pBoundFramebuffer != nullptr, "There is no active framebuffer"); - VERIFY(m_pActiveRenderPass->GetDesc().SubpassCount == m_SubpassIndex + 1, - "Ending render pass at subpass ", m_SubpassIndex, " before reaching the final subpass"); + if (m_RenderPassAttachmentsTransitionMode != RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + return; + + VERIFY_EXPR(m_pActiveRenderPass != nullptr); + VERIFY_EXPR(m_pBoundFramebuffer != nullptr); - if (UpdateResourceStates) + const auto& RPDesc = m_pActiveRenderPass->GetDesc(); + const auto& FBDesc = m_pBoundFramebuffer->GetDesc(); + VERIFY(FBDesc.AttachmentCount == RPDesc.AttachmentCount, + "Framebuffer attachment count (", FBDesc.AttachmentCount, ") is not consistent with the render pass attachment count (", RPDesc.AttachmentCount, ")"); + VERIFY_EXPR(SubpassIndex <= RPDesc.SubpassCount); + for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) { - const auto& RPDesc = m_pActiveRenderPass->GetDesc(); - const auto& FBDesc = m_pBoundFramebuffer->GetDesc(); - VERIFY(FBDesc.AttachmentCount >= RPDesc.AttachmentCount, - "Framebuffer attachment count (", FBDesc.AttachmentCount, ") is smaller than the render pass attachment count (", RPDesc.AttachmentCount, ")"); - for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) + if (auto* pView = FBDesc.ppAttachments[i]) { - if (auto* pView = FBDesc.ppAttachments[i]) + auto* pTex = ValidatedCast<TextureImplType>(pView->GetTexture()); + if (pTex->IsInKnownState()) { - auto* pTex = ValidatedCast<TextureImplType>(pView->GetTexture()); - if (pTex->IsInKnownState()) - pTex->SetState(RPDesc.pAttachments[i].FinalState); + auto CurrState = SubpassIndex < RPDesc.SubpassCount ? + m_pActiveRenderPass->GetAttachmentState(SubpassIndex, i) : + RPDesc.pAttachments[i].FinalState; + pTex->SetState(CurrState); } } } +} + +template <typename BaseInterface, typename ImplementationTraits> +inline void DeviceContextBase<BaseInterface, ImplementationTraits>::EndRenderPass() +{ + VERIFY(m_pActiveRenderPass != nullptr, "There is no active render pass"); + VERIFY(m_pBoundFramebuffer != nullptr, "There is no active framebuffer"); + VERIFY(m_pActiveRenderPass->GetDesc().SubpassCount == m_SubpassIndex + 1, + "Ending render pass at subpass ", m_SubpassIndex, " before reaching the final subpass"); + + UpdateAttachmentStates(m_SubpassIndex + 1); + m_pActiveRenderPass.Release(); m_pBoundFramebuffer.Release(); - m_SubpassIndex = 0; + m_SubpassIndex = 0; + m_RenderPassAttachmentsTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE; ResetRenderTargets(); } diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp index fd0256b6..1805f7d3 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.hpp +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -184,6 +184,12 @@ public: return (this->m_State & State) == State; } + bool CheckAnyState(RESOURCE_STATE States) const + { + VERIFY(IsInKnownState(), "Texture state is unknown"); + return (this->m_State & States) != 0; + } + /// Implementation of ITexture::GetDefaultView(). virtual ITextureView* DILIGENT_CALL_TYPE GetDefaultView(TEXTURE_VIEW_TYPE ViewType) override { diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 3445a8d6..eb77ba8e 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -633,7 +633,18 @@ struct BeginRenderPassAttribs /// Other elements of pClearValues are ignored. OptimizedClearValue* pClearValues DEFAULT_INITIALIZER(nullptr); - /// Framebuffer attachments state transition mode. + /// Framebuffer attachments state transition mode before the render pass begins. + + /// This parameter also indicates how attachment states should be handled when + /// transitioning between subpasses as well as after the render pass ends. + /// When RESOURCE_STATE_TRANSITION_MODE_TRANSITION is used, attachment states will be + /// updated so that they match the state in the current subpass as well as the final states + /// specified by the render pass when the pass ends. + /// Note that resources are always transitioned. The flag only indicates if the internal + /// state variables should be updated. + /// When RESOURCE_STATE_TRANSITION_MODE_NONE or RESOURCE_STATE_TRANSITION_MODE_VERIFY is used, + /// internal state variables are not updated and it is the application responsibility to set them + /// manually to match the actual states. RESOURCE_STATE_TRANSITION_MODE StateTransitionMode DEFAULT_INITIALIZER(RESOURCE_STATE_TRANSITION_MODE_NONE); }; typedef struct BeginRenderPassAttribs BeginRenderPassAttribs; @@ -905,14 +916,7 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) /// Ends current render pass. - - /// \param [in] UpdateResourceStates - Indicates whether to update resource states so that they match - /// the final states specified by the render pass attachments. - /// Note that resources are always transitioned to the final states. - /// The flag only indicates if the internal state variables should be - /// updated to match the actual final states. - VIRTUAL void METHOD(EndRenderPass)(THIS_ - bool UpdateResourceStates) PURE; + VIRTUAL void METHOD(EndRenderPass)(THIS) PURE; /// Executes a draw command. diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 4df12602..6da56a4f 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -131,7 +131,7 @@ public: virtual void DILIGENT_CALL_TYPE NextSubpass() override final; /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE EndRenderPass(bool UpdateResourceStates) override final; + virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; /// Implementation of IDeviceContext::Draw() in Direct3D11 backend. virtual void DILIGENT_CALL_TYPE Draw(const DrawAttribs& Attribs) override final; @@ -390,8 +390,6 @@ private: /// Strong references to committed D3D11 shaders CComPtr<ID3D11DeviceChild> m_CommittedD3DShaders[NumShaderTypes]; - RESOURCE_STATE_TRANSITION_MODE m_RenderPassAttachmentsTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE; - const Uint32 m_DebugFlags; FixedBlockMemoryAllocator m_CmdListAllocator; diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index a40aa77a..748723f5 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -261,7 +261,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* {
if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
{
- if (pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ if (pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT))
UnbindTextureFromInput(pTexture, UAVRes.pd3d11Resource);
pTexture->SetState(RESOURCE_STATE_UNORDERED_ACCESS);
}
@@ -482,7 +482,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* {
if (auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
{
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ if (pTexture->IsInKnownState() && !pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT))
{
if (pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS))
{
@@ -521,7 +521,8 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* VERIFY_EXPR(CommitResources);
if (const auto* pTexture = ValidatedCast<TextureBaseD3D11>(SRVRes.pTexture))
{
- if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE))
+ if (pTexture->IsInKnownState() &&
+ !(pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE) || m_pActiveRenderPass != nullptr && pTexture->CheckState(RESOURCE_STATE_INPUT_ATTACHMENT)))
{
LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state.");
}
@@ -1677,8 +1678,6 @@ void DeviceContextD3D11Impl::BeginRenderPass(const BeginRenderPassAttribs& Attri TDeviceContextBase::BeginRenderPass(Attribs);
// BeginRenderPass() transitions resources to required states
- m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode;
-
CommitRenderTargets();
// Set the viewport to match the framebuffer size
@@ -1761,33 +1760,13 @@ void DeviceContextD3D11Impl::NextSubpass() TDeviceContextBase::NextSubpass();
- if (m_RenderPassAttachmentsTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
- {
- for (Uint32 att = 0; att < RPDesc.AttachmentCount; ++att)
- {
- auto* pTexView = ValidatedCast<TextureViewD3D11Impl>(FBDesc.ppAttachments[att]);
- if (pTexView == nullptr)
- continue;
-
- auto* pTex = ValidatedCast<TextureBaseD3D11>(pTexView->GetTexture());
- if (pTex->IsInKnownState())
- {
- auto CurrState = m_pActiveRenderPass->GetAttachmentState(m_SubpassIndex, att);
- if ((CurrState & RESOURCE_STATE_INPUT_ATTACHMENT) != 0)
- CurrState |= RESOURCE_STATE_SHADER_RESOURCE;
- pTex->SetState(CurrState);
- }
- }
- }
-
CommitRenderTargets();
}
-void DeviceContextD3D11Impl::EndRenderPass(bool UpdateResourceStates)
+void DeviceContextD3D11Impl::EndRenderPass()
{
EndSubpass();
- TDeviceContextBase::EndRenderPass(UpdateResourceStates);
- m_RenderPassAttachmentsTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE;
+ TDeviceContextBase::EndRenderPass();
}
diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp index dddf159e..09d9419b 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.hpp @@ -132,7 +132,7 @@ public: virtual void DILIGENT_CALL_TYPE NextSubpass() override final; /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE EndRenderPass(bool UpdateResourceStates) override final; + virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off /// Implementation of IDeviceContext::Draw() in Direct3D12 backend. diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 25c0bba9..32f03319 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -1238,12 +1238,12 @@ void DeviceContextD3D12Impl::NextSubpass() CommitSubpassRenderTargets(); } -void DeviceContextD3D12Impl::EndRenderPass(bool UpdateResourceStates) +void DeviceContextD3D12Impl::EndRenderPass() { auto& CmdCtx = GetCmdContext(); CmdCtx.AsGraphicsContext().EndRenderPass(); TransitionSubpassAttachments(m_SubpassIndex + 1); - TDeviceContextBase::EndRenderPass(UpdateResourceStates); + TDeviceContextBase::EndRenderPass(); } D3D12DynamicAllocation DeviceContextD3D12Impl::AllocateDynamicSpace(size_t NumBytes, size_t Alignment) diff --git a/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h b/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h index b5a7feec..0bfff2b3 100644 --- a/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h +++ b/Graphics/GraphicsEngineMetal/include/DeviceContextMtlImpl.h @@ -100,7 +100,7 @@ public: virtual void NextSubpass() override final; - virtual void EndRenderPass(bool UpdateResourceStates) override final; + virtual void EndRenderPass() override final; virtual void Draw(const DrawAttribs& Attribs) override final; virtual void DrawIndexed(const DrawIndexedAttribs& Attribs) override final; diff --git a/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm b/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm index ff08c1bb..abfa15ba 100644 --- a/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm +++ b/Graphics/GraphicsEngineMetal/src/DeviceContextMtlImpl.mm @@ -383,9 +383,9 @@ namespace Diligent LOG_ERROR_MESSAGE("DeviceContextMtlImpl::NextSubpass() is not implemented"); } - void DeviceContextMtlImpl::EndRenderPass(bool UpdateResourceStates) + void DeviceContextMtlImpl::EndRenderPass() { - TDeviceContextBase::EndRenderPass(UpdateResourceStates); + TDeviceContextBase::EndRenderPass(); LOG_ERROR_MESSAGE("DeviceContextMtlImpl::EndRenderPass() is not implemented"); } diff --git a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp index 52b3481b..ad9ff03b 100644 --- a/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/DeviceContextGLImpl.hpp @@ -121,7 +121,7 @@ public: virtual void DILIGENT_CALL_TYPE NextSubpass() override final; /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE EndRenderPass(bool UpdateResourceStates) override final; + virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index c06c7d3e..478be058 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -428,9 +428,9 @@ void DeviceContextGLImpl::NextSubpass() UNEXPECTED("Method not implemented"); } -void DeviceContextGLImpl::EndRenderPass(bool UpdateResourceStates) +void DeviceContextGLImpl::EndRenderPass() { - TDeviceContextBase::EndRenderPass(UpdateResourceStates); + TDeviceContextBase::EndRenderPass(); UNEXPECTED("Method not implemented"); } diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index a0249ec9..ebca0282 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -142,7 +142,7 @@ public: virtual void DILIGENT_CALL_TYPE NextSubpass() override final; /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE EndRenderPass(bool UpdateResourceStates) override final; + virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off /// Implementation of IDeviceContext::Draw() in Vulkan backend. diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index cc72fbb2..2310109f 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -1307,9 +1307,9 @@ void DeviceContextVkImpl::NextSubpass() m_CommandBuffer.NextSubpass(); } -void DeviceContextVkImpl::EndRenderPass(bool UpdateResourceStates) +void DeviceContextVkImpl::EndRenderPass() { - TDeviceContextBase::EndRenderPass(UpdateResourceStates); + TDeviceContextBase::EndRenderPass(); // TDeviceContextBase::EndRenderPass calls ResetRenderTargets() that in turn // calls m_CommandBuffer.EndRenderPass() |
