diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-07-02 00:08:59 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-07-02 00:08:59 +0000 |
| commit | 354898decf45d32a09d9b4a15319413a5d199f2a (patch) | |
| tree | 61e46f6cb4fc324338903c79292c9c995e3f67ef /Graphics/GraphicsEngineVulkan | |
| parent | Reworked how render targets are bound in Vulkan: added RenderPass cache (diff) | |
| download | DiligentCore-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')
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 |
