summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-07-01 18:34:20 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-07-01 18:34:20 +0000
commit5257f98c5b0b43a887f7cd0528d343c831c053cb (patch)
tree78adaa74c27323c17645a61252fd1301fef370db /Graphics/GraphicsEngineVulkan
parentUnified implementation of IPipelineState::BindShaderResources() (diff)
downloadDiligentCore-5257f98c5b0b43a887f7cd0528d343c831c053cb.tar.gz
DiligentCore-5257f98c5b0b43a887f7cd0528d343c831c053cb.zip
Reworked how render targets are bound in Vulkan: added RenderPass cache
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h16
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h13
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderPassCache.h131
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h11
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp268
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp69
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp67
-rw-r--r--Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp61
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp2
15 files changed, 414 insertions, 239 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index ab667660..d93101be 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -18,6 +18,7 @@ set(INCLUDE
include/PipelineLayout.h
include/PipelineStateVkImpl.h
include/RenderDeviceVkImpl.h
+ include/RenderPassCache.h
include/SamplerVkImpl.h
include/ShaderVkImpl.h
include/ShaderResourceBindingVkImpl.h
@@ -77,6 +78,7 @@ set(SRC
src/PipelineLayout.cpp
src/PipelineStateVkImpl.cpp
src/RenderDeviceVkImpl.cpp
+ src/RenderPassCache.cpp
src/RenderDeviceFactoryVk.cpp
src/SamplerVkImpl.cpp
src/ShaderVkImpl.cpp
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
index ecd6d4a4..057467c0 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
@@ -154,11 +154,12 @@ public:
VulkanDynamicAllocation AllocateDynamicSpace(Uint32 SizeInBytes);
+ void ResetRenderTargets();
+
private:
- void CommitRenderPassAndFramebuffer(class PipelineStateVkImpl* pPipelineStateVk);
+ void CommitRenderPassAndFramebuffer();
void CommitVkVertexBuffers();
void TransitionVkVertexBuffers();
- void CommitRenderTargets();
void CommitViewports();
void CommitScissorRects();
@@ -180,7 +181,16 @@ private:
Uint32 NumCommands = 0;
}m_State;
-
+
+
+ /// Render pass that matches currently bound render targets.
+ /// This render pass may or may not be currently set in the command buffer
+ VkRenderPass m_RenderPass = VK_NULL_HANDLE;
+
+ /// Framebuffer that matches currently bound render targets.
+ /// This framebuffer may or may not be currently set in the command buffer
+ VkFramebuffer m_Framebuffer = VK_NULL_HANDLE;
+
#if 0
GenerateMipsHelper m_MipsGenerator;
#endif
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
index 07e6da7b..ab78374b 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
@@ -89,10 +89,17 @@ public:
}
IShaderVariable *GetDummyShaderVar(){return &m_DummyVar;}
+
+ static VkRenderPassCreateInfo GetRenderPassCreateInfo(Uint32 NumRenderTargets,
+ const TEXTURE_FORMAT RTVFormats[],
+ TEXTURE_FORMAT DSVFormat,
+ Uint32 SampleCount,
+ std::array<VkAttachmentDescription, MaxRenderTargets+1>& Attachments,
+ std::array<VkAttachmentReference, MaxRenderTargets+1>& AttachmentReferences,
+ VkSubpassDescription& SubpassDesc);
-private:
- void CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice);
+private:
DummyShaderVariable m_DummyVar;
@@ -107,7 +114,7 @@ private:
// Default SRB must be defined after allocators
std::unique_ptr<class ShaderResourceBindingVkImpl, STDDeleter<ShaderResourceBindingVkImpl, FixedBlockMemoryAllocator> > m_pDefaultShaderResBinding;
- VulkanUtilities::RenderPassWrapper m_RenderPass;
+ VkRenderPass m_RenderPass = VK_NULL_HANDLE; // Render passes are managed by the render device
VulkanUtilities::PipelineWrapper m_Pipeline;
PipelineLayout m_PipelineLayout;
bool m_HasStaticResources = false;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
index 7c200d79..a4ed381d 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
@@ -42,6 +42,7 @@
#include "VulkanUtilities/VulkanMemoryManager.h"
#include "VulkanUtilities/VulkanUploadHeap.h"
#include "FramebufferCache.h"
+#include "RenderPassCache.h"
#include "CommandPoolManager.h"
#include "ResourceReleaseQueue.h"
#include "VulkanDynamicHeap.h"
@@ -124,6 +125,7 @@ public:
const VulkanUtilities::VulkanPhysicalDevice& GetPhysicalDevice(){return *m_PhysicalDevice;}
const VulkanUtilities::VulkanLogicalDevice& GetLogicalDevice() {return *m_LogicalVkDevice;}
FramebufferCache& GetFramebufferCache(){return m_FramebufferCache;}
+ RenderPassCache& GetRenderPassCache(){return m_RenderPassCache;}
VulkanUtilities::VulkanMemoryAllocation AllocateMemory(const VkMemoryRequirements& MemReqs, VkMemoryPropertyFlags MemoryProperties)
{
@@ -183,6 +185,7 @@ private:
// be released
FramebufferCache m_FramebufferCache;
+ RenderPassCache m_RenderPassCache;
DescriptorPoolManager m_MainDescriptorPool;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderPassCache.h b/Graphics/GraphicsEngineVulkan/include/RenderPassCache.h
new file mode 100644
index 00000000..8cede4bb
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/RenderPassCache.h
@@ -0,0 +1,131 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+/// \file
+/// Declaration of Diligent::RenderPassCache class
+
+#include <unordered_map>
+#include <mutex>
+#include "GraphicsTypes.h"
+#include "Constants.h"
+#include "HashUtils.h"
+#include "VulkanUtilities/VulkanObjectWrappers.h"
+
+namespace Diligent
+{
+
+class RenderDeviceVkImpl;
+class RenderPassCache
+{
+public:
+ RenderPassCache(RenderDeviceVkImpl& DeviceVk)noexcept :
+ m_DeviceVkImpl(DeviceVk)
+ {}
+
+ RenderPassCache (const RenderPassCache&) = delete;
+ RenderPassCache (RenderPassCache&&) = delete;
+ RenderPassCache& operator = (const RenderPassCache&) = delete;
+ RenderPassCache& operator = (RenderPassCache&&) = delete;
+
+ ~RenderPassCache();
+
+ // This structure is used as the key to find framebuffer
+ struct RenderPassCacheKey
+ {
+ RenderPassCacheKey() :
+ NumRenderTargets(0),
+ SampleCount (0),
+ DSVFormat (TEX_FORMAT_UNKNOWN)
+ {}
+
+ RenderPassCacheKey(Uint32 _NumRenderTargets,
+ Uint32 _SampleCount,
+ const TEXTURE_FORMAT _RTVFormats[],
+ TEXTURE_FORMAT _DSVFormat) :
+ NumRenderTargets( static_cast<decltype(NumRenderTargets)>(_NumRenderTargets) ),
+ SampleCount ( static_cast<decltype(SampleCount)> (_SampleCount) ),
+ DSVFormat ( _DSVFormat )
+ {
+ VERIFY_EXPR(_NumRenderTargets <= std::numeric_limits<decltype(NumRenderTargets)>::max());
+ VERIFY_EXPR(_SampleCount <= std::numeric_limits<decltype(SampleCount)>::max());
+ for(Uint32 rt=0; rt < NumRenderTargets; ++rt)
+ RTVFormats[rt] = _RTVFormats[rt];
+ }
+ // Default memeber initialization is intentionally omitted
+ Uint8 NumRenderTargets;
+ Uint8 SampleCount;
+ TEXTURE_FORMAT DSVFormat;
+ TEXTURE_FORMAT RTVFormats[MaxRenderTargets];
+
+ bool operator == (const RenderPassCacheKey &rhs)const
+ {
+ if (GetHash() != rhs.GetHash() ||
+ NumRenderTargets != rhs.NumRenderTargets ||
+ SampleCount != rhs.SampleCount ||
+ DSVFormat != rhs.DSVFormat)
+ {
+ return false;
+ }
+
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ if (RTVFormats[rt] != rhs.RTVFormats[rt])
+ return false;
+
+ return true;
+ }
+
+ size_t GetHash()const
+ {
+ if(Hash == 0)
+ {
+ Hash = ComputeHash(NumRenderTargets, SampleCount, DSVFormat);
+ for(Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ HashCombine(Hash, RTVFormats[rt]);
+ }
+ return Hash;
+ }
+
+ private:
+ mutable size_t Hash = 0;
+ };
+
+ VkRenderPass GetRenderPass(const RenderPassCacheKey& Key);
+
+private:
+
+ struct RenderPassCacheKeyHash
+ {
+ std::size_t operator() (const RenderPassCacheKey& Key)const
+ {
+ return Key.GetHash();
+ }
+ };
+
+ RenderDeviceVkImpl& m_DeviceVkImpl;
+ std::mutex m_Mutex;
+ std::unordered_map<RenderPassCacheKey, VulkanUtilities::RenderPassWrapper, RenderPassCacheKeyHash> m_Cache;
+};
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
index cda2bb73..63c44e80 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
@@ -179,16 +179,9 @@ namespace VulkanUtilities
VERIFY(m_State.RenderPass != VK_NULL_HANDLE, "Render pass has not been started");
VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
vkCmdEndRenderPass(m_VkCmdBuffer);
- m_State.RenderPass = VK_NULL_HANDLE;
- // Do not set framebuffer to null. We will reuse cached framebuffer handle
- // if the render pass is restarted without changing render targets
- //m_State.Framebuffer = VK_NULL_HANDLE;
- }
-
- void ResetFramebuffer()
- {
+ m_State.RenderPass = VK_NULL_HANDLE;
m_State.Framebuffer = VK_NULL_HANDLE;
- m_State.FramebufferWidth = 0;
+ m_State.FramebufferWidth = 0;
m_State.FramebufferHeight = 0;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index cd254899..2f566d17 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -407,8 +407,8 @@ void BufferVkImpl::Unmap( IDeviceContext* pContext, MAP_TYPE MapType, Uint32 Map
TBufferBase::Unmap( pContext, MapType, MapFlags );
auto *pDeviceContextVk = ValidatedCast<DeviceContextVkImpl>(pContext);
-#ifdef _DEBUG
Uint32 CtxId = pDeviceContextVk != nullptr ? pDeviceContextVk->GetContextId() : static_cast<Uint32>(-1);
+#ifdef _DEBUG
if (pDeviceContextVk != nullptr)
{
VERIFY(m_DbgMapType[CtxId].first == MapType, "Map type does not match the type provided to Map()");
diff --git a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
index c118b788..d49560fc 100644
--- a/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/CommandPoolManager.cpp
@@ -27,9 +27,9 @@
namespace Diligent
{
-CommandPoolManager ::CommandPoolManager(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
- uint32_t queueFamilyIndex,
- VkCommandPoolCreateFlags flags)noexcept:
+CommandPoolManager::CommandPoolManager(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ uint32_t queueFamilyIndex,
+ VkCommandPoolCreateFlags flags)noexcept:
m_LogicalDevice (LogicalDevice),
m_QueueFamilyIndex(queueFamilyIndex),
m_CmdPoolFlags (flags),
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 9585d612..31015257 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -178,7 +178,6 @@ namespace Diligent
{
m_CommandBuffer.EndRenderPass();
}
- m_CommandBuffer.ResetFramebuffer();
// Never flush deferred context!
if (!m_bIsDeferred && m_State.NumCommands >= m_NumCommandsToFlush)
@@ -227,7 +226,7 @@ namespace Diligent
{
m_CommandBuffer.SetStencilReference(m_StencilRef);
m_CommandBuffer.SetBlendConstants(m_BlendFactors);
- CommitRenderTargets();
+ CommitRenderPassAndFramebuffer();
CommitViewports();
}
@@ -275,84 +274,6 @@ namespace Diligent
}
}
- void DeviceContextVkImpl::CommitRenderPassAndFramebuffer(PipelineStateVkImpl *pPipelineStateVk)
- {
- auto *pRenderDeviceVk = m_pDevice.RawPtr<RenderDeviceVkImpl>();
- auto &FBCache = pRenderDeviceVk->GetFramebufferCache();
- auto RenderPass = pPipelineStateVk->GetVkRenderPass();
- const auto& CmdBufferState = m_CommandBuffer.GetState();
- if(CmdBufferState.Framebuffer != VK_NULL_HANDLE)
- {
- // Render targets have not changed since the last time, so we can reuse
- // previously bound framebuffer
- VERIFY_EXPR(m_FramebufferWidth == CmdBufferState.FramebufferWidth && m_FramebufferHeight == CmdBufferState.FramebufferHeight);
- m_CommandBuffer.BeginRenderPass(RenderPass, CmdBufferState.Framebuffer, CmdBufferState.FramebufferWidth, CmdBufferState.FramebufferHeight);
- return;
- }
-
- const auto &GrPipelineDesc = pPipelineStateVk->GetDesc().GraphicsPipeline;
- FramebufferCache::FramebufferCacheKey Key;
- Key.Pass = RenderPass;
- if(m_NumBoundRenderTargets == 0 && !m_pBoundDepthStencil)
- {
- auto *pSwapChainVk = m_pSwapChain.RawPtr<ISwapChainVk>();
- if(GrPipelineDesc.DSVFormat != TEX_FORMAT_UNKNOWN)
- {
- auto *pDSV = pSwapChainVk->GetDepthBufferDSV();
- TransitionImageLayout(pDSV->GetTexture(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- Key.DSV = pDSV->GetVulkanImageView();
- }
- else
- Key.DSV = VK_NULL_HANDLE;
-
- VERIFY(GrPipelineDesc.NumRenderTargets <= 1, "Pipeline state expects ", GrPipelineDesc.NumRenderTargets, " render targets, but default framebuffer has only one");
- if(GrPipelineDesc.RTVFormats[0] != TEX_FORMAT_UNKNOWN)
- {
- auto *pRTV = pSwapChainVk->GetCurrentBackBufferRTV();
- TransitionImageLayout(pRTV->GetTexture(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- Key.NumRenderTargets = 1;
- Key.RTVs[0] = pRTV->GetVulkanImageView();
- }
- else
- Key.NumRenderTargets = 0;
- }
- else
- {
- if (GrPipelineDesc.DSVFormat != TEX_FORMAT_UNKNOWN)
- {
- if(m_pBoundDepthStencil)
- {
- auto *pDSVVk = m_pBoundDepthStencil.RawPtr<TextureViewVkImpl>();
- TransitionImageLayout(pDSVVk->GetTexture(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
- Key.DSV = pDSVVk->GetVulkanImageView();
- }
- else
- {
- LOG_ERROR("Currently bound graphics pipeline state expects depth-stencil buffer, but none is currently bound. This is an error and will result in undefined behavior");
- Key.DSV = VK_NULL_HANDLE;
- }
- }
- else
- Key.DSV = nullptr;
-
- VERIFY(m_NumBoundRenderTargets >= GrPipelineDesc.NumRenderTargets, "Pipeline state expects ", GrPipelineDesc.NumRenderTargets, " render targets, but only ", m_NumBoundRenderTargets, " is bound");
- Key.NumRenderTargets = GrPipelineDesc.NumRenderTargets;
- for(Uint32 rt=0; rt < Key.NumRenderTargets; ++rt)
- {
- if(ITextureView *pRTV = m_pBoundRenderTargets[rt])
- {
- auto *pRTVVk = ValidatedCast<TextureViewVkImpl>(pRTV);
- TransitionImageLayout(pRTV->GetTexture(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
- Key.RTVs[rt] = pRTVVk->GetVulkanImageView();
- }
- else
- Key.RTVs[rt] = nullptr;
- }
- }
- auto vkFramebuffer = FBCache.GetFramebuffer(Key, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
- m_CommandBuffer.BeginRenderPass(Key.Pass, vkFramebuffer, m_FramebufferWidth, m_FramebufferHeight);
- }
-
void DeviceContextVkImpl::TransitionVkVertexBuffers()
{
for( UINT Buff = 0; Buff < m_NumVertexStreams; ++Buff )
@@ -466,8 +387,16 @@ namespace Diligent
BufferMemoryBarrier(*pBufferVk, VK_ACCESS_INDIRECT_COMMAND_READ_BIT);
}
- if(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE)
- CommitRenderPassAndFramebuffer(pPipelineStateVk);
+#ifdef _DEBUG
+ if(pPipelineStateVk->GetVkRenderPass() != m_RenderPass)
+ {
+ LOG_ERROR_MESSAGE("Committed render pass does not match render pass from the Pipeline State object. "
+ "This indicates the mismatch between the number and/or format of bound render targets and depth stencil buffer "
+ "and information used to initialize the PSO.");
+ }
+#endif
+
+ CommitRenderPassAndFramebuffer();
if( DrawAttribs.IsIndirect )
{
@@ -558,9 +487,9 @@ namespace Diligent
++m_State.NumCommands;
}
- void DeviceContextVkImpl::ClearDepthStencil( ITextureView *pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil )
+ void DeviceContextVkImpl::ClearDepthStencil( ITextureView* pView, Uint32 ClearFlags, float fDepth, Uint8 Stencil )
{
- ITextureViewVk *pVkDSV = nullptr;
+ ITextureViewVk* pVkDSV = nullptr;
if( pView != nullptr )
{
pVkDSV = ValidatedCast<ITextureViewVk>(pView);
@@ -587,12 +516,12 @@ namespace Diligent
const auto &ViewDesc = pVkDSV->GetDesc();
EnsureVkCmdBuffer();
bool ClearedAsAttachment = false;
- if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ if(m_RenderPass != VK_NULL_HANDLE)
{
- if(m_pPipelineState &&
- m_pPipelineState->GetDesc().GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN &&
- (pView == nullptr || pView == m_pBoundDepthStencil))
+ 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;
@@ -613,7 +542,8 @@ namespace Diligent
else
{
// End render pass to clear the buffer with vkCmdClearDepthStencilImage
- m_CommandBuffer.EndRenderPass();
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
}
}
@@ -702,15 +632,12 @@ namespace Diligent
Uint32 attachmentIndex = InvalidAttachmentIndex;
if(pView == nullptr)
{
- attachmentIndex = 0;
+ if(m_IsDefaultFramebufferBound)
+ attachmentIndex = 0;
}
else
{
- VERIFY(m_pPipelineState, "Valid pipeline state must be bound inside active render pass");
- const auto &GrPipelineDesc = m_pPipelineState->GetDesc().GraphicsPipeline;
- VERIFY(m_NumBoundRenderTargets >= GrPipelineDesc.NumRenderTargets, "Pipeline state expects ", GrPipelineDesc.NumRenderTargets, " render targets, but only ", m_NumBoundRenderTargets, " is bound");
- Uint32 MaxRTIndex = std::min(Uint32{GrPipelineDesc.NumRenderTargets}, m_NumBoundRenderTargets);
- for(Uint32 rt = 0; rt < MaxRTIndex; ++rt)
+ for(Uint32 rt = 0; rt < m_NumBoundRenderTargets; ++rt)
{
if(m_pBoundRenderTargets[rt] == pView)
{
@@ -742,7 +669,8 @@ namespace Diligent
else
{
// End current render pass and clear the image with vkCmdClearColorImage
- m_CommandBuffer.EndRenderPass();
+ if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
}
}
@@ -865,6 +793,8 @@ namespace Diligent
TDeviceContextBase::InvalidateState();
m_State = ContextState{};
+ m_RenderPass = VK_NULL_HANDLE;
+ m_Framebuffer = VK_NULL_HANDLE;
m_DesrSetBindInfo.Reset();
VERIFY(m_CommandBuffer.GetState().RenderPass == VK_NULL_HANDLE, "Invalidating context with unifinished render pass");
m_CommandBuffer.Reset();
@@ -945,52 +875,136 @@ namespace Diligent
}
- void DeviceContextVkImpl::CommitRenderTargets()
+ void DeviceContextVkImpl::CommitRenderPassAndFramebuffer()
{
-#if 0
- const Uint32 MaxVkRTs = Vk_SIMULTANEOUS_RENDER_TARGET_COUNT;
- Uint32 NumRenderTargets = m_NumBoundRenderTargets;
- VERIFY( NumRenderTargets <= MaxVkRTs, "Vk only allows 8 simultaneous render targets" );
- NumRenderTargets = std::min( MaxVkRTs, NumRenderTargets );
-
- ITextureViewVk *ppRTVs[MaxVkRTs]; // Do not initialize with zeroes!
- ITextureViewVk *pDSV = nullptr;
- if( m_IsDefaultFramebufferBound )
+ const auto& CmdBufferState = m_CommandBuffer.GetState();
+ if(CmdBufferState.RenderPass != m_RenderPass)
{
- if (m_pSwapChain)
- {
- NumRenderTargets = 1;
- auto *pSwapChainVk = m_pSwapChain.RawPtr<ISwapChainVk>();
- ppRTVs[0] = pSwapChainVk->GetCurrentBackBufferRTV();
- pDSV = pSwapChainVk->GetDepthBufferDSV();
- }
- else
+ if(CmdBufferState.RenderPass != VK_NULL_HANDLE)
+ m_CommandBuffer.EndRenderPass();
+
+ if(m_RenderPass != VK_NULL_HANDLE)
{
- LOG_WARNING_MESSAGE("Failed to bind default render targets and depth-stencil buffer: swap chain is not initialized in the device context");
- return;
+ VERIFY_EXPR(m_Framebuffer != VK_NULL_HANDLE);
+ if(m_IsDefaultFramebufferBound)
+ {
+ 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);
+ }
+ 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)
+ {
+ if(ITextureView* pRTV = m_pBoundRenderTargets[rt])
+ {
+ 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);
}
}
- else
- {
- for( Uint32 rt = 0; rt < NumRenderTargets; ++rt )
- ppRTVs[rt] = m_pBoundRenderTargets[rt].RawPtr<ITextureViewVk>();
- pDSV = m_pBoundDepthStencil.RawPtr<ITextureViewVk>();
- }
- RequestCmdContext()->AsGraphicsContext().SetRenderTargets(NumRenderTargets, ppRTVs, pDSV);
-#endif
}
void DeviceContextVkImpl::SetRenderTargets( Uint32 NumRenderTargets, ITextureView *ppRenderTargets[], ITextureView *pDepthStencil )
{
if( TDeviceContextBase::SetRenderTargets( NumRenderTargets, ppRenderTargets, pDepthStencil ) )
{
- if(m_CommandBuffer.GetState().RenderPass != VK_NULL_HANDLE)
- m_CommandBuffer.EndRenderPass();
- m_CommandBuffer.ResetFramebuffer();
+ FramebufferCache::FramebufferCacheKey FBKey;
+ RenderPassCache::RenderPassCacheKey RenderPassKey;
+ if(m_IsDefaultFramebufferBound)
+ {
+ 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);
+ }
+ 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.NumRenderTargets = m_NumBoundRenderTargets;
+ RenderPassKey.NumRenderTargets = static_cast<Uint8>(m_NumBoundRenderTargets);
+
+ for(Uint32 rt=0; rt < m_NumBoundRenderTargets; ++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");
+ }
+ else
+ {
+ FBKey.RTVs[rt] = nullptr;
+ RenderPassKey.RTVFormats[rt] = TEX_FORMAT_UNKNOWN;
+ }
+ }
+ }
+
+ auto pDeviceVkImpl = m_pDevice.RawPtr<RenderDeviceVkImpl>();
+ auto& FBCache = pDeviceVkImpl->GetFramebufferCache();
+ auto& RPCache = pDeviceVkImpl->GetRenderPassCache();
+
+ m_RenderPass = RPCache.GetRenderPass(RenderPassKey);
+ FBKey.Pass = m_RenderPass;
+ m_Framebuffer = FBCache.GetFramebuffer(FBKey, m_FramebufferWidth, m_FramebufferHeight, m_FramebufferSlices);
// Set the viewport to match the render target size
SetViewports(1, nullptr, 0, 0);
}
+ EnsureVkCmdBuffer();
+ CommitRenderPassAndFramebuffer();
+ }
+
+ void DeviceContextVkImpl::ResetRenderTargets()
+ {
+ TDeviceContextBase::ResetRenderTargets();
+ m_RenderPass = VK_NULL_HANDLE;
+ m_Framebuffer = VK_NULL_HANDLE;
}
void DeviceContextVkImpl::UpdateBufferRegion(BufferVkImpl* pBuffVk, Uint64 DstOffset, Uint64 NumBytes, VkBuffer vkSrcBuffer, Uint64 SrcOffset)
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 9763e0e4..ed3d334e 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -36,30 +36,32 @@
namespace Diligent
{
-void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice)
+VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo(
+ Uint32 NumRenderTargets,
+ const TEXTURE_FORMAT RTVFormats[],
+ TEXTURE_FORMAT DSVFormat,
+ Uint32 SampleCount,
+ std::array<VkAttachmentDescription, MaxRenderTargets+1>& Attachments,
+ std::array<VkAttachmentReference, MaxRenderTargets+1>& AttachmentReferences,
+ VkSubpassDescription& SubpassDesc)
{
- // NOTE: framebuffer cache and clear commands assume that depth buffer
- // attachment always goes first followed by all color attachments
+ VERIFY_EXPR(NumRenderTargets <= MaxRenderTargets);
- const auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- // Create render pass (7.1)
+ // Prepare render pass create info (7.1)
VkRenderPassCreateInfo RenderPassCI = {};
RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
RenderPassCI.pNext = nullptr;
RenderPassCI.flags = 0; // reserved for future use
- RenderPassCI.attachmentCount = (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + GraphicsPipeline.NumRenderTargets;
- std::vector<VkAttachmentDescription> Attachments(RenderPassCI.attachmentCount);
+ RenderPassCI.attachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
uint32_t AttachmentInd = 0;
- VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(1 << (GraphicsPipeline.SmplDesc.Count - 1));
- VkAttachmentReference DepthAttachmentReference = {};
- if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN)
+ VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(1 << (SampleCount - 1));
+ VkAttachmentReference* pDepthAttachmentReference = nullptr;
+ if (DSVFormat != TEX_FORMAT_UNKNOWN)
{
auto& DepthAttachment = Attachments[AttachmentInd];
- DepthAttachmentReference.attachment = AttachmentInd;
- DepthAttachmentReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
DepthAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
- DepthAttachment.format = TexFormatToVkFormat(GraphicsPipeline.DSVFormat);
+ DepthAttachment.format = TexFormatToVkFormat(DSVFormat);
DepthAttachment.samples = SampleCountFlags;
DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
// will be preserved. For attachments with a depth/stencil format,
@@ -72,18 +74,20 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD
DepthAttachment.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
DepthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+ pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
+ pDepthAttachmentReference->attachment = AttachmentInd;
+ pDepthAttachmentReference->layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
++AttachmentInd;
}
- std::vector<VkAttachmentReference> ColorAttachmentReferences(GraphicsPipeline.NumRenderTargets);
- for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt, ++AttachmentInd)
+
+ VkAttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd)
{
auto& ColorAttachment = Attachments[AttachmentInd];
- auto& ColorAttachmentRef = ColorAttachmentReferences[rt];
- ColorAttachmentRef.attachment = AttachmentInd;
- ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
ColorAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT
- ColorAttachment.format = TexFormatToVkFormat(GraphicsPipeline.RTVFormats[rt]);
+ ColorAttachment.format = TexFormatToVkFormat(RTVFormats[rt]);
ColorAttachment.samples = SampleCountFlags;
ColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
// will be preserved. For attachments with a depth/stencil format,
@@ -95,11 +99,13 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD
ColorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
ColorAttachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
ColorAttachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+ auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
+ ColorAttachmentRef.attachment = AttachmentInd;
+ ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
RenderPassCI.pAttachments = Attachments.data();
-
- VkSubpassDescription SubpassDesc = {};
RenderPassCI.subpassCount = 1;
RenderPassCI.pSubpasses = &SubpassDesc;
RenderPassCI.dependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
@@ -111,17 +117,14 @@ void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalD
SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported.
SubpassDesc.inputAttachmentCount = 0;
SubpassDesc.pInputAttachments = nullptr;
- SubpassDesc.colorAttachmentCount = GraphicsPipeline.NumRenderTargets;
- SubpassDesc.pColorAttachments = ColorAttachmentReferences.data();
+ SubpassDesc.colorAttachmentCount = NumRenderTargets;
+ SubpassDesc.pColorAttachments = pColorAttachmentsReference;
SubpassDesc.pResolveAttachments = nullptr;
- SubpassDesc.pDepthStencilAttachment = GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN ? &DepthAttachmentReference : nullptr;
+ SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference;
SubpassDesc.preserveAttachmentCount = 0;
SubpassDesc.pPreserveAttachments = nullptr;
- std::string RenderPassName = "Render pass for '";
- RenderPassName += m_Desc.Name;
- RenderPassName += '\'';
- m_RenderPass = LogicalDevice.CreateRenderPass(RenderPassCI, RenderPassName.c_str());
+ return RenderPassCI;
}
PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters,
@@ -231,7 +234,13 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- CreateRenderPass(LogicalDevice);
+ auto& RPCache = pDeviceVk->GetRenderPassCache();
+ RenderPassCache::RenderPassCacheKey Key(
+ GraphicsPipeline.NumRenderTargets,
+ GraphicsPipeline.SmplDesc.Count,
+ GraphicsPipeline.RTVFormats,
+ GraphicsPipeline.DSVFormat);
+ m_RenderPass = RPCache.GetRenderPass(Key);
VkGraphicsPipelineCreateInfo PipelineCI = {};
PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
@@ -396,8 +405,6 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters
PipelineStateVkImpl::~PipelineStateVkImpl()
{
auto pDeviceVkImpl = GetDevice<RenderDeviceVkImpl>();
- pDeviceVkImpl->GetFramebufferCache().OnDestroyRenderPass(m_RenderPass);
- pDeviceVkImpl->SafeReleaseVkObject(std::move(m_RenderPass));
pDeviceVkImpl->SafeReleaseVkObject(std::move(m_Pipeline));
m_PipelineLayout.Release(pDeviceVkImpl);
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 59befce3..2cafc8f7 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -67,6 +67,7 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters*
m_FrameNumber(0),
m_NextCmdBuffNumber(0),
m_FramebufferCache(*this),
+ m_RenderPassCache(*this),
m_MainDescriptorPool
{
m_LogicalVkDevice,
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
new file mode 100644
index 00000000..a1d66f4d
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/RenderPassCache.cpp
@@ -0,0 +1,67 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include <sstream>
+#include "RenderPassCache.h"
+#include "RenderDeviceVkImpl.h"
+#include "PipelineStateVkImpl.h"
+
+namespace Diligent
+{
+
+RenderPassCache::~RenderPassCache()
+{
+ auto& FBCache = m_DeviceVkImpl.GetFramebufferCache();
+ for(auto it = m_Cache.begin(); it != m_Cache.end(); ++it)
+ {
+ FBCache.OnDestroyRenderPass(it->second);
+ }
+}
+
+VkRenderPass RenderPassCache::GetRenderPass(const RenderPassCacheKey& Key)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ auto it = m_Cache.find(Key);
+ if(it == m_Cache.end())
+ {
+ // Do not zero-intitialize arrays
+ std::array<VkAttachmentDescription, MaxRenderTargets+1> Attachments;
+ std::array<VkAttachmentReference, MaxRenderTargets+1> AttachmentReferences;
+ VkSubpassDescription Subpass;
+ auto RenderPassCI = PipelineStateVkImpl::GetRenderPassCreateInfo(Key.NumRenderTargets, Key.RTVFormats, Key.DSVFormat,
+ Key.SampleCount, Attachments, AttachmentReferences, Subpass);
+ std::stringstream PassNameSS;
+ PassNameSS << "Render pass: rt count: " << Key.NumRenderTargets << "; sample count: "<< Key.SampleCount
+ << "; DSV Format: " << GetTextureFormatAttribs(Key.DSVFormat).Name << "; RTV Formats: ";
+ for(Uint32 rt = 0; rt < Key.NumRenderTargets; ++rt)
+ PassNameSS << (rt > 0 ? ", " : "") << GetTextureFormatAttribs(Key.RTVFormats[rt]).Name;
+ auto RenderPass = m_DeviceVkImpl.GetLogicalDevice().CreateRenderPass(RenderPassCI, PassNameSS.str().c_str());
+ VERIFY_EXPR(RenderPass != VK_NULL_HANDLE);
+ it = m_Cache.emplace(Key, std::move(RenderPass)).first;
+ }
+
+ return it->second;
+}
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
index d9222767..91db6b49 100644
--- a/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp
@@ -425,6 +425,7 @@ 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;
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 94000d3a..bda852f4 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -36,27 +36,6 @@ using namespace Diligent;
namespace Diligent
{
-#if 0
-DXGI_FORMAT GetClearFormat(DXGI_FORMAT Fmt, Vk_RESOURCE_FLAGS Flags)
-{
- if( Flags & Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL )
- {
- switch (Fmt)
- {
- case DXGI_FORMAT_R32_TYPELESS: return DXGI_FORMAT_D32_FLOAT;
- case DXGI_FORMAT_R16_TYPELESS: return DXGI_FORMAT_D16_UNORM;
- case DXGI_FORMAT_R24G8_TYPELESS: return DXGI_FORMAT_D24_UNORM_S8_UINT;
- case DXGI_FORMAT_R32G8X24_TYPELESS: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
- }
- }
- else if (Flags & Vk_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
- {
-
- }
- return Fmt;
-}
-#endif
-
TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
FixedBlockMemoryAllocator& TexViewObjAllocator,
RenderDeviceVkImpl* pRenderDeviceVk,
@@ -159,46 +138,6 @@ TextureVkImpl :: TextureVkImpl(IReferenceCounters* pRefCounters,
m_CurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
ImageCI.initialLayout = m_CurrentLayout;
-#if 0
- Desc.Flags = Vk_RESOURCE_FLAG_NONE;
-
- auto Format = TexFormatToDXGI_Format(m_Desc.Format, m_Desc.BindFlags);
- if (Format == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB && (Desc.Flags & Vk_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS))
- Desc.Format = DXGI_FORMAT_R8G8B8A8_TYPELESS;
- else
- Desc.Format = Format;
-
- Vk_HEAP_PROPERTIES HeapProps;
- HeapProps.Type = Vk_HEAP_TYPE_DEFAULT;
- HeapProps.CPUPageProperty = Vk_CPU_PAGE_PROPERTY_UNKNOWN;
- HeapProps.MemoryPoolPreference = Vk_MEMORY_POOL_UNKNOWN;
- HeapProps.CreationNodeMask = 1;
- HeapProps.VisibleNodeMask = 1;
-
- auto *pVkDevice = pRenderDeviceVk->GetVkDevice();
- Vk_CLEAR_VALUE ClearValue;
- Vk_CLEAR_VALUE *pClearValue = nullptr;
- if( Desc.Flags & (Vk_RESOURCE_FLAG_ALLOW_RENDER_TARGET | Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) )
- {
- if(m_Desc.ClearValue.Format != TEX_FORMAT_UNKNOWN)
- ClearValue.Format = TexFormatToDXGI_Format(m_Desc.ClearValue.Format);
- else
- ClearValue.Format = GetClearFormat(Format, Desc.Flags);
-
- if (Desc.Flags & Vk_RESOURCE_FLAG_ALLOW_RENDER_TARGET)
- {
- for(int i=0; i < 4; ++i)
- ClearValue.Color[i] = m_Desc.ClearValue.Color[i];
- }
- else if(Desc.Flags & Vk_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)
- {
- ClearValue.DepthStencil.Depth = m_Desc.ClearValue.DepthStencil.Depth;
- ClearValue.DepthStencil.Stencil = m_Desc.ClearValue.DepthStencil.Stencil;
- }
- pClearValue = &ClearValue;
- }
-#endif
-
bool bInitializeTexture = (InitData.pSubResources != nullptr && InitData.NumSubresources > 0);
m_VulkanImage = LogicalDevice.CreateImage(ImageCI, m_Desc.Name);
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index 6a3642f1..e2365f7d 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -130,7 +130,7 @@ namespace VulkanUtilities
VkInstanceCreateInfo InstanceCreateInfo = {};
InstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
- InstanceCreateInfo.pNext = NULL; // Pointer to an extension-specific structure.
+ InstanceCreateInfo.pNext = nullptr; // Pointer to an extension-specific structure.
InstanceCreateInfo.flags = 0; // Reserved for future use.
InstanceCreateInfo.pApplicationInfo = &appInfo;
InstanceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(GlobalExtensions.size());