diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-08-15 22:42:13 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-08-15 22:42:13 +0000 |
| commit | df3a2c7c744eae194c79187a59914c6662f69b52 (patch) | |
| tree | 6f67919092b671b4a0fb637db26f75293f849886 /Graphics/GraphicsEngine | |
| parent | Fixed Visual Studio 16.7 build error (diff) | |
| parent | Vk backend: not setting render pass in SetPipelineState (diff) | |
| download | DiligentCore-df3a2c7c744eae194c79187a59914c6662f69b52.tar.gz DiligentCore-df3a2c7c744eae194c79187a59914c6662f69b52.zip | |
Added render passes to the API (fixed https://github.com/DiligentGraphics/DiligentCore/issues/9)
Diffstat (limited to 'Graphics/GraphicsEngine')
21 files changed, 2327 insertions, 204 deletions
diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index 935aeee9..c6ec31ae 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -13,10 +13,12 @@ set(INCLUDE include/EngineFactoryBase.hpp include/EngineMemory.h include/FenceBase.hpp + include/FramebufferBase.hpp include/pch.h include/PipelineStateBase.hpp include/QueryBase.hpp include/RenderDeviceBase.hpp + include/RenderPassBase.hpp include/ResourceMappingImpl.hpp include/SamplerBase.hpp include/ShaderBase.hpp @@ -41,12 +43,14 @@ set(INTERFACE interface/DeviceObject.h interface/EngineFactory.h interface/Fence.h + interface/Framebuffer.h interface/GraphicsTypes.h interface/InputLayout.h interface/PipelineState.h interface/Query.h interface/RasterizerState.h interface/RenderDevice.h + interface/RenderPass.h interface/ResourceMapping.h interface/Sampler.h interface/Shader.h @@ -61,8 +65,10 @@ set(SOURCE src/APIInfo.cpp src/DefaultShaderSourceStreamFactory.cpp src/EngineMemory.cpp - src/ResourceMapping.cpp - src/Texture.cpp + src/FramebufferBase.cpp + src/ResourceMappingBase.cpp + src/RenderPassBase.cpp + src/TextureBase.cpp ) add_library(Diligent-GraphicsEngine STATIC ${SOURCE} ${INTERFACE} ${INCLUDE}) diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index b4c271fa..e5d9b90e 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -76,6 +76,8 @@ public: using PipelineStateImplType = typename ImplementationTraits::PipelineStateType; using TextureViewImplType = typename TextureImplType::ViewImplType; using QueryImplType = typename ImplementationTraits::QueryType; + using FramebufferImplType = typename ImplementationTraits::FramebufferType; + using RenderPassImplType = typename ImplementationTraits::RenderPassType; /// \param pRefCounters - reference counters object that controls the lifetime of this device context. /// \param pRenderDevice - render device. @@ -120,9 +122,11 @@ public: /// Caches the scissor rects inline void SetScissorRects(Uint32 NumRects, const Rect* pRects, Uint32& RTWidth, Uint32& RTHeight); - /// Caches the render target and depth stencil views. Returns true if any view is different - /// from the cached value and false otherwise. - inline bool SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil); + virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override = 0; + + virtual void DILIGENT_CALL_TYPE NextSubpass() 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, @@ -202,6 +206,13 @@ public: bool UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage); protected: + /// Caches the render target and depth stencil views. Returns true if any view is different + /// from the cached value and false otherwise. + inline bool SetRenderTargets(Uint32 NumRenderTargets, ITextureView* ppRenderTargets[], ITextureView* pDepthStencil); + + /// Initializes render targets for the current subpass + inline bool SetSubpassRenderTargets(); + inline bool SetBlendFactors(const float* BlendFactors, int Dummy); inline bool SetStencilRef(Uint32 StencilRef, int Dummy); @@ -217,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); @@ -309,6 +323,18 @@ protected: /// Use final texture view implementation type to avoid virtual calls to AddRef()/Release() RefCntAutoPtr<TextureViewImplType> m_pBoundDepthStencil; + /// Strong reference to the bound framebuffer. + RefCntAutoPtr<FramebufferImplType> m_pBoundFramebuffer; + + /// Strong reference to the render pass. + RefCntAutoPtr<RenderPassImplType> m_pActiveRenderPass; + + /// 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 @@ -344,6 +370,10 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: LOG_ERROR_MESSAGE("The range of vertex buffer slots being set [", StartSlot, ", ", StartSlot + NumBuffersSet - 1, "] is out of allowed range [0, ", MAX_BUFFER_SLOTS - 1, "]."); NumBuffersSet = MAX_BUFFER_SLOTS - StartSlot; } + + VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION), + "Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); #endif if (Flags & SET_VERTEX_BUFFERS_FLAG_RESET) @@ -392,6 +422,10 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode, int) { #ifdef DILIGENT_DEVELOPMENT + VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION), + "Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); + if (!m_pPipelineState) { LOG_ERROR_MESSAGE("No pipeline state is bound to the pipeline"); @@ -413,6 +447,9 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: template <typename BaseInterface, typename ImplementationTraits> inline void DeviceContextBase<BaseInterface, ImplementationTraits>::InvalidateState() { + if (m_pActiveRenderPass != nullptr) + LOG_ERROR_MESSAGE("Invalidating context inside an active render pass. Call EndRenderPass() to finish the pass."); + DeviceContextBase<BaseInterface, ImplementationTraits>::ClearStateCache(); } @@ -423,6 +460,10 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: m_pIndexBuffer = ValidatedCast<BufferImplType>(pIndexBuffer); m_IndexDataStartOffset = ByteOffset; #ifdef DILIGENT_DEVELOPMENT + VERIFY(!(m_pActiveRenderPass != nullptr && StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION), + "Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); + if (m_pIndexBuffer) { const auto& BuffDesc = m_pIndexBuffer->GetDesc(); @@ -571,7 +612,7 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: const auto& RTVDesc = pRTView->GetDesc(); #ifdef DILIGENT_DEVELOPMENT if (RTVDesc.ViewType != TEXTURE_VIEW_RENDER_TARGET) - LOG_ERROR("Texture view object named '", RTVDesc.Name ? RTVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(RTVDesc.ViewType), "). Render target view is expected"); + LOG_ERROR_MESSAGE("Texture view object named '", RTVDesc.Name ? RTVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(RTVDesc.ViewType), "). Render target view is expected"); #endif // Use this RTV to set the render target size if (m_FramebufferWidth == 0) @@ -587,11 +628,11 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: #ifdef DILIGENT_DEVELOPMENT const auto& TexDesc = pRTView->GetTexture()->GetDesc(); if (m_FramebufferWidth != std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Render target width (", std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); + LOG_ERROR_MESSAGE("Render target width (", std::max(TexDesc.Width >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); if (m_FramebufferHeight != std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Render target height (", std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); + LOG_ERROR_MESSAGE("Render target height (", std::max(TexDesc.Height >> RTVDesc.MostDetailedMip, 1U), ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); if (m_FramebufferSlices != RTVDesc.NumArraySlices) - LOG_ERROR("Number of slices (", RTVDesc.NumArraySlices, ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); + LOG_ERROR_MESSAGE("Number of slices (", RTVDesc.NumArraySlices, ") specified by RTV '", RTVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); #endif } } @@ -611,7 +652,7 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: const auto& DSVDesc = pDepthStencil->GetDesc(); #ifdef DILIGENT_DEVELOPMENT if (DSVDesc.ViewType != TEXTURE_VIEW_DEPTH_STENCIL) - LOG_ERROR("Texture view object named '", DSVDesc.Name ? DSVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(DSVDesc.ViewType), "). Depth stencil view is expected"); + LOG_ERROR_MESSAGE("Texture view object named '", DSVDesc.Name ? DSVDesc.Name : "", "' has incorrect view type (", GetTexViewTypeLiteralName(DSVDesc.ViewType), "). Depth stencil view is expected"); #endif // Use depth stencil size to set render target size @@ -628,11 +669,11 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: #ifdef DILIGENT_DEVELOPMENT const auto& TexDesc = pDepthStencil->GetTexture()->GetDesc(); if (m_FramebufferWidth != std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Depth-stencil target width (", std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); + LOG_ERROR_MESSAGE("Depth-stencil target width (", std::max(TexDesc.Width >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the width of previously bound render targets (", m_FramebufferWidth, ")"); if (m_FramebufferHeight != std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U)) - LOG_ERROR("Depth-stencil target height (", std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); + LOG_ERROR_MESSAGE("Depth-stencil target height (", std::max(TexDesc.Height >> DSVDesc.MostDetailedMip, 1U), ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the height of previously bound render targets (", m_FramebufferHeight, ")"); if (m_FramebufferSlices != DSVDesc.NumArraySlices) - LOG_ERROR("Number of slices (", DSVDesc.NumArraySlices, ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); + LOG_ERROR_MESSAGE("Number of slices (", DSVDesc.NumArraySlices, ") specified by DSV '", DSVDesc.Name, "' is inconsistent with the number of slices in previously bound render targets (", m_FramebufferSlices, ")"); #endif } } @@ -650,6 +691,49 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: } template <typename BaseInterface, typename ImplementationTraits> +inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::SetSubpassRenderTargets() +{ + VERIFY_EXPR(m_pBoundFramebuffer); + VERIFY_EXPR(m_pActiveRenderPass); + + const auto& RPDesc = m_pActiveRenderPass->GetDesc(); + const auto& FBDesc = m_pBoundFramebuffer->GetDesc(); + VERIFY_EXPR(m_SubpassIndex < RPDesc.SubpassCount); + const auto& Subpass = RPDesc.pSubpasses[m_SubpassIndex]; + + ITextureView* ppRTVs[MAX_RENDER_TARGETS] = {}; + ITextureView* pDSV = nullptr; + for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt) + { + const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt]; + if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + ppRTVs[rt] = FBDesc.ppAttachments[RTAttachmentRef.AttachmentIndex]; + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment; + if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + pDSV = FBDesc.ppAttachments[DSAttachmentRef.AttachmentIndex]; + } + } + bool BindRenderTargets = SetRenderTargets(Subpass.RenderTargetAttachmentCount, ppRTVs, pDSV); + + // Use framebuffer dimensions (override what was set by SetRenderTargets) + m_FramebufferWidth = FBDesc.Width; + m_FramebufferHeight = FBDesc.Height; + m_FramebufferSlices = FBDesc.NumArraySlices; + + return BindRenderTargets; +} + + +template <typename BaseInterface, typename ImplementationTraits> inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: GetRenderTargets(Uint32& NumRenderTargets, ITextureView** ppRTVs, ITextureView** ppDSV) { @@ -716,6 +800,10 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::ClearStateCa m_NumScissorRects = 0; ResetRenderTargets(); + + VERIFY(!m_pActiveRenderPass, "Clearing state cache inside an active render pass"); + m_pActiveRenderPass = nullptr; + m_pBoundFramebuffer = nullptr; } template <typename BaseInterface, typename ImplementationTraits> @@ -747,6 +835,8 @@ bool DeviceContextBase<BaseInterface, ImplementationTraits>::CheckIfBoundAsDepth template <typename BaseInterface, typename ImplementationTraits> bool DeviceContextBase<BaseInterface, ImplementationTraits>::UnbindTextureFromFramebuffer(TextureImplType* pTexture, bool bShowMessage) { + VERIFY(m_pActiveRenderPass == nullptr, "State transitions are not allowed inside a render pass."); + if (pTexture == nullptr) return false; @@ -813,6 +903,142 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>::ResetRenderTargets( m_FramebufferSlices = 0; m_pBoundDepthStencil.Release(); + + // Do not reset framebuffer here as there may potentially + // be a subpass without any render target attachments. +} + +template <typename BaseInterface, typename ImplementationTraits> +inline void DeviceContextBase<BaseInterface, ImplementationTraits>::BeginRenderPass(const BeginRenderPassAttribs& Attribs) +{ + VERIFY(m_pActiveRenderPass == nullptr, "Attempting to begin render pass while another render pass ('", m_pActiveRenderPass->GetDesc().Name, "') is active."); + VERIFY(m_pBoundFramebuffer == nullptr, "Attempting to begin render pass while another framebuffer ('", m_pBoundFramebuffer->GetDesc().Name, "') is bound."); + VERIFY(Attribs.pRenderPass != nullptr, "Render pass must not be null"); + VERIFY(Attribs.pFramebuffer != nullptr, "Framebuffer must not be null"); +#ifdef DILIGENT_DEBUG + { + const auto& RPDesc = Attribs.pRenderPass->GetDesc(); + + Uint32 NumRequiredClearValues = 0; + for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) + { + const auto& Attchmnt = RPDesc.pAttachments[i]; + if (Attchmnt.LoadOp == ATTACHMENT_LOAD_OP_CLEAR) + NumRequiredClearValues = i + 1; + + const auto& FmtAttribs = GetTextureFormatAttribs(Attchmnt.Format); + if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) + { + if (Attchmnt.StencilLoadOp == ATTACHMENT_LOAD_OP_CLEAR) + NumRequiredClearValues = i + 1; + } + } + VERIFY(Attribs.ClearValueCount >= NumRequiredClearValues, + "Begin render pass operation requiers at least ", NumRequiredClearValues, + " clear values, but only ", Attribs.ClearValueCount, " are given."); + VERIFY(Attribs.ClearValueCount == 0 || Attribs.pClearValues != nullptr, + "pClearValues must not be null when ClearValueCount is not zero"); + } +#endif + + // Reset current render targets (in Vulkan backend, this may end current render pass). + ResetRenderTargets(); + + auto* pNewRenderPass = ValidatedCast<RenderPassImplType>(Attribs.pRenderPass); + auto* pNewFramebuffer = ValidatedCast<FramebufferImplType>(Attribs.pFramebuffer); + if (Attribs.StateTransitionMode != RESOURCE_STATE_TRANSITION_MODE_NONE) + { + const auto& RPDesc = pNewRenderPass->GetDesc(); + const auto& FBDesc = pNewFramebuffer->GetDesc(); + VERIFY(RPDesc.AttachmentCount <= FBDesc.AttachmentCount, + "The number of attachments (", FBDesc.AttachmentCount, + ") in currently bound framebuffer is smaller than the number of attachments in the render pass (", RPDesc.AttachmentCount, ")"); + for (Uint32 i = 0; i < FBDesc.AttachmentCount; ++i) + { + auto* pView = FBDesc.ppAttachments[i]; + if (pView == nullptr) + return; + + auto* pTex = ValidatedCast<TextureImplType>(pView->GetTexture()); + auto RequiredState = RPDesc.pAttachments[i].InitialState; + if (Attribs.StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + if (pTex->IsInKnownState() && !pTex->CheckState(RequiredState)) + { + StateTransitionDesc Barrier{pTex, RESOURCE_STATE_UNKNOWN, RequiredState, true}; + this->TransitionResourceStates(1, &Barrier); + } + } + else if (Attribs.StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) + { + DvpVerifyTextureState(*pTex, RequiredState, "BeginRenderPass"); + } + } + } + + m_pActiveRenderPass = pNewRenderPass; + m_pBoundFramebuffer = pNewFramebuffer; + m_SubpassIndex = 0; + m_RenderPassAttachmentsTransitionMode = Attribs.StateTransitionMode; + UpdateAttachmentStates(m_SubpassIndex); + SetSubpassRenderTargets(); +} + +template <typename BaseInterface, typename ImplementationTraits> +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>::UpdateAttachmentStates(Uint32 SubpassIndex) +{ + if (m_RenderPassAttachmentsTransitionMode != RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + return; + + VERIFY_EXPR(m_pActiveRenderPass != nullptr); + VERIFY_EXPR(m_pBoundFramebuffer != nullptr); + + 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) + { + if (auto* pView = FBDesc.ppAttachments[i]) + { + auto* pTex = ValidatedCast<TextureImplType>(pView->GetTexture()); + if (pTex->IsInKnownState()) + { + 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_RenderPassAttachmentsTransitionMode = RESOURCE_STATE_TRANSITION_MODE_NONE; + ResetRenderTargets(); } @@ -837,7 +1063,14 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::ClearDepthSt if (pView != m_pBoundDepthStencil) { - if (m_pDevice->GetDeviceCaps().IsGLDevice()) + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("Depth-stencil view '", ViewDesc.Name, + "' is not bound as framebuffer attachment. ClearDepthStencil command inside a render pass " + "requires depth-stencil view to be bound as a framebuffer attachment."); + return false; + } + else if (m_pDevice->GetDeviceCaps().IsGLDevice()) { LOG_ERROR_MESSAGE("Depth-stencil view '", ViewDesc.Name, "' is not bound to the device context. ClearDepthStencil command requires " @@ -882,13 +1115,21 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>::ClearRenderT { RTFound = m_pBoundRenderTargets[i] == pView; } + if (!RTFound) { - if (m_pDevice->GetDeviceCaps().IsGLDevice()) + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("Render target view '", ViewDesc.Name, + "' is not bound as framebuffer attachment. ClearRenderTarget command inside a render pass " + "requires render target view to be bound as a framebuffer attachment."); + return false; + } + else if (m_pDevice->GetDeviceCaps().IsGLDevice()) { LOG_ERROR_MESSAGE("Render target view '", ViewDesc.Name, "' is not bound to the device context. ClearRenderTarget command " - "requires render target view be bound to the device contex in OpenGL backend"); + "requires render target view to be bound to the device contex in OpenGL backend"); return false; } else @@ -957,6 +1198,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: UpdateBuffer(IBuffer* pBuffer, Uint32 Offset, Uint32 Size, const void* pData, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) { VERIFY(pBuffer != nullptr, "Buffer must not be null"); + VERIFY(m_pActiveRenderPass == nullptr, "UpdateBuffer command must be used outside of render pass."); #ifdef DILIGENT_DEVELOPMENT { const auto& BuffDesc = ValidatedCast<BufferImplType>(pBuffer)->GetDesc(); @@ -979,6 +1221,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: { VERIFY(pSrcBuffer != nullptr, "Source buffer must not be null"); VERIFY(pDstBuffer != nullptr, "Destination buffer must not be null"); + VERIFY(m_pActiveRenderPass == nullptr, "CopyBuffer command must be used outside of render pass."); #ifdef DILIGENT_DEVELOPMENT { const auto& SrcBufferDesc = ValidatedCast<BufferImplType>(pSrcBuffer)->GetDesc(); @@ -1062,6 +1305,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: UpdateTexture(ITexture* pTexture, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData, RESOURCE_STATE_TRANSITION_MODE SrcBufferTransitionMode, RESOURCE_STATE_TRANSITION_MODE TextureTransitionMode) { VERIFY(pTexture != nullptr, "pTexture must not be null"); + VERIFY(m_pActiveRenderPass == nullptr, "UpdateTexture command must be used outside of render pass."); ValidateUpdateTextureParams(pTexture->GetDesc(), MipLevel, Slice, DstBox, SubresData); } @@ -1071,6 +1315,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: { VERIFY(CopyAttribs.pSrcTexture, "Src texture must not be null"); VERIFY(CopyAttribs.pDstTexture, "Dst texture must not be null"); + VERIFY(m_pActiveRenderPass == nullptr, "CopyTexture command must be used outside of render pass."); ValidateCopyTextureParams(CopyAttribs); } @@ -1102,6 +1347,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: GenerateMips(ITextureView* pTexView) { VERIFY(pTexView != nullptr, "pTexView must not be null"); + VERIFY(m_pActiveRenderPass == nullptr, "GenerateMips command must be used outside of render pass."); #ifdef DILIGENT_DEVELOPMENT { const auto& ViewDesc = pTexView->GetDesc(); @@ -1158,6 +1404,7 @@ void DeviceContextBase<BaseInterface, ImplementationTraits>:: DEV_CHECK_ERR(!ResolveFmtAttribs.IsTypeless, "Format of a resolve operation must not be typeless when one of the texture formats is typeless"); } + VERIFY(m_pActiveRenderPass == nullptr, "ResolveTextureSubresource command must be used outside of render pass."); #endif } @@ -1266,6 +1513,13 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: return false; } + if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); + return false; + } + return true; } @@ -1317,6 +1571,13 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: return false; } + if (m_pActiveRenderPass != nullptr && Attribs.IndirectAttribsBufferStateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) + { + LOG_ERROR_MESSAGE("Resource state transitons are not allowed inside a render pass and may result in an undefined behavior. " + "Do not use RESOURCE_STATE_TRANSITION_MODE_TRANSITION or end the render pass first."); + return false; + } + return true; } @@ -1326,7 +1587,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: { if (!m_pPipelineState) { - LOG_ERROR("No pipeline state is bound"); + LOG_ERROR_MESSAGE("No pipeline state is bound"); return; } @@ -1347,7 +1608,7 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>:: const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) { - LOG_WARNING_MESSAGE("Number of currently bound render targets (", m_NumBoundRenderTargets, + LOG_WARNING_MESSAGE("The number of currently bound render targets (", m_NumBoundRenderTargets, ") does not match the number of outputs specified by the PSO '", PSODesc.Name, "' (", Uint32{GraphicsPipeline.NumRenderTargets}, ")."); } @@ -1391,6 +1652,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: return false; } + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("DispatchCompute command must be performed outside of render pass"); + return false; + } + if (Attribs.ThreadGroupCountX == 0) LOG_WARNING_MESSAGE("DispatchCompute command arguments are invalid: ThreadGroupCountX is zero."); @@ -1420,6 +1687,12 @@ inline bool DeviceContextBase<BaseInterface, ImplementationTraits>:: return false; } + if (m_pActiveRenderPass != nullptr) + { + LOG_ERROR_MESSAGE("DispatchComputeIndirect command must be performed outside of render pass"); + return false; + } + if (pAttribsBuffer != nullptr) { if ((pAttribsBuffer->GetDesc().BindFlags & BIND_INDIRECT_DRAW_ARGS) == 0) diff --git a/Graphics/GraphicsEngine/include/FramebufferBase.hpp b/Graphics/GraphicsEngine/include/FramebufferBase.hpp new file mode 100644 index 00000000..fc008d73 --- /dev/null +++ b/Graphics/GraphicsEngine/include/FramebufferBase.hpp @@ -0,0 +1,136 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Implementation of the Diligent::FramebufferBase template class + +#include "Framebuffer.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" +#include "TextureView.h" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +void ValidateFramebufferDesc(const FramebufferDesc& Desc); + +/// Template class implementing base functionality for the framebuffer object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (e.g. Diligent::IFramebufferVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template <class BaseInterface, class RenderDeviceImplType> +class FramebufferBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, FramebufferDesc> +{ +public: + using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, FramebufferDesc>; + + /// \param pRefCounters - reference counters object that controls the lifetime of this framebuffer pass. + /// \param pDevice - pointer to the device. + /// \param Desc - Framebuffer description. + /// \param bIsDeviceInternal - flag indicating if the Framebuffer is an internal device object and + /// must not keep a strong reference to the device. + FramebufferBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const FramebufferDesc& Desc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal}, + m_pRenderPass{Desc.pRenderPass} + { + ValidateFramebufferDesc(Desc); + + if (this->m_Desc.AttachmentCount > 0) + { + m_ppAttachments = + ALLOCATE(GetRawAllocator(), "Memory for framebuffer attachment array", ITextureView*, this->m_Desc.AttachmentCount); + this->m_Desc.ppAttachments = m_ppAttachments; + for (Uint32 i = 0; i < this->m_Desc.AttachmentCount; ++i) + { + if (Desc.ppAttachments[i] == nullptr) + continue; + + m_ppAttachments[i] = Desc.ppAttachments[i]; + m_ppAttachments[i]->AddRef(); + + if (this->m_Desc.Width == 0 || this->m_Desc.Height == 0 || this->m_Desc.NumArraySlices == 0) + { + const auto& ViewDesc = m_ppAttachments[i]->GetDesc(); + const auto& TexDesc = m_ppAttachments[i]->GetTexture()->GetDesc(); + + auto MipLevelProps = GetMipLevelProperties(TexDesc, ViewDesc.MostDetailedMip); + if (this->m_Desc.Width == 0) + this->m_Desc.Width = MipLevelProps.LogicalWidth; + if (this->m_Desc.Height == 0) + this->m_Desc.Height = MipLevelProps.LogicalHeight; + if (this->m_Desc.NumArraySlices == 0) + this->m_Desc.NumArraySlices = ViewDesc.NumArraySlices; + } + } + } + + // It is legal for a subpass to use no color or depth/stencil attachments, either because it has no attachment + // references or because all of them are VK_ATTACHMENT_UNUSED. This kind of subpass can use shader side effects + // such as image stores and atomics to produce an output. In this case, the subpass continues to use the width, + // height, and layers of the framebuffer to define the dimensions of the rendering area. + if (this->m_Desc.Width == 0) + LOG_ERROR_AND_THROW("The framebuffer width is zero and can't be automatically determined as there are no non-null attachments"); + if (this->m_Desc.Height == 0) + LOG_ERROR_AND_THROW("The framebuffer height is zero and can't be automatically determined as there are no non-null attachments"); + if (this->m_Desc.NumArraySlices == 0) + LOG_ERROR_AND_THROW("The framebuffer array slice count is zero and can't be automatically determined as there are no non-null attachments"); + + Desc.pRenderPass->AddRef(); + } + + ~FramebufferBase() + { + if (this->m_Desc.AttachmentCount > 0) + { + VERIFY_EXPR(m_ppAttachments != nullptr); + for (Uint32 i = 0; i < this->m_Desc.AttachmentCount; ++i) + { + m_ppAttachments[i]->Release(); + } + GetRawAllocator().Free(m_ppAttachments); + } + this->m_Desc.pRenderPass->Release(); + } + + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_Framebuffer, TDeviceObjectBase) + +private: + RefCntAutoPtr<IRenderPass> m_pRenderPass; + + ITextureView** m_ppAttachments = nullptr; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 6d70f4da..fbfbb100 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -69,6 +69,8 @@ public: TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}, m_NumShaders{0} { + ValidateDesc(); + const auto& SrcLayout = PSODesc.ResourceLayout; size_t StringPoolSize = 0; if (SrcLayout.Variables != nullptr) @@ -187,6 +189,8 @@ public: DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State"); + m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass; + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) { auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; @@ -197,6 +201,34 @@ public: } } + if (m_pRenderPass) + { + const auto& RPDesc = m_pRenderPass->GetDesc(); + VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount); + const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex]; + + this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast<Uint8>(Subpass.RenderTargetAttachmentCount); + for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt) + { + const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt]; + if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + this->m_Desc.GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format; + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment; + if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format; + } + } + } + const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; LayoutElement* pLayoutElements = nullptr; if (InputLayout.NumElements > 0) @@ -389,17 +421,58 @@ protected: RefCntAutoPtr<IShader> m_pHS; ///< Strong reference to the hull shader RefCntAutoPtr<IShader> m_pCS; ///< Strong reference to the compute shader + RefCntAutoPtr<IRenderPass> m_pRenderPass; ///< Strong reference to the render pass object + IShader* m_ppShaders[5] = {}; ///< Array of pointers to the shaders used by this PSO size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout private: +#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", (this->m_Desc.IsComputePipeline ? "compute" : "graphics"), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) + + void ValidateDesc() const + { + if (this->m_Desc.IsComputePipeline) + { + if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr) + { + LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines"); + } + } + else + { + const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline; + if (GraphicsPipeline.pRenderPass != nullptr) + { + if (GraphicsPipeline.NumRenderTargets != 0) + LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used"); + if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + + for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) + { + if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + } + + const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc(); + if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'"); + } + else + { + if (GraphicsPipeline.SubpassIndex != 0) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); + } + } + } + void CheckRasterizerStateDesc() const { const auto& RSDesc = this->m_Desc.GraphicsPipeline.RasterizerDesc; if (RSDesc.FillMode == FILL_MODE_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED"); if (RSDesc.CullMode == CULL_MODE_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED"); } void CheckAndCorrectDepthStencilDesc() @@ -408,7 +481,7 @@ private: if (DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN) { if (DSSDesc.DepthEnable) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled"); + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled"); else DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc; } @@ -418,13 +491,13 @@ private: if (DSSDesc.StencilEnable) { if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled"); + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled"); } else { @@ -455,18 +528,18 @@ private: if (BlendEnable) { if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED"); if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED"); if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED"); if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED) - LOG_ERROR_AND_THROW("Description of graphics PSO '", this->m_Desc.Name, "' is invalid: BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED"); + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED"); } else { @@ -489,6 +562,7 @@ private: RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp; } } +#undef LOG_PSO_ERROR_AND_THROW }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp index 49e54d12..a0ffeda6 100644 --- a/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp +++ b/Graphics/GraphicsEngine/include/RenderDeviceBase.hpp @@ -220,6 +220,12 @@ public: /// Size of the query object (QueryD3D12Impl, QueryVkImpl, etc.), in bytes const size_t QuerySize; + + /// Size of the render pass object (RenderPassD3D12Impl, RenderPassVkImpl, etc.), in bytes + const size_t RenderPassObjSize; + + /// Size of the framebuffer object (FramebufferD3D12Impl, FramebufferVkImpl, etc.), in bytes + const size_t FramebufferObjSize; }; /// \param pRefCounters - reference counters object that controls the lifetime of this render device @@ -243,17 +249,19 @@ public: m_TexFmtInfoInitFlags (TEX_FORMAT_NUM_FORMATS, false, STD_ALLOCATOR_RAW_MEM(bool, RawMemAllocator, "Allocator for vector<bool>")), m_wpDeferredContexts (NumDeferredContexts, RefCntWeakPtr<IDeviceContext>(), STD_ALLOCATOR_RAW_MEM(RefCntWeakPtr<IDeviceContext>, RawMemAllocator, "Allocator for vector< RefCntWeakPtr<IDeviceContext> >")), m_RawMemAllocator {RawMemAllocator}, - m_TexObjAllocator {RawMemAllocator, ObjectSizes.TextureObjSize, 64 }, - m_TexViewObjAllocator {RawMemAllocator, ObjectSizes.TexViewObjSize, 64 }, - m_BufObjAllocator {RawMemAllocator, ObjectSizes.BufferObjSize, 128 }, - m_BuffViewObjAllocator {RawMemAllocator, ObjectSizes.BuffViewObjSize, 128 }, - m_ShaderObjAllocator {RawMemAllocator, ObjectSizes.ShaderObjSize, 32 }, - m_SamplerObjAllocator {RawMemAllocator, ObjectSizes.SamplerObjSize, 32 }, - m_PSOAllocator {RawMemAllocator, ObjectSizes.PSOSize, 128 }, - m_SRBAllocator {RawMemAllocator, ObjectSizes.SRBSize, 1024}, - m_ResMappingAllocator {RawMemAllocator, sizeof(ResourceMappingImpl), 16 }, - m_FenceAllocator {RawMemAllocator, ObjectSizes.FenceSize, 16 }, - m_QueryAllocator {RawMemAllocator, ObjectSizes.QuerySize, 16 } + m_TexObjAllocator {RawMemAllocator, ObjectSizes.TextureObjSize, 64 }, + m_TexViewObjAllocator {RawMemAllocator, ObjectSizes.TexViewObjSize, 64 }, + m_BufObjAllocator {RawMemAllocator, ObjectSizes.BufferObjSize, 128 }, + m_BuffViewObjAllocator {RawMemAllocator, ObjectSizes.BuffViewObjSize, 128 }, + m_ShaderObjAllocator {RawMemAllocator, ObjectSizes.ShaderObjSize, 32 }, + m_SamplerObjAllocator {RawMemAllocator, ObjectSizes.SamplerObjSize, 32 }, + m_PSOAllocator {RawMemAllocator, ObjectSizes.PSOSize, 128 }, + m_SRBAllocator {RawMemAllocator, ObjectSizes.SRBSize, 1024}, + m_ResMappingAllocator {RawMemAllocator, sizeof(ResourceMappingImpl), 16 }, + m_FenceAllocator {RawMemAllocator, ObjectSizes.FenceSize, 16 }, + m_QueryAllocator {RawMemAllocator, ObjectSizes.QuerySize, 16 }, + m_RenderPassAllocator {RawMemAllocator, ObjectSizes.RenderPassObjSize, 16 }, + m_FramebufferAllocator {RawMemAllocator, ObjectSizes.FramebufferObjSize, 16 } // clang-format on { // Initialize texture format info @@ -426,6 +434,8 @@ protected: FixedBlockMemoryAllocator m_ResMappingAllocator; ///< Allocator for resource mapping objects FixedBlockMemoryAllocator m_FenceAllocator; ///< Allocator for fence objects FixedBlockMemoryAllocator m_QueryAllocator; ///< Allocator for query objects + FixedBlockMemoryAllocator m_RenderPassAllocator; ///< Allocator for render pass objects + FixedBlockMemoryAllocator m_FramebufferAllocator; ///< Allocator for framebuffer objects }; diff --git a/Graphics/GraphicsEngine/include/RenderPassBase.hpp b/Graphics/GraphicsEngine/include/RenderPassBase.hpp new file mode 100644 index 00000000..c2a6b5c1 --- /dev/null +++ b/Graphics/GraphicsEngine/include/RenderPassBase.hpp @@ -0,0 +1,278 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Implementation of the Diligent::RenderPassBase template class + +#include <vector> +#include <utility> + +#include "RenderPass.h" +#include "DeviceObjectBase.hpp" +#include "RenderDeviceBase.hpp" + +namespace Diligent +{ + +void ValidateRenderPassDesc(const RenderPassDesc& Desc); + +template <typename RenderDeviceImplType> +void _CorrectAttachmentState(RESOURCE_STATE& State) {} + +template <> +inline void _CorrectAttachmentState<class RenderDeviceVkImpl>(RESOURCE_STATE& State) +{ + if (State == RESOURCE_STATE_RESOLVE_DEST) + { + // In Vulkan resolve attachments must be in VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL state. + // It is important to correct the state because outside of render pass RESOURCE_STATE_RESOLVE_DEST maps + // to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL. + State = RESOURCE_STATE_RENDER_TARGET; + } +} + +/// Template class implementing base functionality for the render pass object. + +/// \tparam BaseInterface - base interface that this class will inheret +/// (e.g. Diligent::IRenderPassVk). +/// \tparam RenderDeviceImplType - type of the render device implementation +/// (Diligent::RenderDeviceD3D11Impl, Diligent::RenderDeviceD3D12Impl, +/// Diligent::RenderDeviceGLImpl, or Diligent::RenderDeviceVkImpl) +template <class BaseInterface, class RenderDeviceImplType> +class RenderPassBase : public DeviceObjectBase<BaseInterface, RenderDeviceImplType, RenderPassDesc> +{ +public: + using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, RenderPassDesc>; + + /// \param pRefCounters - reference counters object that controls the lifetime of this render pass. + /// \param pDevice - pointer to the device. + /// \param Desc - Render pass description. + /// \param bIsDeviceInternal - flag indicating if the RenderPass is an internal device object and + /// must not keep a strong reference to the device. + RenderPassBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const RenderPassDesc& Desc, + bool bIsDeviceInternal = false) : + TDeviceObjectBase{pRefCounters, pDevice, Desc, bIsDeviceInternal} + { + ValidateRenderPassDesc(Desc); + + if (Desc.AttachmentCount != 0) + { + auto* pAttachments = + ALLOCATE(GetRawAllocator(), "Memory for RenderPassAttachmentDesc array", RenderPassAttachmentDesc, Desc.AttachmentCount); + this->m_Desc.pAttachments = pAttachments; + for (Uint32 i = 0; i < Desc.AttachmentCount; ++i) + { + pAttachments[i] = Desc.pAttachments[i]; + _CorrectAttachmentState<RenderDeviceImplType>(pAttachments[i].FinalState); + } + } + + Uint32 TotalAttachmentReferencesCount = 0; + Uint32 TotalPreserveAttachmentsCount = 0; + CountSubpassAttachmentReferences(Desc, TotalAttachmentReferencesCount, TotalPreserveAttachmentsCount); + if (TotalAttachmentReferencesCount != 0) + { + m_pAttachmentReferences = ALLOCATE(GetRawAllocator(), "Memory for subpass attachment references array", AttachmentReference, TotalAttachmentReferencesCount); + } + if (TotalPreserveAttachmentsCount != 0) + { + m_pPreserveAttachments = ALLOCATE(GetRawAllocator(), "Memory for subpass preserve attachments array", Uint32, TotalPreserveAttachmentsCount); + } + + m_AttachmentStates.resize(Desc.AttachmentCount * Desc.SubpassCount); + m_AttachmentFirstLastUse.resize(Desc.AttachmentCount, std::pair<Uint32, Uint32>{ATTACHMENT_UNUSED, 0}); + + auto* pCurrAttachmentRef = m_pAttachmentReferences; + auto* pCurrPreserveAttachment = m_pPreserveAttachments; + 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 subpass = 0; subpass < Desc.SubpassCount; ++subpass) + { + for (Uint32 att = 0; att < Desc.AttachmentCount; ++att) + { + SetAttachmentState(subpass, att, subpass > 0 ? GetAttachmentState(subpass - 1, att) : Desc.pAttachments[subpass].InitialState); + } + + const auto& SrcSubpass = Desc.pSubpasses[subpass]; + auto& DstSubpass = pSubpasses[subpass]; + + auto UpdateAttachmentStateAndFirstUseSubpass = [this, subpass](const AttachmentReference& AttRef) // + { + if (AttRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + SetAttachmentState(subpass, AttRef.AttachmentIndex, AttRef.State); + auto& FirstLastUse = m_AttachmentFirstLastUse[AttRef.AttachmentIndex]; + if (FirstLastUse.first == ATTACHMENT_UNUSED) + FirstLastUse.first = subpass; + FirstLastUse.second = subpass; + } + }; + + DstSubpass = SrcSubpass; + if (SrcSubpass.InputAttachmentCount != 0) + { + DstSubpass.pInputAttachments = pCurrAttachmentRef; + for (Uint32 input_attachment = 0; input_attachment < SrcSubpass.InputAttachmentCount; ++input_attachment, ++pCurrAttachmentRef) + { + *pCurrAttachmentRef = SrcSubpass.pInputAttachments[input_attachment]; + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); + } + } + else + DstSubpass.pInputAttachments = nullptr; + + if (SrcSubpass.RenderTargetAttachmentCount != 0) + { + DstSubpass.pRenderTargetAttachments = pCurrAttachmentRef; + for (Uint32 rt_attachment = 0; rt_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rt_attachment, ++pCurrAttachmentRef) + { + *pCurrAttachmentRef = SrcSubpass.pRenderTargetAttachments[rt_attachment]; + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); + } + + if (DstSubpass.pResolveAttachments) + { + DstSubpass.pResolveAttachments = pCurrAttachmentRef; + for (Uint32 rslv_attachment = 0; rslv_attachment < SrcSubpass.RenderTargetAttachmentCount; ++rslv_attachment, ++pCurrAttachmentRef) + { + *pCurrAttachmentRef = SrcSubpass.pResolveAttachments[rslv_attachment]; + _CorrectAttachmentState<RenderDeviceImplType>(pCurrAttachmentRef->State); + UpdateAttachmentStateAndFirstUseSubpass(*pCurrAttachmentRef); + } + } + } + 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); + + if (Desc.DependencyCount != 0) + { + auto* pDependencies = + ALLOCATE(GetRawAllocator(), "Memory for SubpassDependencyDesc array", SubpassDependencyDesc, Desc.DependencyCount); + this->m_Desc.pDependencies = pDependencies; + for (Uint32 i = 0; i < Desc.DependencyCount; ++i) + { + pDependencies[i] = Desc.pDependencies[i]; + } + } + } + + ~RenderPassBase() + { + auto& RawAllocator = GetRawAllocator(); + if (this->m_Desc.pAttachments != nullptr) + RawAllocator.Free(const_cast<RenderPassAttachmentDesc*>(this->m_Desc.pAttachments)); + if (this->m_Desc.pSubpasses != nullptr) + RawAllocator.Free(const_cast<SubpassDesc*>(this->m_Desc.pSubpasses)); + if (this->m_Desc.pDependencies != nullptr) + RawAllocator.Free(const_cast<SubpassDependencyDesc*>(this->m_Desc.pDependencies)); + if (m_pAttachmentReferences != nullptr) + RawAllocator.Free(m_pAttachmentReferences); + if (m_pPreserveAttachments != nullptr) + RawAllocator.Free(m_pPreserveAttachments); + } + + 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]; + } + + std::pair<Uint32, Uint32> GetAttachmentFirstLastUse(Uint32 Attachment) const + { + return m_AttachmentFirstLastUse[Attachment]; + } + +protected: + static void CountSubpassAttachmentReferences(const RenderPassDesc& Desc, + Uint32& TotalAttachmentReferencesCount, + Uint32& TotalPreserveAttachmentsCount) + { + TotalAttachmentReferencesCount = 0; + TotalPreserveAttachmentsCount = 0; + for (Uint32 i = 0; i < Desc.SubpassCount; ++i) + { + const auto& Subpass = Desc.pSubpasses[i]; + TotalAttachmentReferencesCount += Subpass.InputAttachmentCount; + TotalAttachmentReferencesCount += Subpass.RenderTargetAttachmentCount; + if (Subpass.pResolveAttachments != nullptr) + TotalAttachmentReferencesCount += Subpass.RenderTargetAttachmentCount; + if (Subpass.pDepthStencilAttachment != nullptr) + TotalAttachmentReferencesCount += 1; + TotalPreserveAttachmentsCount += Subpass.PreserveAttachmentCount; + } + } + +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<std::pair<Uint32, Uint32>> m_AttachmentFirstLastUse; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp index 38414be2..1805f7d3 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.hpp +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -123,6 +123,9 @@ public: ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues"); this->m_Desc.CommandQueueMask &= DeviceQueuesMask; + if ((this->m_Desc.BindFlags & BIND_INPUT_ATTACHMENT) != 0) + this->m_Desc.BindFlags |= BIND_SHADER_RESOURCE; + // Validate correctness of texture description ValidateTextureDesc(this->m_Desc); } @@ -181,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/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index c355b315..59d3bd30 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240064 +#define DILIGENT_API_VERSION 240065 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index 79f8bd39..eb77ba8e 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -49,6 +49,8 @@ #include "PipelineState.h" #include "Fence.h" #include "Query.h" +#include "RenderPass.h" +#include "Framebuffer.h" #include "CommandList.h" #include "SwapChain.h" @@ -609,6 +611,44 @@ struct CopyTextureAttribs }; typedef struct CopyTextureAttribs CopyTextureAttribs; + +/// BeginRenderPass command attributes. + +/// This structure is used by IDeviceContext::BeginRenderPass(). +struct BeginRenderPassAttribs +{ + /// Render pass to begin. + IRenderPass* pRenderPass DEFAULT_INITIALIZER(nullptr); + + /// Framebuffer containing the attachments that are used with the render pass. + IFramebuffer* pFramebuffer DEFAULT_INITIALIZER(nullptr); + + /// The number of elements in pClearValues array. + Uint32 ClearValueCount DEFAULT_INITIALIZER(0); + + /// A pointer to an array of ClearValueCount OptimizedClearValue structures that contains + /// clear values for each attachment, if the attachment uses a LoadOp value of ATTACHMENT_LOAD_OP_CLEAR + /// or if the attachment has a depth/stencil format and uses a StencilLoadOp value of ATTACHMENT_LOAD_OP_CLEAR. + /// The array is indexed by attachment number. Only elements corresponding to cleared attachments are used. + /// Other elements of pClearValues are ignored. + OptimizedClearValue* pClearValues DEFAULT_INITIALIZER(nullptr); + + /// 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; + #define DILIGENT_INTERFACE_NAME IDeviceContext #include "../../../Primitives/interface/DefineInterfaceHelperMacros.h" @@ -864,6 +904,21 @@ DILIGENT_BEGIN_INTERFACE(IDeviceContext, IObject) RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) PURE; + /// Begins a new render pass. + + /// \param [in] Attribs - The command attributes, see Diligent::BeginRenderPassAttribs for details. + VIRTUAL void METHOD(BeginRenderPass)(THIS_ + const BeginRenderPassAttribs REF Attribs) PURE; + + + /// Transitions to the next subpass in the render pass instance. + VIRTUAL void METHOD(NextSubpass)(THIS) PURE; + + + /// Ends current render pass. + VIRTUAL void METHOD(EndRenderPass)(THIS) PURE; + + /// Executes a draw command. /// \param [in] Attribs - Draw command attributes, see Diligent::DrawAttribs for details. diff --git a/Graphics/GraphicsEngine/interface/Framebuffer.h b/Graphics/GraphicsEngine/interface/Framebuffer.h new file mode 100644 index 00000000..9b00ea70 --- /dev/null +++ b/Graphics/GraphicsEngine/interface/Framebuffer.h @@ -0,0 +1,102 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +// clang-format off + +/// \file +/// Definition of the Diligent::IFramebuffer interface and related data structures + +#include "DeviceObject.h" +#include "RenderPass.h" +#include "TextureView.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {05DA9E47-3CA6-4F96-A967-1DDDC53181A6} +static const struct INTERFACE_ID IID_Framebuffer = + { 0x5da9e47, 0x3ca6, 0x4f96, { 0xa9, 0x67, 0x1d, 0xdd, 0xc5, 0x31, 0x81, 0xa6 } }; + +/// Framebuffer description. +struct FramebufferDesc DILIGENT_DERIVE(DeviceObjectAttribs) + + /// Render pass that the framebuffer will be compatible with. + IRenderPass* pRenderPass DEFAULT_INITIALIZER(nullptr); + + /// The number of attachments. + Uint32 AttachmentCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of attachments. + ITextureView* const* ppAttachments DEFAULT_INITIALIZER(nullptr); + + /// Width of the framebuffer. + Uint32 Width DEFAULT_INITIALIZER(0); + + /// Height of the framebuffer. + Uint32 Height DEFAULT_INITIALIZER(0); + + /// The number of array slices in the framebuffer. + Uint32 NumArraySlices DEFAULT_INITIALIZER(0); +}; +typedef struct FramebufferDesc FramebufferDesc; + +#if DILIGENT_CPP_INTERFACE + +/// Framebuffer interface + +/// Framebuffer has no methods. +class IFramebuffer : public IDeviceObject +{ +public: + virtual const FramebufferDesc& GetDesc() const override = 0; +}; + +#else + +struct IFramebuffer; + +// C requires that a struct or union has at least one member +//struct IFramebufferMethods +//{ +//}; + +struct IFramebufferVtbl +{ + struct IObjectMethods Object; + struct IDeviceObjectMethods DeviceObject; + //struct IFramebufferMethods Framebuffer; +}; + +typedef struct IFramebuffer +{ + struct IFramebufferVtbl* pVtbl; +} IFramebuffer; + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 0d0631b7..41e83d4e 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -65,7 +65,7 @@ DILIGENT_TYPED_ENUM(VALUE_TYPE, Uint8) /// Resource binding flags -/// [D3D11_BIND_FLAG]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476085(v=vs.85).aspx +/// [D3D11_BIND_FLAG]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_bind_flag /// /// This enumeration describes which parts of the pipeline a resource can be bound to. /// It generally mirrors [D3D11_BIND_FLAG][] enumeration. It is used by @@ -84,13 +84,14 @@ DILIGENT_TYPED_ENUM(BIND_FLAGS, Uint32) BIND_RENDER_TARGET = 0x20L,///< A texture can be bound as a render target BIND_DEPTH_STENCIL = 0x40L,///< A texture can be bound as a depth-stencil target BIND_UNORDERED_ACCESS = 0x80L,///< A buffer or a texture can be bound as an unordered access view - BIND_INDIRECT_DRAW_ARGS = 0x100L///< A buffer can be bound as the source buffer for indirect draw commands + BIND_INDIRECT_DRAW_ARGS = 0x100L,///< A buffer can be bound as the source buffer for indirect draw commands + BIND_INPUT_ATTACHMENT = 0x200L ///< A texture can be used as render pass input attachment }; DEFINE_FLAG_ENUM_OPERATORS(BIND_FLAGS) /// Resource usage -/// [D3D11_USAGE]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476259(v=vs.85).aspx +/// [D3D11_USAGE]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_usage /// This enumeration describes expected resource usage. It generally mirrors [D3D11_USAGE] enumeration. /// The enumeration is used by /// - BufferDesc to describe usage for a buffer @@ -133,7 +134,7 @@ DEFINE_FLAG_ENUM_OPERATORS(CPU_ACCESS_FLAGS) /// Resource mapping type -/// [D3D11_MAP]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476181(v=vs.85).aspx +/// [D3D11_MAP]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_map /// Describes how a mapped resource will be accessed. This enumeration generally /// mirrors [D3D11_MAP][] enumeration. It is used by /// - IBuffer::Map to describe buffer mapping type @@ -257,7 +258,7 @@ DILIGENT_TYPED_ENUM(BUFFER_VIEW_TYPE, Uint8) /// This enumeration describes available texture formats and generally mirrors DXGI_FORMAT enumeration. /// The table below provides detailed information on each format. Most of the formats are widely supported /// by all modern APIs (DX10+, OpenGL3.3+ and OpenGLES3.0+). Specific requirements are additionally indicated. -/// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb173059(v=vs.85).aspx">DXGI_FORMAT enumeration on MSDN</a>, +/// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format">DXGI_FORMAT enumeration on MSDN</a>, /// <a href = "https://www.opengl.org/wiki/Image_Format">OpenGL Texture Formats</a> /// DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) @@ -568,7 +569,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC1_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RGB_S3TC_DXT1_EXT is used. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1">BC1 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc1">BC1 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT1_Format">DXT1 on OpenGL.org </a> TEX_FORMAT_BC1_TYPELESS, @@ -577,7 +578,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC1_UNORM. OpenGL counterpart: GL_COMPRESSED_RGB_S3TC_DXT1_EXT.\n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1">BC1 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc1">BC1 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT1_Format">DXT1 on OpenGL.org </a> TEX_FORMAT_BC1_UNORM, @@ -586,7 +587,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC1_UNORM_SRGB. OpenGL counterpart: GL_COMPRESSED_SRGB_S3TC_DXT1_EXT.\n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1">BC1 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc1">BC1 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT1_Format">DXT1 on OpenGL.org </a> TEX_FORMAT_BC1_UNORM_SRGB, @@ -594,7 +595,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC2_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT is used. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC2">BC2 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc2">BC2 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT3_Format">DXT3 on OpenGL.org </a> TEX_FORMAT_BC2_TYPELESS, @@ -603,7 +604,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC2_UNORM. OpenGL counterpart: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC2">BC2 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc2">BC2 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT3_Format">DXT3 on OpenGL.org </a> TEX_FORMAT_BC2_UNORM, @@ -612,7 +613,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC2_UNORM_SRGB. OpenGL counterpart: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC2">BC2 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc2">BC2 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT3_Format">DXT3 on OpenGL.org </a> TEX_FORMAT_BC2_UNORM_SRGB, @@ -620,7 +621,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC3_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT is used. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC3">BC3 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc3">BC3 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT5_Format">DXT5 on OpenGL.org </a> TEX_FORMAT_BC3_TYPELESS, @@ -629,7 +630,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC3_UNORM. OpenGL counterpart: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC3">BC3 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc3">BC3 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT5_Format">DXT5 on OpenGL.org </a> TEX_FORMAT_BC3_UNORM, @@ -638,7 +639,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC3_UNORM_SRGB. OpenGL counterpart: GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT. \n /// [GL_EXT_texture_compression_s3tc]: https://www.khronos.org/registry/gles/extensions/EXT/texture_compression_s3tc.txt /// OpenGL & OpenGLES: [GL_EXT_texture_compression_s3tc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC3">BC3 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc3">BC3 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/S3_Texture_Compression#DXT5_Format">DXT5 on OpenGL.org </a> TEX_FORMAT_BC3_UNORM_SRGB, @@ -646,7 +647,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC4_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RED_RGTC1 is used. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC4">BC4 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc4">BC4 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC4_TYPELESS, @@ -655,7 +656,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC4_UNORM. OpenGL counterpart: GL_COMPRESSED_RED_RGTC1. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC4">BC4 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc4">BC4 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC4_UNORM, @@ -664,7 +665,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC4_SNORM. OpenGL counterpart: GL_COMPRESSED_SIGNED_RED_RGTC1. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC4">BC4 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc4">BC4 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC4_SNORM, @@ -672,7 +673,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC5_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RG_RGTC2 is used. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC5">BC5 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc5">BC5 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC5_TYPELESS, @@ -681,7 +682,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC5_UNORM. OpenGL counterpart: GL_COMPRESSED_RG_RGTC2. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC5">BC5 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc5">BC5 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC5_UNORM, @@ -690,7 +691,7 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// D3D counterpart: DXGI_FORMAT_BC5_SNORM. OpenGL counterpart: GL_COMPRESSED_SIGNED_RG_RGTC2. \n /// [GL_ARB_texture_compression_rgtc]: https://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt /// OpenGL & OpenGLES: [GL_ARB_texture_compression_rgtc][] extension is required - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC5">BC5 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc5">BC5 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/Image_Format#Compressed_formats">Compressed formats on OpenGL.org </a> TEX_FORMAT_BC5_SNORM, @@ -741,49 +742,49 @@ DILIGENT_TYPED_ENUM(TEXTURE_FORMAT, Uint16) /// Three-component typeless block-compression format. \n /// D3D counterpart: DXGI_FORMAT_BC6H_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT is used. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308952(v=vs.85).aspx">BC6H on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format">BC6H on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC6H_TYPELESS, /// Three-component unsigned half-precision floating-point format with 16 bits for each channel. \n /// D3D counterpart: DXGI_FORMAT_BC6H_UF16. OpenGL counterpart: GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308952(v=vs.85).aspx">BC6H on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format">BC6H on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC6H_UF16, /// Three-channel signed half-precision floating-point format with 16 bits per each channel. \n /// D3D counterpart: DXGI_FORMAT_BC6H_SF16. OpenGL counterpart: GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308952(v=vs.85).aspx">BC6H on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc6h-format">BC6H on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC6H_SF16, /// Three-component typeless block-compression format. \n /// D3D counterpart: DXGI_FORMAT_BC7_TYPELESS. OpenGL does not have direct counterpart, GL_COMPRESSED_RGBA_BPTC_UNORM is used. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308953(v=vs.85).aspx">BC7 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format">BC7 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC7_TYPELESS, /// Three-component block-compression unsigned-normalized-integer format with 4 to 7 bits per color channel and 0 to 8 bits of alpha. \n /// D3D counterpart: DXGI_FORMAT_BC7_UNORM. OpenGL counterpart: GL_COMPRESSED_RGBA_BPTC_UNORM. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308953(v=vs.85).aspx">BC7 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format">BC7 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC7_UNORM, /// Three-component block-compression unsigned-normalized-integer sRGB format with 4 to 7 bits per color channel and 0 to 8 bits of alpha. \n /// D3D counterpart: DXGI_FORMAT_BC7_UNORM_SRGB. OpenGL counterpart: GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM. \n - /// [GL_ARB_texture_compression_bptc]: https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/specs/ARB/texture_compression_bptc.txt + /// [GL_ARB_texture_compression_bptc]: https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_bptc.txt /// OpenGL: [GL_ARB_texture_compression_bptc][] extension is required. Not supported in at least OpenGLES3.1 - /// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh308953(v=vs.85).aspx">BC7 on MSDN </a>, + /// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/direct3d11/bc7-format">BC7 on MSDN </a>, /// <a href = "https://www.opengl.org/wiki/BPTC_Texture_Compression">BPTC Texture Compression on OpenGL.org </a> TEX_FORMAT_BC7_UNORM_SRGB, @@ -816,8 +817,8 @@ DILIGENT_TYPED_ENUM(FILTER_TYPE, Uint8) /// Texture address mode -/// [D3D11_TEXTURE_ADDRESS_MODE]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476256(v=vs.85).aspx -/// [D3D12_TEXTURE_ADDRESS_MODE]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn770441(v=vs.85).aspx +/// [D3D11_TEXTURE_ADDRESS_MODE]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_texture_address_mode +/// [D3D12_TEXTURE_ADDRESS_MODE]: https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode /// Defines a technique for resolving texture coordinates that are outside of /// the boundaries of a texture. The enumeration generally mirrors [D3D11_TEXTURE_ADDRESS_MODE][]/[D3D12_TEXTURE_ADDRESS_MODE][] enumeration. /// It is used by SamplerDesc structure to define the address mode for U,V and W texture coordinates. @@ -857,8 +858,8 @@ DILIGENT_TYPED_ENUM(TEXTURE_ADDRESS_MODE, Uint8) /// Comparison function -/// [D3D11_COMPARISON_FUNC]: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476101(v=vs.85).aspx -/// [D3D12_COMPARISON_FUNC]: https://msdn.microsoft.com/en-us/library/windows/desktop/dn770349(v=vs.85).aspx +/// [D3D11_COMPARISON_FUNC]: https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_comparison_func +/// [D3D12_COMPARISON_FUNC]: https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_comparison_func /// This enumeartion defines a comparison function. It generally mirrors [D3D11_COMPARISON_FUNC]/[D3D12_COMPARISON_FUNC] enum and is used by /// - SamplerDesc to define a comparison function if one of the comparison mode filters is used /// - StencilOpDesc to define a stencil function @@ -1078,6 +1079,55 @@ DILIGENT_TYPED_ENUM(PRIMITIVE_TOPOLOGY, Uint8) PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES }; + +/// Defines optimized depth-stencil clear value. +struct DepthStencilClearValue +{ + /// Depth clear value + Float32 Depth DEFAULT_INITIALIZER(1.f); + /// Stencil clear value + Uint8 Stencil DEFAULT_INITIALIZER(0); + +#if DILIGENT_CPP_INTERFACE + DepthStencilClearValue()noexcept{} + + DepthStencilClearValue(Float32 _Depth, + Uint8 _Stencil)noexcept : + Depth {_Depth }, + Stencil {_Stencil} + {} +#endif +}; +typedef struct DepthStencilClearValue DepthStencilClearValue; + +/// Defines optimized clear value. +struct OptimizedClearValue +{ + /// Format + TEXTURE_FORMAT Format DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); + + /// Render target clear value + Float32 Color[4] DEFAULT_INITIALIZER({}); + + /// Depth stencil clear value + DepthStencilClearValue DepthStencil; + +#if DILIGENT_CPP_INTERFACE + bool operator == (const OptimizedClearValue& rhs)const + { + return Format == rhs.Format && + Color[0] == rhs.Color[0] && + Color[1] == rhs.Color[1] && + Color[2] == rhs.Color[2] && + Color[3] == rhs.Color[3] && + DepthStencil.Depth == rhs.DepthStencil.Depth && + DepthStencil.Stencil == rhs.DepthStencil.Stencil; + } +#endif +}; +typedef struct OptimizedClearValue OptimizedClearValue; + + /// Describes common device object attributes struct DeviceObjectAttribs { @@ -1141,7 +1191,7 @@ typedef struct AdapterAttribs AdapterAttribs; /// Flags indicating how an image is stretched to fit a given monitor's resolution. -/// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb173066(v=vs.85).aspx">DXGI_MODE_SCALING enumeration on MSDN</a>, +/// \sa <a href = "https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb173066(v=vs.85)">DXGI_MODE_SCALING enumeration on MSDN</a>, enum SCALING_MODE { /// Unspecified scaling. @@ -1160,7 +1210,7 @@ enum SCALING_MODE /// Flags indicating the method the raster uses to create an image on a surface. -/// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/bb173067">DXGI_MODE_SCANLINE_ORDER enumeration on MSDN</a>, +/// \sa <a href = "https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb173067(v=vs.85)">DXGI_MODE_SCANLINE_ORDER enumeration on MSDN</a>, enum SCANLINE_ORDER { /// Scanline order is unspecified @@ -1327,7 +1377,7 @@ struct SwapChainDesc typedef struct SwapChainDesc SwapChainDesc; /// Full screen mode description -/// \sa <a href = "https://msdn.microsoft.com/en-us/library/windows/desktop/hh404531(v=vs.85).aspx">DXGI_SWAP_CHAIN_FULLSCREEN_DESC structure on MSDN</a>, +/// \sa <a href = "https://docs.microsoft.com/en-us/windows/win32/api/dxgi1_2/ns-dxgi1_2-dxgi_swap_chain_fullscreen_desc">DXGI_SWAP_CHAIN_FULLSCREEN_DESC structure on MSDN</a>, struct FullScreenModeDesc { /// A Boolean value that specifies whether the swap chain is in fullscreen mode. @@ -1594,6 +1644,7 @@ struct VulkanDescriptorPoolSize Uint32 NumStorageBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumUniformTexelBufferDescriptors DEFAULT_INITIALIZER(0); Uint32 NumStorageTexelBufferDescriptors DEFAULT_INITIALIZER(0); + Uint32 NumInputAttachmentDescriptors DEFAULT_INITIALIZER(0); #if DILIGENT_CPP_INTERFACE VulkanDescriptorPoolSize()noexcept {} @@ -1606,7 +1657,8 @@ struct VulkanDescriptorPoolSize Uint32 _NumUniformBufferDescriptors, Uint32 _NumStorageBufferDescriptors, Uint32 _NumUniformTexelBufferDescriptors, - Uint32 _NumStorageTexelBufferDescriptors)noexcept : + Uint32 _NumStorageTexelBufferDescriptors, + Uint32 _NumInputAttachmentDescriptors)noexcept : MaxDescriptorSets {_MaxDescriptorSets }, NumSeparateSamplerDescriptors {_NumSeparateSamplerDescriptors }, NumCombinedSamplerDescriptors {_NumCombinedSamplerDescriptors }, @@ -1615,7 +1667,8 @@ struct VulkanDescriptorPoolSize NumUniformBufferDescriptors {_NumUniformBufferDescriptors }, NumStorageBufferDescriptors {_NumStorageBufferDescriptors }, NumUniformTexelBufferDescriptors{_NumUniformTexelBufferDescriptors}, - NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors} + NumStorageTexelBufferDescriptors{_NumStorageTexelBufferDescriptors}, + NumInputAttachmentDescriptors {_NumInputAttachmentDescriptors } { // On clang aggregate initialization fails to compile if // structure members have default initializers @@ -1650,8 +1703,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) /// the engine creates another one. VulkanDescriptorPoolSize MainDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB - {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt + {8192, 1024, 8192, 8192, 1024, 4096, 4096, 1024, 1024, 256} #endif ; @@ -1662,8 +1715,8 @@ struct EngineVkCreateInfo DILIGENT_DERIVE(EngineCreateInfo) VulkanDescriptorPoolSize DynamicDescriptorPoolSize #if DILIGENT_CPP_INTERFACE - //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB - {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256} + //Max SepSm CmbSm SmpImg StrImg UB SB UTxB StTxB InptAtt + {2048, 256, 2048, 2048, 256, 1024, 1024, 256, 256, 64} #endif ; @@ -1906,61 +1959,256 @@ struct TextureFormatInfoExt DILIGENT_DERIVE(TextureFormatInfo) typedef struct TextureFormatInfoExt TextureFormatInfoExt; +/// Pipeline stage flags. + +/// These flags mirror [VkPipelineStageFlagBits](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VkPipelineStageFlagBits) +/// enum and only have effect in Vulkan backend. +DILIGENT_TYPED_ENUM(PIPELINE_STAGE_FLAGS, Uint32) +{ + /// Undefined stage + PIPELINE_STAGE_FLAG_UNDEFINED = 0x00000000, + + /// The top of the pipeline. + PIPELINE_STAGE_FLAG_TOP_OF_PIPE = 0x00000001, + + /// The stage of the pipeline where Draw/DispatchIndirect data structures are consumed. + PIPELINE_STAGE_FLAG_DRAW_INDIRECT = 0x00000002, + + /// The stage of the pipeline where vertex and index buffers are consumed. + PIPELINE_STAGE_FLAG_VERTEX_INPUT = 0x00000004, + + /// Vertex shader stage. + PIPELINE_STAGE_FLAG_VERTEX_SHADER = 0x00000008, + + /// Hull shader stage. + PIPELINE_STAGE_FLAG_HULL_SHADER = 0x00000010, + + /// Domain shader stage. + PIPELINE_STAGE_FLAG_DOMAIN_SHADER = 0x00000020, + + /// Geometry shader stage. + PIPELINE_STAGE_FLAG_GEOMETRY_SHADER = 0x00000040, + + /// Pixel shader stage. + PIPELINE_STAGE_FLAG_PIXEL_SHADER = 0x00000080, + + /// The stage of the pipeline where early fragment tests (depth and + /// stencil tests before fragment shading) are performed. This stage + /// also includes subpass load operations for framebuffer attachments + /// with a depth/stencil format. + PIPELINE_STAGE_FLAG_EARLY_FRAGMENT_TESTS = 0x00000100, + + /// The stage of the pipeline where late fragment tests (depth and + /// stencil tests after fragment shading) are performed. This stage + /// also includes subpass store operations for framebuffer attachments + /// with a depth/stencil format. + PIPELINE_STAGE_FLAG_LATE_FRAGMENT_TESTS = 0x00000200, + + /// The stage of the pipeline after blending where the final color values + /// are output from the pipeline. This stage also includes subpass load + /// and store operations and multisample resolve operations for framebuffer + /// attachments with a color or depth/stencil format. + PIPELINE_STAGE_FLAG_RENDER_TARGET = 0x00000400, + + /// Compute shader stage. + PIPELINE_STAGE_FLAG_COMPUTE_SHADER = 0x00000800, + + /// The stage where all copy and outside-of-renderpass + /// resolve and clear operations happen. + PIPELINE_STAGE_FLAG_TRANSFER = 0x00001000, + + /// The bottom of the pipeline. + PIPELINE_STAGE_FLAG_BOTTOM_OF_PIPE = 0x00002000, + + /// A pseudo-stage indicating execution on the host of reads/writes + /// of device memory. This stage is not invoked by any commands recorded + /// in a command buffer. + PIPELINE_STAGE_FLAG_HOST = 0x00004000, + + /// The stage of the pipeline where the predicate of conditional rendering is consumed. + PIPELINE_STAGE_FLAG_CONDITIONAL_RENDERING = 0x00040000, + + /// The stage of the pipeline where the shading rate texture is + /// read to determine the shading rate for portions of a rasterized primitive. + PIPELINE_STAGE_FLAG_SHADING_RATE_TEXTURE = 0x00400000, + + /// Ray tracing shader. + PIPELINE_STAGE_FLAG_RAY_TRACING_SHADER = 0x00200000, + + /// Acceleration structure build shader. + PIPELINE_STAGE_FLAG_ACCELERATION_STRUCTURE_BUILD = 0x02000000, + + /// Task shader stage. + PIPELINE_STAGE_FLAG_TASK_SHADER = 0x00080000, + + /// Mesh shader stage. + PIPELINE_STAGE_FLAG_MESH_SHADER = 0x00100000, + + /// + PIPELINE_STAGE_FLAG_FRAGMENT_DENSITY_PROCESS = 0x00800000, + + /// Default pipeline stage that is determined by the resource state. + /// For example, RESOURCE_STATE_RENDER_TARGET corresponds to + /// PIPELINE_STAGE_FLAG_RENDER_TARGET pipeline stage. + PIPELINE_STAGE_FLAG_DEFAULT = 0x80000000 +}; +DEFINE_FLAG_ENUM_OPERATORS(PIPELINE_STAGE_FLAGS) + + +/// Access flag. + +/// The flags mirror [VkAccessFlags](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VkAccessFlags) enum +/// and only have effect in Vulkan backend. +DILIGENT_TYPED_ENUM(ACCESS_FLAGS, Uint32) +{ + /// No access + ACCESS_FLAG_NONE = 0x00000000, + + /// Read access to indirect command data read as part of an indirect + /// drawing or dispatch command. + ACCESS_FLAG_INDIRECT_COMMAND_READ = 0x00000001, + + /// Read access to an index buffer as part of an indexed drawing command + ACCESS_FLAG_INDEX_READ = 0x00000002, + + /// Read access to a vertex buffer as part of a drawing command + ACCESS_FLAG_VERTEX_READ = 0x00000004, + + /// Read access to a uniform buffer + ACCESS_FLAG_UNIFORM_READ = 0x00000008, + + /// Read access to an input attachment within a render pass during fragment shading + ACCESS_FLAG_INPUT_ATTACHMENT_READ = 0x00000010, + + /// Read access from a shader resource, formatted buffer, UAV + ACCESS_FLAG_SHADER_READ = 0x00000020, + + /// Write access to a UAV + ACCESS_FLAG_SHADER_WRITE = 0x00000040, + + /// Read access to a color render target, such as via blending, + /// logic operations, or via certain subpass load operations. + ACCESS_FLAG_RENDER_TARGET_READ = 0x00000080, + + /// Write access to a color render target, resolve, or depth/stencil resolve + /// attachment during a render pass or via certain subpass load and store operations. + ACCESS_FLAG_RENDER_TARGET_WRITE = 0x00000100, + + /// Read access to a depth/stencil buffer, via depth or stencil operations + /// or via certain subpass load operations + ACCESS_FLAG_DEPTH_STENCIL_READ = 0x00000200, + + /// Write access to a depth/stencil buffer, via depth or stencil operations + /// or via certain subpass load and store operations + ACCESS_FLAG_DEPTH_STENCIL_WRITE = 0x00000400, + + /// Read access to an texture or buffer in a copy operation. + ACCESS_FLAG_COPY_SRC = 0x00000800, + + /// Write access to an texture or buffer in a copy operation. + ACCESS_FLAG_COPY_DST = 0x00001000, + + /// Read access by a host operation. Accesses of this type are + /// not performed through a resource, but directly on memory. + ACCESS_FLAG_HOST_READ = 0x00002000, + + /// Write access by a host operation. Accesses of this type are + /// not performed through a resource, but directly on memory. + ACCESS_FLAG_HOST_WRITE = 0x00004000, + + /// All read accesses. It is always valid in any access mask, + /// and is treated as equivalent to setting all READ access flags + /// that are valid where it is used. + ACCESS_FLAG_MEMORY_READ = 0x00008000, + + /// All write accesses. It is always valid in any access mask, + /// and is treated as equivalent to setting all WRITE access + // flags that are valid where it is used. + ACCESS_FLAG_MEMORY_WRITE = 0x00010000, + + /// Read access to a predicate as part of conditional rendering. + ACCESS_FLAG_CONDITIONAL_RENDERING_READ = 0x00100000, + + /// Read access to a shading rate texture as part of a drawing comman. + ACCESS_FLAG_SHADING_RATE_TEXTURE_READ = 0x00800000, + + /// Read access to an acceleration structure as part of a trace or build command. + ACCESS_FLAG_ACCELERATION_STRUCTURE_READ = 0x00200000, + + /// Write access to an acceleration structure or acceleration structure + /// scratch buffer as part of a build command. + ACCESS_FLAG_ACCELERATION_STRUCTURE_WRITE = 0x00400000, + + /// Read access to a fragment density map attachment during + /// dynamic fragment density map operations. + ACCESS_FLAG_FRAGMENT_DENSITY_MAP_READ = 0x01000000, + + /// Default access type that is determined by the resource state. + /// For example, RESOURCE_STATE_RENDER_TARGET corresponds to + /// ACCESS_FLAG_RENDER_TARGET_WRITE access type. + ACCESS_FLAG_DEFAULT = 0x80000000 +}; +DEFINE_FLAG_ENUM_OPERATORS(ACCESS_FLAGS) + + /// Resource usage state DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) { /// The resource state is not known to the engine and is managed by the application - RESOURCE_STATE_UNKNOWN = 0x0000, + RESOURCE_STATE_UNKNOWN = 0x00000, /// The resource state is known to the engine, but is undefined. A resource is typically in an undefined state right after initialization. - RESOURCE_STATE_UNDEFINED = 0x0001, + RESOURCE_STATE_UNDEFINED = 0x00001, /// The resource is accessed as vertex buffer - RESOURCE_STATE_VERTEX_BUFFER = 0x0002, + RESOURCE_STATE_VERTEX_BUFFER = 0x00002, /// The resource is accessed as constant (uniform) buffer - RESOURCE_STATE_CONSTANT_BUFFER = 0x0004, + RESOURCE_STATE_CONSTANT_BUFFER = 0x00004, /// The resource is accessed as index buffer - RESOURCE_STATE_INDEX_BUFFER = 0x0008, + RESOURCE_STATE_INDEX_BUFFER = 0x00008, /// The resource is accessed as render target - RESOURCE_STATE_RENDER_TARGET = 0x0010, + RESOURCE_STATE_RENDER_TARGET = 0x00010, /// The resource is used for unordered access - RESOURCE_STATE_UNORDERED_ACCESS = 0x0020, + RESOURCE_STATE_UNORDERED_ACCESS = 0x00020, /// The resource is used in a writable depth-stencil view or in clear operation - RESOURCE_STATE_DEPTH_WRITE = 0x0040, + RESOURCE_STATE_DEPTH_WRITE = 0x00040, /// The resource is used in a read-only depth-stencil view - RESOURCE_STATE_DEPTH_READ = 0x0080, + RESOURCE_STATE_DEPTH_READ = 0x00080, /// The resource is accessed from a shader - RESOURCE_STATE_SHADER_RESOURCE = 0x0100, + RESOURCE_STATE_SHADER_RESOURCE = 0x00100, /// The resource is used as the destination for stream output - RESOURCE_STATE_STREAM_OUT = 0x0200, + RESOURCE_STATE_STREAM_OUT = 0x00200, /// The resource is used as indirect draw/dispatch arguments buffer - RESOURCE_STATE_INDIRECT_ARGUMENT = 0x0400, + RESOURCE_STATE_INDIRECT_ARGUMENT = 0x00400, /// The resource is used as the destination in a copy operation - RESOURCE_STATE_COPY_DEST = 0x0800, + RESOURCE_STATE_COPY_DEST = 0x00800, /// The resource is used as the source in a copy operation - RESOURCE_STATE_COPY_SOURCE = 0x1000, + RESOURCE_STATE_COPY_SOURCE = 0x01000, /// The resource is used as the destination in a resolve operation - RESOURCE_STATE_RESOLVE_DEST = 0x2000, + RESOURCE_STATE_RESOLVE_DEST = 0x02000, /// The resource is used as the source in a resolve operation - RESOURCE_STATE_RESOLVE_SOURCE = 0x4000, + RESOURCE_STATE_RESOLVE_SOURCE = 0x04000, + + /// The resource is used as input attachment in a render pass subpass + RESOURCE_STATE_INPUT_ATTACHMENT = 0x08000, /// The resource is used for present - RESOURCE_STATE_PRESENT = 0x8000, + RESOURCE_STATE_PRESENT = 0x10000, - RESOURCE_STATE_MAX_BIT = 0x8000, + RESOURCE_STATE_MAX_BIT = 0x10000, RESOURCE_STATE_GENERIC_READ = RESOURCE_STATE_VERTEX_BUFFER | RESOURCE_STATE_CONSTANT_BUFFER | @@ -1969,6 +2217,7 @@ DILIGENT_TYPED_ENUM(RESOURCE_STATE, Uint32) RESOURCE_STATE_INDIRECT_ARGUMENT | RESOURCE_STATE_COPY_SOURCE }; +DEFINE_FLAG_ENUM_OPERATORS(RESOURCE_STATE); /// State transition barrier type DILIGENT_TYPED_ENUM(STATE_TRANSITION_TYPE, Uint8) diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 5e99a392..3de6f02d 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -43,6 +43,7 @@ #include "ShaderResourceVariable.h" #include "Shader.h" #include "Sampler.h" +#include "RenderPass.h" DILIGENT_BEGIN_NAMESPACE(Diligent) @@ -150,24 +151,24 @@ typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc; /// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure. struct GraphicsPipelineDesc { - /// Vertex shader to be used with the pipeline + /// Vertex shader to be used with the pipeline. IShader* pVS DEFAULT_INITIALIZER(nullptr); - /// Pixel shader to be used with the pipeline + /// Pixel shader to be used with the pipeline. IShader* pPS DEFAULT_INITIALIZER(nullptr); - /// Domain shader to be used with the pipeline + /// Domain shader to be used with the pipeline. IShader* pDS DEFAULT_INITIALIZER(nullptr); - /// Hull shader to be used with the pipeline + /// Hull shader to be used with the pipeline. IShader* pHS DEFAULT_INITIALIZER(nullptr); - /// Geometry shader to be used with the pipeline + /// Geometry shader to be used with the pipeline. IShader* pGS DEFAULT_INITIALIZER(nullptr); //D3D12_STREAM_OUTPUT_DESC StreamOutput; - /// Blend state description + /// Blend state description. BlendStateDesc BlendDesc; /// 32-bit sample mask that determines which samples get updated @@ -176,34 +177,48 @@ struct GraphicsPipelineDesc /// depend on whether an application uses multisample render targets. Uint32 SampleMask DEFAULT_INITIALIZER(0xFFFFFFFF); - /// Rasterizer state description + /// Rasterizer state description. RasterizerStateDesc RasterizerDesc; - /// Depth-stencil state description + /// Depth-stencil state description. DepthStencilStateDesc DepthStencilDesc; - /// Input layout + /// Input layout. InputLayoutDesc InputLayout; //D3D12_INDEX_BUFFER_STRIP_CUT_VALUE IBStripCutValue; - /// Primitive topology type + /// Primitive topology type. PRIMITIVE_TOPOLOGY PrimitiveTopology DEFAULT_INITIALIZER(PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); - /// Number of viewports used by this pipeline + /// The number of viewports used by this pipeline Uint8 NumViewports DEFAULT_INITIALIZER(1); - /// Number of render targets in the RTVFormats member + /// The number of render targets in the RTVFormats array. + /// Must be 0 when pRenderPass is not null. Uint8 NumRenderTargets DEFAULT_INITIALIZER(0); - /// Render target formats + /// When pRenderPass is not null, the subpass + /// index within the render pass. + /// When pRenderPass is null, this member must be 0. + Uint8 SubpassIndex DEFAULT_INITIALIZER(0); + + /// Render target formats. + /// All formats must be TEX_FORMAT_UNKNOWN when pRenderPass is not null. TEXTURE_FORMAT RTVFormats[8] DEFAULT_INITIALIZER({}); - /// Depth-stencil format + /// Depth-stencil format. + /// Must be TEX_FORMAT_UNKNOWN when pRenderPass is not null. TEXTURE_FORMAT DSVFormat DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); - /// Multisampling parameters + /// Multisampling parameters. SampleDesc SmplDesc; + /// Pointer to the render pass object. + + /// When non-null render pass is specified, NumRenderTargets must be 0, + /// and all RTV formats as well as DSV format must be TEX_FORMAT_UNKNOWN. + IRenderPass* pRenderPass DEFAULT_INITIALIZER(nullptr); + /// Node mask. Uint32 NodeMask DEFAULT_INITIALIZER(0); diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 23eae467..ddbc75b2 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -46,6 +46,8 @@ #include "PipelineState.h" #include "Fence.h" #include "Query.h" +#include "RenderPass.h" +#include "Framebuffer.h" #include "DepthStencilState.h" #include "RasterizerState.h" @@ -188,6 +190,31 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) IQuery** ppQuery) PURE; + /// Creates a render pass object + + /// \param [in] Desc - Render pass description, see Diligent::RenderPassDesc for details. + /// \param [out] ppRenderPass - Address of the memory location where the pointer to the + /// render pass interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + VIRTUAL void METHOD(CreateRenderPass)(THIS_ + const RenderPassDesc REF Desc, + IRenderPass** ppRenderPass) PURE; + + + + /// Creates a framebuffer object + + /// \param [in] Desc - Framebuffer description, see Diligent::FramebufferDesc for details. + /// \param [out] ppFramebuffer - Address of the memory location where the pointer to the + /// framebuffer interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + VIRTUAL void METHOD(CreateFramebuffer)(THIS_ + const FramebufferDesc REF Desc, + IFramebuffer** ppFramebuffer) PURE; + + /// Gets the device capabilities, see Diligent::DeviceCaps for details VIRTUAL const DeviceCaps REF METHOD(GetDeviceCaps)(THIS) CONST PURE; diff --git a/Graphics/GraphicsEngine/interface/RenderPass.h b/Graphics/GraphicsEngine/interface/RenderPass.h new file mode 100644 index 00000000..3f822e0c --- /dev/null +++ b/Graphics/GraphicsEngine/interface/RenderPass.h @@ -0,0 +1,398 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +// clang-format off + +/// \file +/// Definition of the Diligent::IRenderPass interface and related data structures + +#include "DeviceObject.h" + +DILIGENT_BEGIN_NAMESPACE(Diligent) + +// {B818DEC7-174D-447A-A8E4-94D21C57B40A} +static const struct INTERFACE_ID IID_RenderPass = + { 0xb818dec7, 0x174d, 0x447a, { 0xa8, 0xe4, 0x94, 0xd2, 0x1c, 0x57, 0xb4, 0xa } }; + + +/// Render pass attachment load operation +/// Vulkan counterpart: [VkAttachmentLoadOp](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VkAttachmentLoadOp). +/// D3D12 counterpart: [D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_render_pass_beginning_access_type). +DILIGENT_TYPED_ENUM(ATTACHMENT_LOAD_OP, Uint8) +{ + /// The previous contents of the texture within the render area will be preserved. + /// Vulkan counterpart: VK_ATTACHMENT_LOAD_OP_LOAD. + /// D3D12 counterpart: D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE. + ATTACHMENT_LOAD_OP_LOAD = 0, + + /// The contents within the render area will be cleared to a uniform value, which is + /// specified when a render pass instance is begun. + /// Vulkan counterpart: VK_ATTACHMENT_LOAD_OP_CLEAR. + /// D3D12 counterpart: D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_CLEAR. + ATTACHMENT_LOAD_OP_CLEAR, + + /// The previous contents within the area need not be preserved; the contents of + /// the attachment will be undefined inside the render area. + /// Vulkan counterpart: VK_ATTACHMENT_LOAD_OP_DONT_CARE. + /// D3D12 counterpart: D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD. + ATTACHMENT_LOAD_OP_DISCARD +}; + + +/// Render pass attachment store operation +/// Vulkan counterpart: [VkAttachmentStoreOp](https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VkAttachmentStoreOp). +/// D3D12 counterpart: [D3D12_RENDER_PASS_ENDING_ACCESS_TYPE](https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_render_pass_ending_access_type). +DILIGENT_TYPED_ENUM(ATTACHMENT_STORE_OP, Uint8) +{ + /// The contents generated during the render pass and within the render area are written to memory. + /// Vulkan counterpart: VK_ATTACHMENT_STORE_OP_STORE. + /// D3D12 counterpart: D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE. + ATTACHMENT_STORE_OP_STORE = 0, + + /// The contents within the render area are not needed after rendering, and may be discarded; + /// the contents of the attachment will be undefined inside the render area. + /// Vulkan counterpart: VK_ATTACHMENT_STORE_OP_DONT_CARE. + /// D3D12 counterpart: D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_DISCARD. + ATTACHMENT_STORE_OP_DISCARD +}; + + + +/// Render pass attachment description. +struct RenderPassAttachmentDesc +{ + /// The format of the texture view that will be used for the attachment. + TEXTURE_FORMAT Format DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); + + /// The number of samples in the texture. + Uint8 SampleCount DEFAULT_INITIALIZER(1); + + /// Load operation that specifies how the contents of color and depth components of + /// the attachment are treated at the beginning of the subpass where it is first used. + ATTACHMENT_LOAD_OP LoadOp DEFAULT_INITIALIZER(ATTACHMENT_LOAD_OP_LOAD); + + /// Store operation how the contents of color and depth components of the attachment + /// are treated at the end of the subpass where it is last used. + ATTACHMENT_STORE_OP StoreOp DEFAULT_INITIALIZER(ATTACHMENT_STORE_OP_STORE); + + /// Load operation that specifies how the contents of the stencil component of the + /// attachment is treated at the beginning of the subpass where it is first used. + /// This value is ignored when the format does not have stencil component. + ATTACHMENT_LOAD_OP StencilLoadOp DEFAULT_INITIALIZER(ATTACHMENT_LOAD_OP_LOAD); + + /// Store operation how the contents of the stencil component of the attachment + /// is treated at the end of the subpass where it is last used. + /// This value is ignored when the format does not have stencil component. + ATTACHMENT_STORE_OP StencilStoreOp DEFAULT_INITIALIZER(ATTACHMENT_STORE_OP_STORE); + + /// The state the attachment texture subresource will be in when a render pass instance begins. + RESOURCE_STATE InitialState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); + + /// The state the attachment texture subresource will be transitioned to when a render pass instance ends. + RESOURCE_STATE FinalState DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); + + +#if DILIGENT_CPP_INTERFACE + /// Tests if two structures are equivalent + + /// \param [in] RHS - reference to the structure to perform comparison with + /// \return + /// - True if all members of the two structures are equal. + /// - False otherwise + bool operator == (const RenderPassAttachmentDesc& RHS)const + { + return Format == RHS.Format && + SampleCount == RHS.SampleCount && + LoadOp == RHS.LoadOp && + StoreOp == RHS.StoreOp && + StencilLoadOp == RHS.StencilLoadOp && + StencilStoreOp == RHS.StencilStoreOp && + InitialState == RHS.InitialState && + FinalState == RHS.FinalState; + } +#endif +}; +typedef struct RenderPassAttachmentDesc RenderPassAttachmentDesc; + +#define ATTACHMENT_UNUSED (~0U) + +/// Attachment reference description. +struct AttachmentReference +{ + /// Either an integer value identifying an attachment at the corresponding index in RenderPassDesc::pAttachments, + /// or ATTACHMENT_UNUSED to signify that this attachment is not used. + Uint32 AttachmentIndex DEFAULT_INITIALIZER(0); + + /// The state of the attachment during the subpass. + RESOURCE_STATE State DEFAULT_INITIALIZER(RESOURCE_STATE_UNKNOWN); + +#if DILIGENT_CPP_INTERFACE + AttachmentReference()noexcept{} + + AttachmentReference(Uint32 _AttachmentIndex, + RESOURCE_STATE _State)noexcept : + AttachmentIndex{_AttachmentIndex}, + State {_State} + {} + + /// Tests if two structures are equivalent + + /// \param [in] RHS - reference to the structure to perform comparison with + /// \return + /// - True if all members of the two structures are equal. + /// - False otherwise + bool operator == (const AttachmentReference& RHS) const + { + return AttachmentIndex == RHS.AttachmentIndex && + State == RHS.State; + } + + bool operator != (const AttachmentReference& RHS) const + { + return !(*this == RHS); + } +#endif +}; +typedef struct AttachmentReference AttachmentReference; + + +/// Render pass subpass decription. +struct SubpassDesc +{ + /// The number of input attachments the subpass uses. + Uint32 InputAttachmentCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of input attachments, see Diligent::AttachmentReference. + const AttachmentReference* pInputAttachments DEFAULT_INITIALIZER(nullptr); + + /// The number of color render target attachments. + Uint32 RenderTargetAttachmentCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of color render target attachments, see Diligent::AttachmentReference. + + /// Each element of the pRenderTargetAttachments array corresponds to an output in the pixel shader, + /// i.e. if the shader declares an output variable decorated with a render target index X, then it uses + /// the attachment provided in pRenderTargetAttachments[X]. If the attachment index is ATTACHMENT_UNUSED, + /// writes to this render target are ignored. + const AttachmentReference* pRenderTargetAttachments DEFAULT_INITIALIZER(nullptr); + + /// Pointer to the array of resolve attachments, see Diligent::AttachmentReference. + + /// If pResolveAttachments is not NULL, each of its elements corresponds to a render target attachment + /// (the element in pRenderTargetAttachments at the same index), and a multisample resolve operation is + /// defined for each attachment. At the end of each subpass, multisample resolve operations read the subpass's + /// color attachments, and resolve the samples for each pixel within the render area to the same pixel location + /// in the corresponding resolve attachments, unless the resolve attachment index is ATTACHMENT_UNUSED. + const AttachmentReference* pResolveAttachments DEFAULT_INITIALIZER(nullptr); + + /// Pointer to the depth-stencil attachment, see Diligent::AttachmentReference. + const AttachmentReference* pDepthStencilAttachment DEFAULT_INITIALIZER(nullptr); + + /// The number of preserve attachments. + Uint32 PreserveAttachmentCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of preserve attachments, see Diligent::AttachmentReference. + const Uint32* pPreserveAttachments DEFAULT_INITIALIZER(nullptr); + +#if DILIGENT_CPP_INTERFACE + /// Tests if two structures are equivalent + + /// \param [in] RHS - reference to the structure to perform comparison with + /// \return + /// - True if all members of the two structures are equal. + /// - False otherwise + bool operator == (const SubpassDesc& RHS)const + { + if (InputAttachmentCount != RHS.InputAttachmentCount || + RenderTargetAttachmentCount != RHS.RenderTargetAttachmentCount || + PreserveAttachmentCount != RHS.PreserveAttachmentCount) + return false; + + for(Uint32 i=0; i < InputAttachmentCount; ++i) + { + if (pInputAttachments[i] != RHS.pInputAttachments[i]) + return false; + } + + for(Uint32 i=0; i < RenderTargetAttachmentCount; ++i) + { + if (pRenderTargetAttachments[i] != RHS.pRenderTargetAttachments[i]) + return false; + } + + if ((pResolveAttachments == nullptr && RHS.pResolveAttachments != nullptr) || + (pResolveAttachments != nullptr && RHS.pResolveAttachments == nullptr)) + return false; + + if (pResolveAttachments != nullptr && RHS.pResolveAttachments != nullptr) + { + for(Uint32 i=0; i < RenderTargetAttachmentCount; ++i) + { + if (pResolveAttachments[i] != RHS.pResolveAttachments[i]) + return false; + } + } + + if ((pDepthStencilAttachment == nullptr && RHS.pDepthStencilAttachment != nullptr) || + (pDepthStencilAttachment != nullptr && RHS.pDepthStencilAttachment == nullptr)) + return false; + + if (pDepthStencilAttachment != nullptr && RHS.pDepthStencilAttachment != nullptr) + { + if (*pDepthStencilAttachment != *RHS.pDepthStencilAttachment) + return false; + } + + if ((pPreserveAttachments == nullptr && RHS.pPreserveAttachments != nullptr) || + (pPreserveAttachments != nullptr && RHS.pPreserveAttachments == nullptr)) + return false; + + if (pPreserveAttachments != nullptr && RHS.pPreserveAttachments != nullptr) + { + for(Uint32 i=0; i < PreserveAttachmentCount; ++i) + { + if (pPreserveAttachments[i] != RHS.pPreserveAttachments[i]) + return false; + } + } + + return true; + } +#endif +}; +typedef struct SubpassDesc SubpassDesc; + + +#define SUBPASS_EXTERNAL (~0U) + +/// Subpass dependency description +struct SubpassDependencyDesc +{ + /// The subpass index of the first subpass in the dependency, or SUBPASS_EXTERNAL. + Uint32 SrcSubpass DEFAULT_INITIALIZER(0); + + /// The subpass index of the second subpass in the dependency, or SUBPASS_EXTERNAL. + Uint32 DstSubpass DEFAULT_INITIALIZER(0); + + /// A bitmask of PIPELINE_STAGE_FLAGS specifying the source stage mask. + PIPELINE_STAGE_FLAGS SrcStageMask DEFAULT_INITIALIZER(PIPELINE_STAGE_FLAG_UNDEFINED); + + /// A bitmask of PIPELINE_STAGE_FLAGS specifying the destination stage mask. + PIPELINE_STAGE_FLAGS DstStageMask DEFAULT_INITIALIZER(PIPELINE_STAGE_FLAG_UNDEFINED); + + /// A bitmask of ACCESS_FLAGS specifying a source access mask. + ACCESS_FLAGS SrcAccessMask DEFAULT_INITIALIZER(ACCESS_FLAG_NONE); + + /// A bitmask of ACCESS_FLAGS specifying a destination access mask. + ACCESS_FLAGS DstAccessMask DEFAULT_INITIALIZER(ACCESS_FLAG_NONE); + +#if DILIGENT_CPP_INTERFACE + /// Tests if two structures are equivalent + + /// \param [in] RHS - reference to the structure to perform comparison with + /// \return + /// - True if all members of the two structures are equal. + /// - False otherwise + bool operator == (const SubpassDependencyDesc& RHS) const + { + return SrcSubpass == RHS.SrcSubpass && + DstSubpass == RHS.DstSubpass && + SrcStageMask == RHS.SrcStageMask && + DstStageMask == RHS.DstStageMask && + SrcAccessMask == RHS.SrcAccessMask && + DstAccessMask == RHS.DstAccessMask; + } + + bool operator != (const SubpassDependencyDesc& RHS) const + { + return !(*this == RHS); + } +#endif +}; +typedef struct SubpassDependencyDesc SubpassDependencyDesc; + +/// Render pass description +struct RenderPassDesc DILIGENT_DERIVE(DeviceObjectAttribs) + + /// The number of attachments used by the render pass. + Uint32 AttachmentCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of subpass attachments, see Diligent::RenderPassAttachmentDesc. + const RenderPassAttachmentDesc* pAttachments DEFAULT_INITIALIZER(nullptr); + + /// The number of subpasses in the render pass. + Uint32 SubpassCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of subpass descriptions, see Diligent::SubpassDesc. + const SubpassDesc* pSubpasses DEFAULT_INITIALIZER(nullptr); + + /// The number of memory dependencies between pairs of subpasses. + Uint32 DependencyCount DEFAULT_INITIALIZER(0); + + /// Pointer to the array of subpass dependencies, see Diligent::SubpassDependencyDesc. + const SubpassDependencyDesc* pDependencies DEFAULT_INITIALIZER(nullptr); +}; +typedef struct RenderPassDesc RenderPassDesc; + + +#if DILIGENT_CPP_INTERFACE + +/// Render pass interface + +/// Render pass has no methods. +class IRenderPass : public IDeviceObject +{ +public: + virtual const RenderPassDesc& GetDesc() const override = 0; +}; + +#else + +struct IRenderPass; + +// C requires that a struct or union has at least one member +//struct IRenderPassMethods +//{ +//}; + +struct IRenderPassVtbl +{ + struct IObjectMethods Object; + struct IDeviceObjectMethods DeviceObject; + //struct IRenderPassMethods RenderPass; +}; + +typedef struct IRenderPass +{ + struct IRenderPassVtbl* pVtbl; +} IRenderPass; + +#endif + +DILIGENT_END_NAMESPACE // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h index eacd35f0..f3df92d3 100644 --- a/Graphics/GraphicsEngine/interface/Shader.h +++ b/Graphics/GraphicsEngine/interface/Shader.h @@ -283,8 +283,10 @@ struct ShaderCreateInfo }; typedef struct ShaderCreateInfo ShaderCreateInfo; +// clang-format off /// Describes shader resource type -DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8){ +DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8) +{ /// Shader resource type is unknown SHADER_RESOURCE_TYPE_UNKNOWN = 0, @@ -304,7 +306,12 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8){ SHADER_RESOURCE_TYPE_BUFFER_UAV, /// Sampler (separate sampler) - SHADER_RESOURCE_TYPE_SAMPLER}; + SHADER_RESOURCE_TYPE_SAMPLER, + + /// Input attachment in a render pass + SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT +}; +// clang-format on /// Shader resource description struct ShaderResourceDesc diff --git a/Graphics/GraphicsEngine/interface/Texture.h b/Graphics/GraphicsEngine/interface/Texture.h index 294bb875..3f61338f 100644 --- a/Graphics/GraphicsEngine/interface/Texture.h +++ b/Graphics/GraphicsEngine/interface/Texture.h @@ -32,6 +32,7 @@ /// \file /// Definition of the Diligent::ITexture interface and related data structures +#include "GraphicsTypes.h" #include "DeviceObject.h" #include "TextureView.h" @@ -42,53 +43,6 @@ DILIGENT_BEGIN_NAMESPACE(Diligent) static const INTERFACE_ID IID_Texture = {0xa64b0e60, 0x1b5e, 0x4cfd,{0xb8, 0x80, 0x66, 0x3a, 0x1a, 0xdc, 0xbe, 0x98}}; -/// Defines optimized depth-stencil clear value. -struct DepthStencilClearValue -{ - /// Depth clear value - Float32 Depth DEFAULT_INITIALIZER(1.f); - /// Stencil clear value - Uint8 Stencil DEFAULT_INITIALIZER(0); - -#if DILIGENT_CPP_INTERFACE - DepthStencilClearValue()noexcept{} - - DepthStencilClearValue(Float32 _Depth, - Uint8 _Stencil)noexcept : - Depth {_Depth }, - Stencil {_Stencil} - {} -#endif -}; -typedef struct DepthStencilClearValue DepthStencilClearValue; - -/// Defines optimized clear value. -struct OptimizedClearValue -{ - /// Format - TEXTURE_FORMAT Format DEFAULT_INITIALIZER(TEX_FORMAT_UNKNOWN); - - /// Render target clear value - Float32 Color[4] DEFAULT_INITIALIZER({}); - - /// Depth stencil clear value - DepthStencilClearValue DepthStencil; - -#if DILIGENT_CPP_INTERFACE - bool operator == (const OptimizedClearValue& rhs)const - { - return Format == rhs.Format && - Color[0] == rhs.Color[0] && - Color[1] == rhs.Color[1] && - Color[2] == rhs.Color[2] && - Color[3] == rhs.Color[3] && - DepthStencil.Depth == rhs.DepthStencil.Depth && - DepthStencil.Stencil == rhs.DepthStencil.Stencil; - } -#endif -}; -typedef struct OptimizedClearValue OptimizedClearValue; - /// Texture description struct TextureDesc DILIGENT_DERIVE(DeviceObjectAttribs) diff --git a/Graphics/GraphicsEngine/src/FramebufferBase.cpp b/Graphics/GraphicsEngine/src/FramebufferBase.cpp new file mode 100644 index 00000000..41943b09 --- /dev/null +++ b/Graphics/GraphicsEngine/src/FramebufferBase.cpp @@ -0,0 +1,245 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "FramebufferBase.hpp" +#include "GraphicsAccessories.hpp" + +namespace Diligent +{ + +void ValidateFramebufferDesc(const FramebufferDesc& Desc) +{ +#define LOG_FRAMEBUFFER_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of framebuffer '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.pRenderPass == nullptr) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("render pass must not be null."); + } + + if (Desc.AttachmentCount != 0 && Desc.ppAttachments == nullptr) + { + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, and attachmentCount is not 0, + // pAttachments must be a valid pointer to an array of attachmentCount valid VkImageView handles. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-flags-02778 + LOG_FRAMEBUFFER_ERROR_AND_THROW("attachment count is not zero, but ppAttachments is null."); + } + + for (Uint32 i = 0; i < Desc.AttachmentCount; ++i) + { + if (Desc.ppAttachments[i] == nullptr) + { + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, and attachmentCount is not 0, + // pAttachments must be a valid pointer to an array of attachmentCount valid VkImageView handles. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-flags-02778 + LOG_FRAMEBUFFER_ERROR_AND_THROW("framebuffer attachment ", i, " is null."); + } + } + + const auto& RPDesc = Desc.pRenderPass->GetDesc(); + if (Desc.AttachmentCount != RPDesc.AttachmentCount) + { + // AttachmentCount must be equal to the attachment count specified in renderPass. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-attachmentCount-00876 + LOG_FRAMEBUFFER_ERROR_AND_THROW("the number of framebuffer attachments (", Desc.AttachmentCount, + ") must be equal to the number of attachments (", RPDesc.AttachmentCount, + ") in the render pass '", RPDesc.Name, "'."); + } + + for (Uint32 i = 0; i < RPDesc.AttachmentCount; ++i) + { + if (Desc.ppAttachments[i] == nullptr) + continue; + + const auto& AttDesc = RPDesc.pAttachments[i]; + const auto& ViewDesc = Desc.ppAttachments[i]->GetDesc(); + const auto& TexDesc = Desc.ppAttachments[i]->GetTexture()->GetDesc(); + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments + // must have been created with a VkFormat value that matches the VkFormat specified by the corresponding + // VkAttachmentDescription in renderPass + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00880 + if (ViewDesc.Format != AttDesc.Format) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") of attachment ", i, + " does not match the format (", GetTextureFormatAttribs(AttDesc.Format).Name, + ") defined by the render pass for the same attachment."); + } + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments must have + // been created with a samples value that matches the samples value specified by the corresponding + // VkAttachmentDescription in renderPass + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00881 + if (TexDesc.SampleCount != AttDesc.SampleCount) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the sample count (", Uint32{TexDesc.SampleCount}, ") of attachment ", i, + " does not match the sample count (", Uint32{AttDesc.SampleCount}, + ") defined by the render pass for the same attachment."); + } + } + + for (Uint32 i = 0; i < RPDesc.SubpassCount; ++i) + { + const auto& Subpass = RPDesc.pSubpasses[i]; + for (Uint32 input_attachment = 0; input_attachment < Subpass.InputAttachmentCount; ++input_attachment) + { + const auto& AttchRef = Subpass.pInputAttachments[input_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Input attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); + + if (Desc.ppAttachments[AttchRef.AttachmentIndex] == nullptr) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("attachment at index ", AttchRef.AttachmentIndex, + " is used as input attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', and must not be null."); + } + + const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that + // is used as an input attachment by renderPass must have been created with a usage value including + // VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00879 + if ((TexDesc.BindFlags & BIND_INPUT_ATTACHMENT) == 0) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + " is used as input attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', but was not created with BIND_INPUT_ATTACHMENT bind flag."); + } + } + + for (Uint32 rt_attachment = 0; rt_attachment < Subpass.RenderTargetAttachmentCount; ++rt_attachment) + { + const auto& AttchRef = Subpass.pRenderTargetAttachments[rt_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Render target attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); + + if (Desc.ppAttachments[AttchRef.AttachmentIndex] == nullptr) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("attachment at index ", AttchRef.AttachmentIndex, + " is used as render target attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', and must not be null."); + } + + const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used + // as a color attachment or resolve attachment by renderPass must have been created with a usage value including + // VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00877 + if ((TexDesc.BindFlags & BIND_RENDER_TARGET) == 0) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + " is used as render target attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', but was not created with BIND_RENDER_TARGET bind flag."); + } + } + + if (Subpass.pResolveAttachments != nullptr) + { + for (Uint32 rslv_attachment = 0; rslv_attachment < Subpass.RenderTargetAttachmentCount; ++rslv_attachment) + { + const auto& AttchRef = Subpass.pResolveAttachments[rslv_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Resolve attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); + + if (Desc.ppAttachments[AttchRef.AttachmentIndex] == nullptr) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("attachment at index ", AttchRef.AttachmentIndex, + " is used as resolve attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', and must not be null."); + } + + const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used + // as a color attachment or resolve attachment by renderPass must have been created with a usage value including + // VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-00877 + if ((TexDesc.BindFlags & BIND_RENDER_TARGET) == 0) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + " is used as resolve attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', but was not created with BIND_RENDER_TARGET bind flag."); + } + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& AttchRef = *Subpass.pDepthStencilAttachment; + if (AttchRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY(AttchRef.AttachmentIndex < Desc.AttachmentCount, + "Depth-stencil attachment index (", AttchRef.AttachmentIndex, ") must be less than the attachment count (", + Desc.AttachmentCount, ") as this is ensured by ValidateRenderPassDesc."); + + if (Desc.ppAttachments[AttchRef.AttachmentIndex] == nullptr) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("attachment at index ", AttchRef.AttachmentIndex, + " is used as detph-stencil attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', and must not be null."); + } + + const auto& TexDesc = Desc.ppAttachments[AttchRef.AttachmentIndex]->GetTexture()->GetDesc(); + + // If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is + // used as a depth/stencil attachment by renderPass must have been created with a usage value including + // VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkFramebufferCreateInfo-pAttachments-02633 + if ((TexDesc.BindFlags & BIND_DEPTH_STENCIL) == 0) + { + LOG_FRAMEBUFFER_ERROR_AND_THROW("the attachment '", TexDesc.Name, "' at index ", AttchRef.AttachmentIndex, + " is used as detph-stencil attachment by subpass ", + i, " of render pass '", RPDesc.Name, + "', but was not created with BIND_DEPTH_STENCIL bind flag."); + } + } + } + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/RenderPassBase.cpp b/Graphics/GraphicsEngine/src/RenderPassBase.cpp new file mode 100644 index 00000000..b6b38dd0 --- /dev/null +++ b/Graphics/GraphicsEngine/src/RenderPassBase.cpp @@ -0,0 +1,316 @@ +/* + * Copyright 2019-2020 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "RenderPassBase.hpp" +#include "GraphicsAccessories.hpp" +#include "Align.hpp" + +namespace Diligent +{ + +void ValidateRenderPassDesc(const RenderPassDesc& Desc) +{ +#define LOG_RENDER_PASS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of render pass '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__) + + if (Desc.AttachmentCount != 0 && Desc.pAttachments == nullptr) + { + // If attachmentCount is not 0, pAttachments must be a valid pointer to an + // array of attachmentCount valid VkAttachmentDescription structures. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pAttachments-parameter + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment count (", Desc.AttachmentCount, ") is not zero, but pAttachments is null."); + } + + if (Desc.SubpassCount == 0) + { + // subpassCount must be greater than 0. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-subpassCount-arraylength + LOG_RENDER_PASS_ERROR_AND_THROW("render pass must have at least one subpass."); + } + if (Desc.pSubpasses == nullptr) + { + // pSubpasses must be a valid pointer to an array of subpassCount valid VkSubpassDescription structures. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pSubpasses-parameter + LOG_RENDER_PASS_ERROR_AND_THROW("pSubpasses must not be null."); + } + + if (Desc.DependencyCount != 0 && Desc.pDependencies == nullptr) + { + // If dependencyCount is not 0, pDependencies must be a valid pointer to an array of + // dependencyCount valid VkSubpassDependency structures. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-pDependencies-parameter + LOG_RENDER_PASS_ERROR_AND_THROW("the dependency count (", Desc.DependencyCount, ") is not zero, but pDependencies is null."); + } + + for (Uint32 i = 0; i < Desc.AttachmentCount; ++i) + { + const auto& Attachment = Desc.pAttachments[i]; + if (Attachment.Format == TEX_FORMAT_UNKNOWN) + LOG_RENDER_PASS_ERROR_AND_THROW("the format of attachment ", i, " is unknown."); + + if (Attachment.SampleCount == 0) + LOG_RENDER_PASS_ERROR_AND_THROW("the sample count of attachment ", i, " is zero."); + + if (!IsPowerOfTwo(Attachment.SampleCount)) + LOG_RENDER_PASS_ERROR_AND_THROW("the sample count (", Uint32{Attachment.SampleCount}, ") of attachment ", i, " is not power of two."); + + const auto& FmtInfo = GetTextureFormatAttribs(Attachment.Format); + if (FmtInfo.ComponentType == COMPONENT_TYPE_DEPTH || + FmtInfo.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL) + { + if (Attachment.InitialState != RESOURCE_STATE_DEPTH_WRITE && + Attachment.InitialState != RESOURCE_STATE_DEPTH_READ && + Attachment.InitialState != RESOURCE_STATE_UNORDERED_ACCESS && + Attachment.InitialState != RESOURCE_STATE_SHADER_RESOURCE && + Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST && + Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE && + Attachment.InitialState != RESOURCE_STATE_COPY_DEST && + Attachment.InitialState != RESOURCE_STATE_COPY_SOURCE && + Attachment.InitialState != RESOURCE_STATE_INPUT_ATTACHMENT) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid."); + } + + if (Attachment.FinalState != RESOURCE_STATE_DEPTH_WRITE && + Attachment.FinalState != RESOURCE_STATE_DEPTH_READ && + Attachment.FinalState != RESOURCE_STATE_UNORDERED_ACCESS && + Attachment.FinalState != RESOURCE_STATE_SHADER_RESOURCE && + Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST && + Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE && + Attachment.FinalState != RESOURCE_STATE_COPY_DEST && + Attachment.FinalState != RESOURCE_STATE_COPY_SOURCE && + Attachment.FinalState != RESOURCE_STATE_INPUT_ATTACHMENT) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the final state of depth-stencil attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid."); + } + } + else + { + if (Attachment.InitialState != RESOURCE_STATE_RENDER_TARGET && + Attachment.InitialState != RESOURCE_STATE_UNORDERED_ACCESS && + Attachment.InitialState != RESOURCE_STATE_SHADER_RESOURCE && + Attachment.InitialState != RESOURCE_STATE_RESOLVE_DEST && + Attachment.InitialState != RESOURCE_STATE_RESOLVE_SOURCE && + Attachment.InitialState != RESOURCE_STATE_COPY_SOURCE && + Attachment.InitialState != RESOURCE_STATE_INPUT_ATTACHMENT && + Attachment.InitialState != RESOURCE_STATE_PRESENT) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the initial state of color attachment ", i, " (", GetResourceStateString(Attachment.InitialState), ") is invalid."); + } + + if (Attachment.FinalState != RESOURCE_STATE_RENDER_TARGET && + Attachment.FinalState != RESOURCE_STATE_UNORDERED_ACCESS && + Attachment.FinalState != RESOURCE_STATE_SHADER_RESOURCE && + Attachment.FinalState != RESOURCE_STATE_RESOLVE_DEST && + Attachment.FinalState != RESOURCE_STATE_RESOLVE_SOURCE && + Attachment.FinalState != RESOURCE_STATE_COPY_SOURCE && + Attachment.FinalState != RESOURCE_STATE_INPUT_ATTACHMENT && + Attachment.FinalState != RESOURCE_STATE_PRESENT) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the final state of color attachment ", i, " (", GetResourceStateString(Attachment.FinalState), ") is invalid."); + } + } + } + + for (Uint32 subpass = 0; subpass < Desc.SubpassCount; ++subpass) + { + const auto& Subpass = Desc.pSubpasses[subpass]; + if (Subpass.InputAttachmentCount != 0 && Subpass.pInputAttachments == nullptr) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the input attachment count (", Subpass.InputAttachmentCount, ") of subpass ", subpass, + " is not zero, while pInputAttachments is null."); + } + if (Subpass.RenderTargetAttachmentCount != 0 && Subpass.pRenderTargetAttachments == nullptr) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the render target attachment count (", Subpass.RenderTargetAttachmentCount, ") of subpass ", subpass, + " is not zero, while pRenderTargetAttachments is null."); + } + if (Subpass.PreserveAttachmentCount != 0 && Subpass.pPreserveAttachments == nullptr) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the preserve attachment count (", Subpass.PreserveAttachmentCount, ") of subpass ", subpass, + " is not zero, while pPreserveAttachments is null."); + } + + for (Uint32 input_attachment = 0; input_attachment < Subpass.InputAttachmentCount; ++input_attachment) + { + const auto& AttchRef = Subpass.pInputAttachments[input_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of input attachment reference ", input_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + for (Uint32 rt_attachment = 0; rt_attachment < Subpass.RenderTargetAttachmentCount; ++rt_attachment) + { + const auto& AttchRef = Subpass.pRenderTargetAttachments[rt_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of render target attachment reference ", rt_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + if (Subpass.pResolveAttachments != nullptr) + { + for (Uint32 rslv_attachment = 0; rslv_attachment < Subpass.RenderTargetAttachmentCount; ++rslv_attachment) + { + const auto& AttchRef = Subpass.pResolveAttachments[rslv_attachment]; + if (AttchRef.AttachmentIndex == ATTACHMENT_UNUSED) + continue; + + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of resolve attachment reference ", rslv_attachment, + " of subpass ", subpass, " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& AttchRef = *Subpass.pDepthStencilAttachment; + if (AttchRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + // If the attachment member of any element of pInputAttachments, pColorAttachments, pResolveAttachments + // or pDepthStencilAttachment, or any element of pPreserveAttachments in any element of pSubpasses is not + // VK_ATTACHMENT_UNUSED, it must be less than attachmentCount + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkRenderPassCreateInfo-attachment-00834 + if (AttchRef.AttachmentIndex >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", AttchRef.AttachmentIndex, ") of depth-stencil attachment reference of subpass ", subpass, + " must be less than the number of attachments (", Desc.AttachmentCount, ")."); + } + } + } + + for (Uint32 prsv_attachment = 0; prsv_attachment < Subpass.PreserveAttachmentCount; ++prsv_attachment) + { + const auto PrsvAttachment = Subpass.pPreserveAttachments[prsv_attachment]; + if (PrsvAttachment == ATTACHMENT_UNUSED) + { + // The attachment member of each element of pPreserveAttachments must not be VK_ATTACHMENT_UNUSED + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-attachment-00853 + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index of preserve attachment reference ", prsv_attachment, + " of subpass ", subpass, " is ATTACHMENT_UNUSED."); + } + + if (PrsvAttachment >= Desc.AttachmentCount) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the attachment index (", PrsvAttachment, ") of preserve attachment reference ", prsv_attachment, + " of subpass ", subpass, " exceeds the number of attachments (", Desc.AttachmentCount, ")."); + } + } + + if (Subpass.pResolveAttachments != nullptr) + { + for (Uint32 attchmnt = 0; attchmnt < Subpass.RenderTargetAttachmentCount; ++attchmnt) + { + const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[attchmnt]; + const auto& RslvAttachmentRef = Subpass.pResolveAttachments[attchmnt]; + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && RTAttachmentRef.AttachmentIndex == ATTACHMENT_UNUSED) + { + // If pResolveAttachments is not NULL, for each resolve attachment that is not VK_ATTACHMENT_UNUSED, + // the corresponding color attachment must not be VK_ATTACHMENT_UNUSED + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00847 + LOG_RENDER_PASS_ERROR_AND_THROW("pResolveAttachments of subpass ", subpass, " is not null and resolve attachment reference ", attchmnt, + " is not ATTACHMENT_UNUSED, but corresponding render target attachment reference is ATTACHMENT_UNUSED."); + } + + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && Desc.pAttachments[RTAttachmentRef.AttachmentIndex].SampleCount == 1) + { + // If pResolveAttachments is not NULL, for each resolve attachment that is not VK_ATTACHMENT_UNUSED, + // the corresponding color attachment must not have a sample count of VK_SAMPLE_COUNT_1_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00848 + LOG_RENDER_PASS_ERROR_AND_THROW("Render target attachment at index ", RTAttachmentRef.AttachmentIndex, " referenced by", + " attachment reference ", attchmnt, " of subpass ", subpass, + " is used as the source of resolve operation, but its sample count is 1."); + } + + if (RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].SampleCount != 1) + { + // If pResolveAttachments is not NULL, each resolve attachment that is not VK_ATTACHMENT_UNUSED must + // have a sample count of VK_SAMPLE_COUNT_1_BIT + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00849 + LOG_RENDER_PASS_ERROR_AND_THROW("Resolve attachment at index ", RslvAttachmentRef.AttachmentIndex, " referenced by", + " attachment reference ", attchmnt, " of subpass ", subpass, + " must have sample count of 1."); + } + + if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && RslvAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED && + Desc.pAttachments[RTAttachmentRef.AttachmentIndex].Format != Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].Format) + { + // If pResolveAttachments is not NULL, each resolve attachment that is not VK_ATTACHMENT_UNUSED + // must have the same VkFormat as its corresponding color attachment. + // https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-VkSubpassDescription-pResolveAttachments-00850 + LOG_RENDER_PASS_ERROR_AND_THROW("The format (", + GetTextureFormatAttribs(Desc.pAttachments[RTAttachmentRef.AttachmentIndex].Format).Name, + ") of render target attachment at index ", RTAttachmentRef.AttachmentIndex, + " referenced by attachment reference ", attchmnt, " of subpass ", subpass, + " does not match the format (", + GetTextureFormatAttribs(Desc.pAttachments[RslvAttachmentRef.AttachmentIndex].Format).Name, + ") of the corresponding resolve attachment at index ", + RslvAttachmentRef.AttachmentIndex, "."); + } + } + } + } + + for (Uint32 i = 0; i < Desc.DependencyCount; ++i) + { + const auto& Dependency = Desc.pDependencies[i]; + + if (Dependency.SrcStageMask == PIPELINE_STAGE_FLAG_UNDEFINED) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the source stage mask of subpass dependency ", i, " is undefined."); + } + if (Dependency.DstStageMask == PIPELINE_STAGE_FLAG_UNDEFINED) + { + LOG_RENDER_PASS_ERROR_AND_THROW("the destination stage mask of subpass dependency ", i, " is undefined."); + } + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngine/src/ResourceMapping.cpp b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp index bf34056c..bf34056c 100644 --- a/Graphics/GraphicsEngine/src/ResourceMapping.cpp +++ b/Graphics/GraphicsEngine/src/ResourceMappingBase.cpp diff --git a/Graphics/GraphicsEngine/src/Texture.cpp b/Graphics/GraphicsEngine/src/TextureBase.cpp index 4cfdbd0b..e7073aae 100644 --- a/Graphics/GraphicsEngine/src/Texture.cpp +++ b/Graphics/GraphicsEngine/src/TextureBase.cpp @@ -34,7 +34,7 @@ namespace Diligent void ValidateTextureDesc(const TextureDesc& Desc) { -#define LOG_TEXTURE_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Texture \"", Desc.Name ? Desc.Name : "", "\": ", ##__VA_ARGS__) +#define LOG_TEXTURE_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Texture '", (Desc.Name ? Desc.Name : ""), "': ", ##__VA_ARGS__) if (Desc.Type == RESOURCE_DIM_UNDEFINED) { @@ -90,7 +90,7 @@ void ValidateTextureDesc(const TextureDesc& Desc) MaxDim = std::max(Desc.Width, Desc.Height); else if (Desc.Type == RESOURCE_DIM_TEX_3D) MaxDim = std::max(std::max(Desc.Width, Desc.Height), Desc.Depth); - VERIFY(MaxDim >= (1U << (Desc.MipLevels - 1)), "Texture \"", Desc.Name ? Desc.Name : "", "\": Incorrect number of Mip levels (", Desc.MipLevels, ")"); + VERIFY(MaxDim >= (1U << (Desc.MipLevels - 1)), "Texture '", Desc.Name ? Desc.Name : "", "': Incorrect number of Mip levels (", Desc.MipLevels, ")"); if (Desc.SampleCount > 1) { @@ -138,7 +138,7 @@ void ValidateTextureRegion(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 S { \ if (!(Expr)) \ { \ - LOG_ERROR("Texture \"", TexDesc.Name ? TexDesc.Name : "", "\": ", ##__VA_ARGS__); \ + LOG_ERROR("Texture '", (TexDesc.Name ? TexDesc.Name : ""), "': ", ##__VA_ARGS__); \ } \ } while (false) diff --git a/Graphics/GraphicsEngine/src/pch.cpp b/Graphics/GraphicsEngine/src/pch.cpp deleted file mode 100644 index 07ab47d2..00000000 --- a/Graphics/GraphicsEngine/src/pch.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright 2015-2018 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -// stdafx.cpp : source file that includes just the standard includes -// RenderEngine.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "pch.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file |
