diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-07 19:14:43 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-07 19:14:43 +0000 |
| commit | a34d7e04dc092e6c1bae4db120edbf5e6fc8c564 (patch) | |
| tree | da8797d3bfcd4685ba57e42699dae3dc1b43b448 /Graphics | |
| parent | Vk backend: fixed ClearRenderTarget and ClearDepthStencil for subpass attachm... (diff) | |
| download | DiligentCore-a34d7e04dc092e6c1bae4db120edbf5e6fc8c564.tar.gz DiligentCore-a34d7e04dc092e6c1bae4db120edbf5e6fc8c564.zip | |
First implementation of render passes in d3d11
Diffstat (limited to 'Graphics')
4 files changed, 188 insertions, 43 deletions
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 3e1a5779..a340bbd2 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -935,6 +935,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::BeginRenderP } #endif + // Reset current render targets (in Vulkan backend, this may end current render pass). ResetRenderTargets(); auto* pNewRenderPass = ValidatedCast<RenderPassImplType>(Attribs.pRenderPass); @@ -1003,7 +1004,8 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::EndRenderPas if (auto* pView = FBDesc.ppAttachments[i]) { auto* pTex = ValidatedCast<TextureImplType>(pView->GetTexture()); - pTex->SetState(RPDesc.pAttachments[i].FinalState); + if (pTex->IsInKnownState()) + pTex->SetState(RPDesc.pAttachments[i].FinalState); } } } diff --git a/Graphics/GraphicsEngine/include/RenderPassBase.hpp b/Graphics/GraphicsEngine/include/RenderPassBase.hpp index 8099abb2..46432ea0 100644 --- a/Graphics/GraphicsEngine/include/RenderPassBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderPassBase.hpp @@ -30,6 +30,7 @@ /// \file /// Implementation of the Diligent::RenderPassBase template class +#include <vector> #include "RenderPass.h" #include "DeviceObjectBase.hpp" #include "RenderDeviceBase.hpp" @@ -88,62 +89,88 @@ public: m_pPreserveAttachments = ALLOCATE(GetRawAllocator(), "Memory for subpass preserve attachments array", Uint32, TotalPreserveAttachmentsCount); } + m_AttachmentStates.resize(Desc.AttachmentCount * Desc.SubpassCount); + m_AttachmentFirstUseSubpass.resize(Desc.AttachmentCount, ATTACHMENT_UNUSED); + auto* pCurrAttachmentRef = m_pAttachmentReferences; auto* pCurrPreserveAttachment = m_pPreserveAttachments; - if (Desc.SubpassCount != 0) + VERIFY(Desc.SubpassCount != 0, "Render pass must have at least one subpass"); + auto* pSubpasses = + ALLOCATE(GetRawAllocator(), "Memory for SubpassDesc array", SubpassDesc, Desc.SubpassCount); + this->m_Desc.pSubpasses = pSubpasses; + for (Uint32 i = 0; i < Desc.SubpassCount; ++i) { - auto* pSubpasses = - ALLOCATE(GetRawAllocator(), "Memory for SubpassDesc array", SubpassDesc, Desc.SubpassCount); - this->m_Desc.pSubpasses = pSubpasses; - for (Uint32 i = 0; i < Desc.SubpassCount; ++i) + for (Uint32 att = 0; att < Desc.AttachmentCount; ++att) { - const auto& SrcSubpass = Desc.pSubpasses[i]; - auto& DstSubpass = pSubpasses[i]; + SetAttachmentState(i, att, i > 0 ? GetAttachmentState(i - 1, att) : Desc.pAttachments[i].InitialState); + } - DstSubpass = SrcSubpass; - if (SrcSubpass.InputAttachmentCount != 0) - { - DstSubpass.pInputAttachments = pCurrAttachmentRef; - for (Uint32 input_attachment = 0; input_attachment < SrcSubpass.InputAttachmentCount; ++input_attachment) - *(pCurrAttachmentRef++) = SrcSubpass.pInputAttachments[input_attachment]; - } - else - DstSubpass.pInputAttachments = nullptr; + const auto& SrcSubpass = Desc.pSubpasses[i]; + auto& DstSubpass = pSubpasses[i]; - if (SrcSubpass.RenderTargetAttachmentCount != 0) + auto UpdateAttachmentStateAndFirstUseSubpass = [this, i](const AttachmentReference& AttRef) // + { + if (AttRef.AttachmentIndex != ATTACHMENT_UNUSED) { - DstSubpass.pRenderTargetAttachments = pCurrAttachmentRef; - for (Uint32 rt_attachment = 0; rt_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rt_attachment) - *(pCurrAttachmentRef++) = SrcSubpass.pRenderTargetAttachments[rt_attachment]; - if (DstSubpass.pResolveAttachments) - { - for (Uint32 rslv_attachment = 0; rslv_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rslv_attachment) - *(pCurrAttachmentRef++) = SrcSubpass.pResolveAttachments[rslv_attachment]; - } - else - DstSubpass.pResolveAttachments = nullptr; + SetAttachmentState(i, AttRef.AttachmentIndex, AttRef.State); + if (m_AttachmentFirstUseSubpass[AttRef.AttachmentIndex] == ATTACHMENT_UNUSED) + m_AttachmentFirstUseSubpass[AttRef.AttachmentIndex] = i; } - else + }; + + DstSubpass = SrcSubpass; + if (SrcSubpass.InputAttachmentCount != 0) + { + DstSubpass.pInputAttachments = pCurrAttachmentRef; + for (Uint32 input_attachment = 0; input_attachment < SrcSubpass.InputAttachmentCount; ++input_attachment, ++pCurrAttachmentRef) { - DstSubpass.pRenderTargetAttachments = nullptr; - DstSubpass.pResolveAttachments = nullptr; + *pCurrAttachmentRef = SrcSubpass.pInputAttachments[input_attachment]; + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); } + } + else + DstSubpass.pInputAttachments = nullptr; - if (SrcSubpass.pDepthStencilAttachment != nullptr) + if (SrcSubpass.RenderTargetAttachmentCount != 0) + { + DstSubpass.pRenderTargetAttachments = pCurrAttachmentRef; + for (Uint32 rt_attachment = 0; rt_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rt_attachment, ++pCurrAttachmentRef) { - DstSubpass.pDepthStencilAttachment = pCurrAttachmentRef; - *(pCurrAttachmentRef++) = *SrcSubpass.pDepthStencilAttachment; + *pCurrAttachmentRef = SrcSubpass.pRenderTargetAttachments[rt_attachment]; + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); } - if (SrcSubpass.PreserveAttachmentCount != 0) + if (DstSubpass.pResolveAttachments) { - DstSubpass.pPreserveAttachments = pCurrPreserveAttachment; - for (Uint32 prsv_attachment = 0; prsv_attachment < SrcSubpass.PreserveAttachmentCount; ++prsv_attachment) - *(pCurrPreserveAttachment++) = SrcSubpass.pPreserveAttachments[prsv_attachment]; + DstSubpass.pResolveAttachments = pCurrAttachmentRef; + for (Uint32 rslv_attachment = 0; rslv_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rslv_attachment, ++pCurrAttachmentRef) + { + *pCurrAttachmentRef = SrcSubpass.pResolveAttachments[rslv_attachment]; + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); + } } - else - DstSubpass.pPreserveAttachments = nullptr; } + else + { + DstSubpass.pRenderTargetAttachments = nullptr; + DstSubpass.pResolveAttachments = nullptr; + } + + if (SrcSubpass.pDepthStencilAttachment != nullptr) + { + DstSubpass.pDepthStencilAttachment = pCurrAttachmentRef; + *(pCurrAttachmentRef++) = *SrcSubpass.pDepthStencilAttachment; + UpdateAttachmentStateAndFirstUseSubpass(*SrcSubpass.pDepthStencilAttachment); + } + + if (SrcSubpass.PreserveAttachmentCount != 0) + { + DstSubpass.pPreserveAttachments = pCurrPreserveAttachment; + for (Uint32 prsv_attachment = 0; prsv_attachment < SrcSubpass.PreserveAttachmentCount; ++prsv_attachment) + *(pCurrPreserveAttachment++) = SrcSubpass.pPreserveAttachments[prsv_attachment]; + } + else + DstSubpass.pPreserveAttachments = nullptr; } VERIFY_EXPR(pCurrAttachmentRef - m_pAttachmentReferences == TotalAttachmentReferencesCount); VERIFY_EXPR(pCurrPreserveAttachment - m_pPreserveAttachments == TotalPreserveAttachmentsCount); @@ -177,6 +204,18 @@ public: IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_RenderPass, TDeviceObjectBase) + RESOURCE_STATE GetAttachmentState(Uint32 Subpass, Uint32 Attachment) const + { + VERIFY_EXPR(Attachment < this->m_Desc.AttachmentCount); + VERIFY_EXPR(Subpass < this->m_Desc.SubpassCount); + return m_AttachmentStates[this->m_Desc.AttachmentCount * Subpass + Attachment]; + } + + Uint32 GetAttachmentFirstUseSubpass(Uint32 Attachment) const + { + return m_AttachmentFirstUseSubpass[Attachment]; + } + protected: static void CountSubpassAttachmentReferences(const RenderPassDesc& Desc, Uint32& TotalAttachmentReferencesCount, @@ -198,8 +237,21 @@ protected: } private: + void SetAttachmentState(Uint32 Subpass, Uint32 Attachment, RESOURCE_STATE State) + { + VERIFY_EXPR(Attachment < this->m_Desc.AttachmentCount); + VERIFY_EXPR(Subpass < this->m_Desc.SubpassCount); + m_AttachmentStates[this->m_Desc.AttachmentCount * Subpass + Attachment] = State; + } + AttachmentReference* m_pAttachmentReferences = nullptr; Uint32* m_pPreserveAttachments = nullptr; + + // Attachment states during each subpass + std::vector<RESOURCE_STATE> m_AttachmentStates; + + // The index of the subpass where the attachment is first used + std::vector<Uint32> m_AttachmentFirstUseSubpass; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 9df79314..ba5cec2f 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -305,6 +305,11 @@ private: /// Prepares for an indexed draw command __forceinline void PrepareForIndexedDraw(DRAW_FLAGS Flags, VALUE_TYPE IndexType); + /// Prepares for current subpass + void BeginSubpass(); + + /// Ends current subpass + void EndSubpass(); template <bool TransitionResources, bool CommitResources> diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index c6f9d289..7da0b98f 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -1582,6 +1582,14 @@ void DeviceContextD3D11Impl::SetRenderTargets(Uint32 Num ITextureView* pDepthStencil,
RESOURCE_STATE_TRANSITION_MODE StateTransitionMode)
{
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_pActiveRenderPass != nullptr)
+ {
+ LOG_ERROR_MESSAGE("Calling SetRenderTargets inside active render pass is invalid. End the render pass first");
+ return;
+ }
+#endif
+
if (TDeviceContextBase::SetRenderTargets(NumRenderTargets, ppRenderTargets, pDepthStencil))
{
for (Uint32 RT = 0; RT < NumRenderTargets; ++RT)
@@ -1628,22 +1636,100 @@ void DeviceContextD3D11Impl::SetRenderTargets(Uint32 Num }
}
+void DeviceContextD3D11Impl::BeginSubpass()
+{
+ VERIFY_EXPR(m_pActiveRenderPass);
+ const auto& RPDesc = m_pActiveRenderPass->GetDesc();
+ VERIFY_EXPR(m_SubpassIndex < RPDesc.SubpassCount);
+ const auto& FBDesc = m_pBoundFramebuffer->GetDesc();
+
+ for (Uint32 att = 0; att < RPDesc.AttachmentCount; ++att)
+ {
+ auto* pTex = ValidatedCast<TextureBaseD3D11>(FBDesc.ppAttachments[att]->GetTexture());
+ if (pTex == nullptr)
+ continue;
+
+ const auto NewState = m_pActiveRenderPass->GetAttachmentState(m_SubpassIndex, att);
+ const auto PrevState = m_SubpassIndex > 0 ?
+ m_pActiveRenderPass->GetAttachmentState(m_SubpassIndex - 1, att) :
+ RPDesc.pAttachments[att].InitialState;
+
+ if (NewState == PrevState)
+ continue;
+
+ switch (NewState)
+ {
+ case RESOURCE_STATE_RENDER_TARGET:
+ case RESOURCE_STATE_DEPTH_WRITE:
+ case RESOURCE_STATE_RESOLVE_DEST:
+ UnbindTextureFromInput(pTex, pTex->GetD3D11Texture());
+ break;
+
+ case RESOURCE_STATE_SHADER_RESOURCE:
+ case RESOURCE_STATE_INPUT_ATTACHMENT:
+ UnbindTextureFromFramebuffer(pTex, false);
+ break;
+
+ default:
+ UNEXPECTED("Unexpected attachment state ", GetResourceStateString(NewState));
+ }
+ }
+
+ CommitRenderTargets();
+}
+
+void DeviceContextD3D11Impl::EndSubpass()
+{
+}
+
void DeviceContextD3D11Impl::BeginRenderPass(const BeginRenderPassAttribs& Attribs)
{
TDeviceContextBase::BeginRenderPass(Attribs);
- UNEXPECTED("Method not implemented");
+ BeginSubpass();
+ // Set the viewport to match the framebuffer size
+ SetViewports(1, nullptr, 0, 0);
+
+ const auto& RPDesc = m_pActiveRenderPass->GetDesc();
+ const auto& FBDesc = m_pBoundFramebuffer->GetDesc();
+
+ for (Uint32 att = 0; att < RPDesc.AttachmentCount; ++att)
+ {
+ auto* pTexView = FBDesc.ppAttachments[att];
+ if (pTexView == nullptr)
+ continue;
+ if (RPDesc.pAttachments[att].LoadOp == ATTACHMENT_LOAD_OP_CLEAR)
+ {
+ auto* pViewD3D11 = ValidatedCast<TextureViewD3D11Impl>(pTexView);
+ const auto FmtAttribs = GetTextureFormatAttribs(pTexView->GetDesc().Format);
+ VERIFY_EXPR(att < Attribs.ClearValueCount);
+ const auto& ClearValue = Attribs.pClearValues[att];
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH ||
+ FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ auto* pd3d11DSV = static_cast<ID3D11DepthStencilView*>(pViewD3D11->GetD3D11View());
+ m_pd3d11DeviceContext->ClearDepthStencilView(pd3d11DSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, ClearValue.DepthStencil.Depth, ClearValue.DepthStencil.Stencil);
+ }
+ else
+ {
+ auto* pd3d11RTV = static_cast<ID3D11RenderTargetView*>(pViewD3D11->GetD3D11View());
+ m_pd3d11DeviceContext->ClearRenderTargetView(pd3d11RTV, ClearValue.Color);
+ }
+ }
+ }
}
void DeviceContextD3D11Impl::NextSubpass()
{
+ EndSubpass();
TDeviceContextBase::NextSubpass();
- UNEXPECTED("Method not implemented");
+ BeginSubpass();
}
void DeviceContextD3D11Impl::EndRenderPass(bool UpdateResourceStates)
{
+ EndSubpass();
TDeviceContextBase::EndRenderPass(UpdateResourceStates);
- UNEXPECTED("Method not implemented");
+ // Nothing needs to be done
}
|
