summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-07-02 00:08:59 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-07-02 00:08:59 +0000
commit354898decf45d32a09d9b4a15319413a5d199f2a (patch)
tree61e46f6cb4fc324338903c79292c9c995e3f67ef /Graphics/GraphicsEngineVulkan
parentReworked how render targets are bound in Vulkan: added RenderPass cache (diff)
downloadDiligentCore-354898decf45d32a09d9b4a15319413a5d199f2a.tar.gz
DiligentCore-354898decf45d32a09d9b4a15319413a5d199f2a.zip
Reworked binding default frame buffer to keep references to current RTV and DSV instead of nulls.
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h16
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp267
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp30
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp87
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp5
6 files changed, 209 insertions, 205 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
index 6fce88a9..6d68758f 100644
--- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h
@@ -58,7 +58,13 @@ public:
virtual void SetWindowedMode()override final;
virtual VkSwapchainKHR GetVkSwapChain()override final{ return m_VkSwapChain; }
- virtual ITextureViewVk* GetCurrentBackBufferRTV()override final;
+
+ virtual ITextureViewVk* GetCurrentBackBufferRTV()override final
+ {
+ VERIFY_EXPR(m_BackBufferIndex >= 0 && m_BackBufferIndex < m_SwapChainDesc.BufferCount);
+ return m_pBackBufferRTV[m_BackBufferIndex];
+ }
+
virtual ITextureViewVk* GetDepthBufferDSV()override final{return m_pDepthBufferDSV;}
private:
@@ -67,13 +73,15 @@ private:
void AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk);
std::shared_ptr<const VulkanUtilities::VulkanInstance> m_VulkanInstance;
- VkSurfaceKHR m_VkSurface = VK_NULL_HANDLE;
- VkSwapchainKHR m_VkSwapChain = VK_NULL_HANDLE;
- VkFormat m_VkColorFormat = VK_FORMAT_UNDEFINED;
+ VkSurfaceKHR m_VkSurface = VK_NULL_HANDLE;
+ VkSwapchainKHR m_VkSwapChain = VK_NULL_HANDLE;
+ VkFormat m_VkColorFormat = VK_FORMAT_UNDEFINED;
std::vector<VulkanUtilities::SemaphoreWrapper> m_ImageAcquiredSemaphores;
std::vector<VulkanUtilities::SemaphoreWrapper> m_DrawCompleteSemaphores;
std::vector< RefCntAutoPtr<ITextureViewVk>, STDAllocatorRawMem<RefCntAutoPtr<ITextureViewVk>> > m_pBackBufferRTV;
+ std::vector<bool, STDAllocatorRawMem<bool> > m_SwapChainImagesInitialized;
+
RefCntAutoPtr<ITextureViewVk> m_pDepthBufferDSV;
Uint32 m_SemaphoreIndex = 0;
uint32_t m_BackBufferIndex = 0;
diff --git a/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h b/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
index 89294efb..12372fcf 100644
--- a/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/SwapChainVk.h
@@ -45,15 +45,6 @@ public:
/// Returns a handle to the Vulkan swap chain object.
virtual VkSwapchainKHR GetVkSwapChain() = 0;
-
- /// Returns a pointer to the render target view of the current back buffer in the swap chain
- virtual ITextureViewVk* GetCurrentBackBufferRTV() = 0;
-
- /// Returns a pointer to the depth-stencil view of the depth buffer
-
- /// The method does *NOT* call AddRef() on the returned interface,
- /// so Release() must not be called.
- virtual ITextureViewVk* GetDepthBufferDSV() = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 31015257..43f25a74 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -502,7 +502,7 @@ namespace Diligent
{
if (m_pSwapChain)
{
- pVkDSV = m_pSwapChain.RawPtr<ISwapChainVk>()->GetDepthBufferDSV();
+ pVkDSV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetDepthBufferDSV());
}
else
{
@@ -511,44 +511,41 @@ namespace Diligent
}
}
- auto *pTexture = pVkDSV->GetTexture();
- auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
- const auto &ViewDesc = pVkDSV->GetDesc();
EnsureVkCmdBuffer();
- bool ClearedAsAttachment = false;
- if(m_RenderPass != VK_NULL_HANDLE)
- {
- if(m_IsDefaultFramebufferBound && pView == nullptr || pView == m_pBoundDepthStencil)
- {
- CommitRenderPassAndFramebuffer();
- VkClearAttachment ClearAttachment = {};
- ClearAttachment.aspectMask = 0;
- if (ClearFlags & CLEAR_DEPTH_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
- if (ClearFlags & CLEAR_STENCIL_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
- // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask
- ClearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
- ClearAttachment.clearValue.depthStencil.depth = fDepth;
- ClearAttachment.clearValue.depthStencil.stencil = Stencil;
- VkClearRect ClearRect;
- ClearRect.rect = { { 0,0 },{ m_FramebufferWidth, m_FramebufferHeight } };
- ClearRect.baseArrayLayer = ViewDesc.FirstArraySlice;
- ClearRect.layerCount = ViewDesc.NumArraySlices;
- // No memory barriers are needed between vkCmdClearAttachments and preceding or
- // subsequent draw or attachment clear commands in the same subpass (17.2)
- m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
- ClearedAsAttachment = true;
- }
- else
- {
- // End render pass to clear the buffer with vkCmdClearDepthStencilImage
- if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
- }
+ const auto& ViewDesc = pVkDSV->GetDesc();
+
+ if(pVkDSV == m_pBoundDepthStencil)
+ {
+ // Render pass may not be currently committed
+ VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE);
+ CommitRenderPassAndFramebuffer();
+
+ VkClearAttachment ClearAttachment = {};
+ ClearAttachment.aspectMask = 0;
+ if (ClearFlags & CLEAR_DEPTH_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ if (ClearFlags & CLEAR_STENCIL_FLAG) ClearAttachment.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask
+ ClearAttachment.colorAttachment = VK_ATTACHMENT_UNUSED;
+ ClearAttachment.clearValue.depthStencil.depth = fDepth;
+ ClearAttachment.clearValue.depthStencil.stencil = Stencil;
+ VkClearRect ClearRect;
+ ClearRect.rect = { { 0,0 },{ m_FramebufferWidth, m_FramebufferHeight } };
+ ClearRect.baseArrayLayer = ViewDesc.FirstArraySlice;
+ ClearRect.layerCount = ViewDesc.NumArraySlices;
+ // No memory barriers are needed between vkCmdClearAttachments and preceding or
+ // subsequent draw or attachment clear commands in the same subpass (17.2)
+ m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
}
-
- if(!ClearedAsAttachment)
+ else
{
+ // End render pass to clear the buffer with vkCmdClearDepthStencilImage
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
+
+ auto* pTexture = pVkDSV->GetTexture();
+ auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+
// Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
TransitionImageLayout(pTexture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkClearDepthStencilValue ClearValue;
@@ -594,7 +591,7 @@ namespace Diligent
void DeviceContextVkImpl::ClearRenderTarget( ITextureView *pView, const float *RGBA )
{
- ITextureViewVk *pVkRTV = nullptr;
+ ITextureViewVk* pVkRTV = nullptr;
if( pView != nullptr )
{
#ifdef _DEBUG
@@ -607,7 +604,7 @@ namespace Diligent
{
if (m_pSwapChain)
{
- pVkRTV = m_pSwapChain.RawPtr<ISwapChainVk>()->GetCurrentBackBufferRTV();
+ pVkRTV = ValidatedCast<ITextureViewVk>(m_pSwapChain->GetCurrentBackBufferRTV());
}
else
{
@@ -620,62 +617,53 @@ namespace Diligent
if( RGBA == nullptr )
RGBA = Zero;
- auto *pTexture = pVkRTV->GetTexture();
- auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
- const auto &ViewDesc = pVkRTV->GetDesc();
EnsureVkCmdBuffer();
- bool ClearedAsAttachment = false;
- if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ const auto& ViewDesc = pVkRTV->GetDesc();
+
+ // Check if the texture is one of the currently bound render targets
+ static constexpr const Uint32 InvalidAttachmentIndex = static_cast<Uint32>(-1);
+ Uint32 attachmentIndex = InvalidAttachmentIndex;
+ for(Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
{
- static constexpr Uint32 InvalidAttachmentIndex = static_cast<Uint32>(-1);
- Uint32 attachmentIndex = InvalidAttachmentIndex;
- if(pView == nullptr)
- {
- if(m_IsDefaultFramebufferBound)
- attachmentIndex = 0;
- }
- else
- {
- for(Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
- {
- if(m_pBoundRenderTargets[rt] == pView)
- {
- attachmentIndex = rt;
- break;
- }
- }
- }
-
- if(attachmentIndex != InvalidAttachmentIndex)
- {
- VkClearAttachment ClearAttachment = {};
- ClearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask,
- // in which case it is an index to the pColorAttachments array in the VkSubpassDescription
- // structure of the current subpass which selects the color attachment to clear (17.2)
- // It is NOT the render pass attachment index
- ClearAttachment.colorAttachment = attachmentIndex;
- ClearAttachment.clearValue.color = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
- VkClearRect ClearRect;
- ClearRect.rect = {{0,0}, {m_FramebufferWidth, m_FramebufferHeight}};
- ClearRect.baseArrayLayer = ViewDesc.FirstArraySlice;
- ClearRect.layerCount = ViewDesc.NumArraySlices;
- // No memory barriers are needed between vkCmdClearAttachments and preceding or
- // subsequent draw or attachment clear commands in the same subpass (17.2)
- m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
- ClearedAsAttachment = true;
- }
- else
+ if(m_pBoundRenderTargets[rt] == pVkRTV)
{
- // End current render pass and clear the image with vkCmdClearColorImage
- if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
+ attachmentIndex = rt;
+ break;
}
}
-
- if(!ClearedAsAttachment)
+
+ if(attachmentIndex != InvalidAttachmentIndex)
{
+ // Render pass may not be currently committed
+ VERIFY_EXPR(m_RenderPass != VK_NULL_HANDLE);
+ CommitRenderPassAndFramebuffer();
+
+ VkClearAttachment ClearAttachment = {};
+ ClearAttachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ // colorAttachment is only meaningful if VK_IMAGE_ASPECT_COLOR_BIT is set in aspectMask,
+ // in which case it is an index to the pColorAttachments array in the VkSubpassDescription
+ // structure of the current subpass which selects the color attachment to clear (17.2)
+ // It is NOT the render pass attachment index
+ ClearAttachment.colorAttachment = attachmentIndex;
+ ClearAttachment.clearValue.color = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
+ VkClearRect ClearRect;
+ ClearRect.rect = {{0,0}, {m_FramebufferWidth, m_FramebufferHeight}};
+ ClearRect.baseArrayLayer = ViewDesc.FirstArraySlice;
+ ClearRect.layerCount = ViewDesc.NumArraySlices;
+ // No memory barriers are needed between vkCmdClearAttachments and preceding or
+ // subsequent draw or attachment clear commands in the same subpass (17.2)
+ m_CommandBuffer.ClearAttachment(ClearAttachment, ClearRect);
+ }
+ else
+ {
+ // End current render pass and clear the image with vkCmdClearColorImage
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
+
+ auto* pTexture = pVkRTV->GetTexture();
+ auto* pTextureVk = ValidatedCast<TextureVkImpl>(pTexture);
+
// Image layout must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL (17.1)
TransitionImageLayout(pTexture, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
auto ClearValue = ClearValueToVkClearValue(RGBA, ViewDesc.Format);
@@ -886,34 +874,20 @@ namespace Diligent
if(m_RenderPass != VK_NULL_HANDLE)
{
VERIFY_EXPR(m_Framebuffer != VK_NULL_HANDLE);
- if(m_IsDefaultFramebufferBound)
+ if(m_pBoundDepthStencil)
{
- auto* pSwapChainVk = m_pSwapChain.RawPtr<ISwapChainVk>();
- auto* pDefaultDSV = pSwapChainVk->GetDepthBufferDSV();
- auto* pDefaultDepthImage = pDefaultDSV->GetTexture();
- TransitionImageLayout(pDefaultDepthImage, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
-
- auto* pDefaultRTV = pSwapChainVk->GetCurrentBackBufferRTV();
- auto* pDefaultBackBuffer = pDefaultRTV->GetTexture();
- TransitionImageLayout(pDefaultBackBuffer, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
+ auto* pDSVVk = m_pBoundDepthStencil.RawPtr<TextureViewVkImpl>();
+ auto* pDepthBuffer = pDSVVk->GetTexture();
+ TransitionImageLayout(pDepthBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
- else
- {
- if(m_pBoundDepthStencil)
- {
- auto* pDSVVk = m_pBoundDepthStencil.RawPtr<TextureViewVkImpl>();
- auto* pDepthBuffer = pDSVVk->GetTexture();
- TransitionImageLayout(pDepthBuffer, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- }
- for(Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
+ for(Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ if(ITextureView* pRTV = m_pBoundRenderTargets[rt])
{
- if(ITextureView* pRTV = m_pBoundRenderTargets[rt])
- {
- auto* pRTVVk = ValidatedCast<TextureViewVkImpl>(pRTV);
- auto* pRenderTarget = pRTVVk->GetTexture();
- TransitionImageLayout(pRenderTarget, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- }
+ auto* pRTVVk = ValidatedCast<TextureViewVkImpl>(pRTV);
+ auto* pRenderTarget = pRTVVk->GetTexture();
+ TransitionImageLayout(pRenderTarget, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
}
}
m_CommandBuffer.BeginRenderPass(m_RenderPass, m_Framebuffer, m_FramebufferWidth, m_FramebufferHeight);
@@ -927,61 +901,40 @@ namespace Diligent
{
FramebufferCache::FramebufferCacheKey FBKey;
RenderPassCache::RenderPassCacheKey RenderPassKey;
- if(m_IsDefaultFramebufferBound)
+ if(m_pBoundDepthStencil)
{
- auto* pSwapChainVk = m_pSwapChain.RawPtr<ISwapChainVk>();
- auto* pDefaultDSV = pSwapChainVk->GetDepthBufferDSV();
- auto* pDefaultDepthImage = pDefaultDSV->GetTexture();
- FBKey.DSV = pDefaultDSV->GetVulkanImageView();
- RenderPassKey.DSVFormat = pDefaultDSV->GetDesc().Format;
-
-
- auto* pDefaultRTV = pSwapChainVk->GetCurrentBackBufferRTV();
- auto* pDefaultBackBuffer = pDefaultRTV->GetTexture();
- FBKey.NumRenderTargets = 1;
- FBKey.RTVs[0] = pDefaultRTV->GetVulkanImageView();
- RenderPassKey.NumRenderTargets = 1;
- RenderPassKey.RTVFormats[0] = pDefaultRTV->GetDesc().Format;
- RenderPassKey.SampleCount = static_cast<Uint8>(pDefaultBackBuffer->GetDesc().SampleCount);
- VERIFY_EXPR(RenderPassKey.SampleCount == pDefaultDepthImage->GetDesc().SampleCount);
+ auto* pDSVVk = m_pBoundDepthStencil.RawPtr<TextureViewVkImpl>();
+ auto* pDepthBuffer = pDSVVk->GetTexture();
+ FBKey.DSV = pDSVVk->GetVulkanImageView();
+ RenderPassKey.DSVFormat = pDSVVk->GetDesc().Format;
+ RenderPassKey.SampleCount = static_cast<Uint8>(pDepthBuffer->GetDesc().SampleCount);
}
else
{
- if(m_pBoundDepthStencil)
- {
- auto* pDSVVk = m_pBoundDepthStencil.RawPtr<TextureViewVkImpl>();
- auto* pDepthBuffer = pDSVVk->GetTexture();
- FBKey.DSV = pDSVVk->GetVulkanImageView();
- RenderPassKey.DSVFormat = pDSVVk->GetDesc().Format;
- RenderPassKey.SampleCount = static_cast<Uint8>(pDepthBuffer->GetDesc().SampleCount);
- }
- else
- {
- FBKey.DSV = nullptr;
- RenderPassKey.DSVFormat = TEX_FORMAT_UNKNOWN;
- }
+ FBKey.DSV = nullptr;
+ RenderPassKey.DSVFormat = TEX_FORMAT_UNKNOWN;
+ }
- FBKey.NumRenderTargets = m_NumBoundRenderTargets;
- RenderPassKey.NumRenderTargets = static_cast<Uint8>(m_NumBoundRenderTargets);
+ FBKey.NumRenderTargets = m_NumBoundRenderTargets;
+ RenderPassKey.NumRenderTargets = static_cast<Uint8>(m_NumBoundRenderTargets);
- for(Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
+ for(Uint32 rt=0; rt < m_NumBoundRenderTargets; ++rt)
+ {
+ if(ITextureView* pRTV = m_pBoundRenderTargets[rt])
{
- if(ITextureView* pRTV = m_pBoundRenderTargets[rt])
- {
- auto* pRTVVk = ValidatedCast<TextureViewVkImpl>(pRTV);
- auto* pRenderTarget = pRTVVk->GetTexture();
- FBKey.RTVs[rt] = pRTVVk->GetVulkanImageView();
- RenderPassKey.RTVFormats[rt] = pRenderTarget->GetDesc().Format;
- if(RenderPassKey.SampleCount == 0)
- RenderPassKey.SampleCount = static_cast<Uint8>(pRenderTarget->GetDesc().SampleCount);
- else
- VERIFY(RenderPassKey.SampleCount == pRenderTarget->GetDesc().SampleCount, "Inconsistent sample count");
- }
+ auto* pRTVVk = ValidatedCast<TextureViewVkImpl>(pRTV);
+ auto* pRenderTarget = pRTVVk->GetTexture();
+ FBKey.RTVs[rt] = pRTVVk->GetVulkanImageView();
+ RenderPassKey.RTVFormats[rt] = pRenderTarget->GetDesc().Format;
+ if(RenderPassKey.SampleCount == 0)
+ RenderPassKey.SampleCount = static_cast<Uint8>(pRenderTarget->GetDesc().SampleCount);
else
- {
- FBKey.RTVs[rt] = nullptr;
- RenderPassKey.RTVFormats[rt] = TEX_FORMAT_UNKNOWN;
- }
+ VERIFY(RenderPassKey.SampleCount == pRenderTarget->GetDesc().SampleCount, "Inconsistent sample count");
+ }
+ else
+ {
+ FBKey.RTVs[rt] = nullptr;
+ RenderPassKey.RTVFormats[rt] = TEX_FORMAT_UNKNOWN;
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index 91db6b49..23da8e2d 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -39,7 +39,8 @@ SwapChainVkImpl::SwapChainVkImpl(IReferenceCounters* pRefCounters,
void* pNativeWndHandle) :
TSwapChainBase(pRefCounters, pRenderDeviceVk, pDeviceContextVk, SCDesc),
m_VulkanInstance(pRenderDeviceVk->GetVulkanInstance()),
- m_pBackBufferRTV(STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<ITextureView>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<ITextureView>>"))
+ m_pBackBufferRTV(STD_ALLOCATOR_RAW_MEM(RefCntAutoPtr<ITextureView>, GetRawAllocator(), "Allocator for vector<RefCntAutoPtr<ITextureView>>")),
+ m_SwapChainImagesInitialized(STD_ALLOCATOR_RAW_MEM(bool, GetRawAllocator(), "Allocator for vector<bool>"))
{
// Create OS-specific surface
#if defined(VK_USE_PLATFORM_WIN32_KHR)
@@ -341,6 +342,7 @@ void SwapChainVkImpl::InitBuffersAndViews()
#endif
m_pBackBufferRTV.resize(m_SwapChainDesc.BufferCount);
+ m_SwapChainImagesInitialized.resize(m_pBackBufferRTV.size(), false);
uint32_t swapchainImageCount = m_SwapChainDesc.BufferCount;
std::vector<VkImage> swapchainImages(swapchainImageCount);
@@ -392,9 +394,9 @@ void SwapChainVkImpl::InitBuffersAndViews()
m_pDepthBufferDSV = RefCntAutoPtr<ITextureViewVk>(pDSV, IID_TextureViewVk);
}
-void SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl *pDeviceCtxVk)
+void SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
{
- auto *pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
+ auto* pDeviceVk = m_pRenderDevice.RawPtr<RenderDeviceVkImpl>();
const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
auto res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, m_ImageAcquiredSemaphores[m_SemaphoreIndex], (VkFence)nullptr, &m_BackBufferIndex);
@@ -403,6 +405,13 @@ void SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl *pDeviceCtxVk)
// Next command in the device context must wait for the next image to be acquired
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2)
pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
+ if (!m_SwapChainImagesInitialized[m_BackBufferIndex])
+ {
+ // Vulkan validation layers do not like uninitialized memory.
+ // Clear back buffer first time we acquire it. This will use vkCmdClearColorImage()
+ pDeviceCtxVk->ClearRenderTarget(GetCurrentBackBufferRTV(), nullptr);
+ m_SwapChainImagesInitialized[m_BackBufferIndex] = true;
+ }
}
IMPLEMENT_QUERY_INTERFACE( SwapChainVkImpl, IID_SwapChainVk, TSwapChainBase )
@@ -425,7 +434,6 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
//VERIFY(pImmediateCtxVk->GetNumCommandsInCtx() != 0, "The context must not be flushed");
pImmediateCtxVk->AddSignalSemaphore(m_DrawCompleteSemaphores[m_SemaphoreIndex]);
pImmediateCtxVk->Flush();
- pImmediateCtxVk->ResetRenderTargets();
VkPresentInfoKHR PresentInfo = {};
PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@@ -461,6 +469,13 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
m_SemaphoreIndex = 0;
AcquireNextImage(pImmediateCtxVk);
+
+ if(pImmediateCtxVk->IsDefaultFBBound())
+ {
+ // If default framebuffer is bound, we need to call SetRenderTargets()
+ // to bind new back buffer RTV
+ pImmediateCtxVk->SetRenderTargets(0, nullptr, nullptr);
+ }
}
void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
@@ -483,6 +498,7 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
// All references to the swap chain must be released before it can be resized
m_pBackBufferRTV.clear();
+ m_SwapChainImagesInitialized.clear();
m_pDepthBufferDSV.Release();
// This will release references to Vk swap chain buffers hold by
@@ -514,12 +530,6 @@ void SwapChainVkImpl::Resize( Uint32 NewWidth, Uint32 NewHeight )
}
}
-ITextureViewVk *SwapChainVkImpl::GetCurrentBackBufferRTV()
-{
- VERIFY_EXPR(m_BackBufferIndex >= 0 && m_BackBufferIndex < m_SwapChainDesc.BufferCount);
- return m_pBackBufferRTV[m_BackBufferIndex];
-}
-
void SwapChainVkImpl::SetFullscreenMode(const DisplayModeAttribs &DisplayMode)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index bda852f4..b488aefa 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -156,6 +156,39 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
auto err = LogicalDevice.BindImageMemory(m_VulkanImage, Memory, AlignedOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind image memory");
+
+ // Vulkan validation layers do not like uninitialized memory, so if no initial data
+ // is provided, we will clear the memory
+
+ VulkanUtilities::CommandPoolWrapper CmdPool;
+ VkCommandBuffer vkCmdBuff;
+ pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
+
+ VkImageAspectFlags aspectMask = 0;
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
+ aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
+ else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ {
+ if(bInitializeTexture)
+ {
+ UNSUPPORTED("Initializing depth-stencil texture is not currently supported");
+ // Only single aspect bit must be specified when copying texture data
+ }
+ aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
+ }
+ else
+ aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+
+ // For either clear or copy command, dst layout must be VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ VkImageSubresourceRange SubresRange;
+ SubresRange.aspectMask = aspectMask;
+ SubresRange.baseArrayLayer = 0;
+ SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ SubresRange.baseMipLevel = 0;
+ SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
+ VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, m_CurrentLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange);
+ m_CurrentLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+
if(bInitializeTexture)
{
Uint32 ExpectedNumSubresources = ImageCI.mipLevels * ImageCI.arrayLayers;
@@ -163,18 +196,6 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Incorrect number of subresources in init data. ", ExpectedNumSubresources, " expected, while ", InitData.NumSubresources, " provided");
std::vector<VkBufferImageCopy> Regions(InitData.NumSubresources);
-
- VkImageAspectFlags aspectMask = 0;
- if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH)
- aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
- else if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
- {
- UNSUPPORTED("Initializing depth-stencil texture is not currently supported");
- // Only single aspect bit must be specified
- aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;// | VK_IMAGE_ASPECT_STENCIL_BIT;
- }
- else
- aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
UINT64 uploadBufferSize = 0;
auto TexelSize = FmtAttribs.ComponentSize * FmtAttribs.NumComponents;
@@ -291,21 +312,8 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
err = LogicalDevice.BindBufferMemory(StagingBuffer, StagingBufferMemory, AlignedStagingMemOffset);
CHECK_VK_ERROR_AND_THROW(err, "Failed to bind staging bufer memory");
- VulkanUtilities::CommandPoolWrapper CmdPool;
- VkCommandBuffer vkCmdBuff;
- pRenderDeviceVk->AllocateTransientCmdPool(CmdPool, vkCmdBuff, "Transient command pool to copy staging data to a device buffer");
-
VulkanUtilities::VulkanCommandBuffer::BufferMemoryBarrier(vkCmdBuff, StagingBuffer, 0, VK_ACCESS_TRANSFER_READ_BIT);
- VkImageSubresourceRange SubresRange;
- SubresRange.aspectMask = aspectMask;
- SubresRange.baseArrayLayer = 0;
- SubresRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
- SubresRange.baseMipLevel = 0;
- SubresRange.levelCount = VK_REMAINING_MIP_LEVELS;
- VulkanUtilities::VulkanCommandBuffer::TransitionImageLayout(vkCmdBuff, m_VulkanImage, m_CurrentLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, SubresRange);
- m_CurrentLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-
// Copy commands MUST be recorded outside of a render pass instance. This is OK here
// as copy will be the only command in the cmd buffer
vkCmdCopyBufferToImage(vkCmdBuff, StagingBuffer, m_VulkanImage,
@@ -320,6 +328,35 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingBuffer));
pRenderDeviceVk->SafeReleaseVkObject(std::move(StagingMemoryAllocation));
}
+ else
+ {
+ VkImageSubresourceRange Subresource;
+ Subresource.aspectMask = aspectMask;
+ Subresource.baseMipLevel = 0;
+ Subresource.levelCount = VK_REMAINING_MIP_LEVELS;
+ Subresource.baseArrayLayer = 0;
+ Subresource.layerCount = VK_REMAINING_ARRAY_LAYERS;
+ if(aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
+ {
+ VkClearColorValue ClearColor = {};
+ vkCmdClearColorImage(vkCmdBuff, m_VulkanImage,
+ m_CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ &ClearColor, 1, &Subresource);
+ }
+ else if(aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT ||
+ aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) )
+ {
+ VkClearDepthStencilValue ClearValue = {};
+ vkCmdClearDepthStencilImage(vkCmdBuff, m_VulkanImage,
+ m_CurrentLayout, // must be VK_IMAGE_LAYOUT_GENERAL or VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ &ClearValue, 1, &Subresource);
+ }
+ else
+ {
+ UNEXPECTED("Unexpected aspect mask");
+ }
+ pRenderDeviceVk->ExecuteAndDisposeTransientCmdBuff(vkCmdBuff, std::move(CmdPool));
+ }
#if 0
if(m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS)
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
index 587d988d..3c9fe3b3 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanDebug.cpp
@@ -31,6 +31,11 @@ namespace VulkanUtilities
{
std::stringstream debugMessage;
+ // Ignore warning about using RenderPass LOAD_OP_CLEAR:
+ // vkCmdClearAttachments() issued on command buffer object 0x... prior to any Draw Cmds. It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.
+ if ( (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) && msgCode == 64)
+ return VK_FALSE;
+
debugMessage << "Vulkan debug message";
// Select prefix depending on flags passed to the callback