summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngine
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-08-15 22:42:13 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-08-15 22:42:13 +0000
commitdf3a2c7c744eae194c79187a59914c6662f69b52 (patch)
tree6f67919092b671b4a0fb637db26f75293f849886 /Graphics/GraphicsEngine
parentFixed Visual Studio 16.7 build error (diff)
parentVk backend: not setting render pass in SetPipelineState (diff)
downloadDiligentCore-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')
-rw-r--r--Graphics/GraphicsEngine/CMakeLists.txt10
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp305
-rw-r--r--Graphics/GraphicsEngine/include/FramebufferBase.hpp136
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp100
-rw-r--r--Graphics/GraphicsEngine/include/RenderDeviceBase.hpp32
-rw-r--r--Graphics/GraphicsEngine/include/RenderPassBase.hpp278
-rw-r--r--Graphics/GraphicsEngine/include/TextureBase.hpp9
-rw-r--r--Graphics/GraphicsEngine/interface/APIInfo.h2
-rw-r--r--Graphics/GraphicsEngine/interface/DeviceContext.h55
-rw-r--r--Graphics/GraphicsEngine/interface/Framebuffer.h102
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h375
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h45
-rw-r--r--Graphics/GraphicsEngine/interface/RenderDevice.h27
-rw-r--r--Graphics/GraphicsEngine/interface/RenderPass.h398
-rw-r--r--Graphics/GraphicsEngine/interface/Shader.h11
-rw-r--r--Graphics/GraphicsEngine/interface/Texture.h48
-rw-r--r--Graphics/GraphicsEngine/src/FramebufferBase.cpp245
-rw-r--r--Graphics/GraphicsEngine/src/RenderPassBase.cpp316
-rw-r--r--Graphics/GraphicsEngine/src/ResourceMappingBase.cpp (renamed from Graphics/GraphicsEngine/src/ResourceMapping.cpp)0
-rw-r--r--Graphics/GraphicsEngine/src/TextureBase.cpp (renamed from Graphics/GraphicsEngine/src/Texture.cpp)6
-rw-r--r--Graphics/GraphicsEngine/src/pch.cpp31
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