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