summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-04-16 03:20:02 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-04-16 03:20:02 +0000
commit0400f81cac9540a460a57595b28c9e403124c727 (patch)
tree3336489453635051aa2a8ae80419f0d3ba61d86e /Graphics/GraphicsEngineVulkan
parentImplemented vulkan swap chain resize (diff)
downloadDiligentCore-0400f81cac9540a460a57595b28c9e403124c727.tar.gz
DiligentCore-0400f81cac9540a460a57595b28c9e403124c727.zip
Added vulkan framebuffer cache
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/FramebufferCache.h88
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h4
-rw-r--r--Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp148
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp2
7 files changed, 246 insertions, 2 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index 63a4d1ec..1da9c203 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -13,6 +13,7 @@ set(INCLUDE
include/DescriptorHeap.h
include/DeviceContextVkImpl.h
include/DynamicUploadHeap.h
+ include/FramebufferCache.h
include/GenerateMips.h
include/pch.h
include/PipelineStateVkImpl.h
@@ -68,6 +69,7 @@ set(SRC
src/DescriptorHeap.cpp
src/DeviceContextVkImpl.cpp
src/DynamicUploadHeap.cpp
+ src/FramebufferCache.cpp
src/GenerateMips.cpp
src/PipelineStateVkImpl.cpp
src/RenderDeviceVkImpl.cpp
diff --git a/Graphics/GraphicsEngineVulkan/include/FramebufferCache.h b/Graphics/GraphicsEngineVulkan/include/FramebufferCache.h
new file mode 100644
index 00000000..db9861da
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/FramebufferCache.h
@@ -0,0 +1,88 @@
+/* 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::FramebufferCache class
+
+#include <unordered_map>
+#include <mutex>
+#include "VulkanUtilities/VulkanObjectWrappers.h"
+
+namespace Diligent
+{
+
+class RenderDeviceVkImpl;
+class FramebufferCache
+{
+public:
+ FramebufferCache(RenderDeviceVkImpl& DeviceVKImpl) :
+ m_DeviceVk(DeviceVKImpl)
+ {}
+
+ FramebufferCache(const FramebufferCache&) = delete;
+ FramebufferCache(FramebufferCache&&) = delete;
+ FramebufferCache& operator = (const FramebufferCache&) = delete;
+ FramebufferCache& operator = (FramebufferCache&&) = delete;
+
+ ~FramebufferCache();
+
+ // This structure is used as the key to find framebuffer
+ struct FramebufferCacheKey
+ {
+ // Default memeber initialization is intentionally omitted
+ VkRenderPass Pass;
+ Uint32 NumRenderTargets;
+ VkImageView DSV;
+ VkImageView RTVs[MaxRenderTargets];
+ bool operator == (const FramebufferCacheKey &rhs)const;
+ size_t GetHash()const;
+
+ private:
+ mutable size_t Hash = 0;
+ };
+
+ VkFramebuffer GetFramebuffer(const FramebufferCacheKey& Key, uint32_t width, uint32_t height, uint32_t layers);
+ void OnDestroyImageView(VkImageView ImgView);
+ void OnDestroyRenderPass(VkRenderPass Pass);
+
+private:
+
+ RenderDeviceVkImpl& m_DeviceVk;
+
+ struct FramebufferCacheKeyHash
+ {
+ std::size_t operator() (const FramebufferCacheKey& Key)const
+ {
+ return Key.GetHash();
+ }
+ };
+
+ std::mutex m_Mutex;
+ std::unordered_map<FramebufferCacheKey, VulkanUtilities::FramebufferWrapper, FramebufferCacheKeyHash> m_Cache;
+ std::unordered_multimap<VkImageView, FramebufferCacheKey> m_ViewToKeyMap;
+ std::unordered_multimap<VkRenderPass, FramebufferCacheKey> m_RenderPassToKeyMap;
+};
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
index 98275f24..471ed78c 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h
@@ -39,6 +39,7 @@
#include "VulkanUtilities/VulkanCommandBufferPool.h"
#include "VulkanUtilities/VulkanLogicalDevice.h"
#include "VulkanUtilities/VulkanObjectWrappers.h"
+#include "FramebufferCache.h"
/// Namespace for the Direct3D11 implementation of the graphics engine
namespace Diligent
@@ -115,6 +116,7 @@ public:
std::shared_ptr<const VulkanUtilities::VulkanInstance> GetVulkanInstance()const{return m_VulkanInstance;}
const VulkanUtilities::VulkanPhysicalDevice &GetPhysicalDevice(){return *m_PhysicalDevice;}
const auto &GetLogicalDevice(){return *m_LogicalVkDevice;}
+ FramebufferCache& GetFramebufferCache(){return m_FramebufferCache;}
private:
virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
@@ -193,7 +195,7 @@ private:
std::mutex m_StaleObjectsMutex;
std::deque< ReleaseQueueElemType, STDAllocatorRawMem<ReleaseQueueElemType> > m_StaleVkObjects;
-
+ FramebufferCache m_FramebufferCache;
#if 0
std::mutex m_UploadHeapMutex;
typedef std::unique_ptr<DynamicUploadHeap, STDDeleterRawMem<DynamicUploadHeap> > UploadHeapPoolElemType;
diff --git a/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp b/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp
new file mode 100644
index 00000000..d34564c3
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/FramebufferCache.cpp
@@ -0,0 +1,148 @@
+/* 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 "FramebufferCache.h"
+#include "HashUtils.h"
+#include "RenderDeviceVkImpl.h"
+
+namespace Diligent
+{
+
+
+bool FramebufferCache::FramebufferCacheKey::operator == (const FramebufferCacheKey &rhs)const
+{
+ if (GetHash() != rhs.GetHash() ||
+ Pass != rhs.Pass ||
+ NumRenderTargets != rhs.NumRenderTargets ||
+ DSV != rhs.DSV)
+ {
+ return false;
+ }
+
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ if (RTVs[rt] != rhs.RTVs[rt])
+ return false;
+
+ return true;
+}
+
+size_t FramebufferCache::FramebufferCacheKey::GetHash()const
+{
+ if(Hash == 0)
+ {
+ Hash = ComputeHash(Pass, NumRenderTargets, DSV);
+ for(Uint32 rt = 0; rt < NumRenderTargets; ++rt)
+ HashCombine(Hash, RTVs[rt]);
+ }
+ return Hash;
+}
+
+VkFramebuffer FramebufferCache::GetFramebuffer(const FramebufferCacheKey& Key, uint32_t width, uint32_t height, uint32_t layers)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ auto it = m_Cache.find(Key);
+ if(it != m_Cache.end())
+ {
+ return it->second;
+ }
+ else
+ {
+ VkFramebufferCreateInfo FramebufferCI = {};
+ FramebufferCI.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ FramebufferCI.pNext = nullptr;
+ FramebufferCI.flags = 0; // reserved for future use
+ FramebufferCI.renderPass = Key.Pass;
+ FramebufferCI.attachmentCount = (Key.DSV != VK_NULL_HANDLE ? 1 : 0) + Key.NumRenderTargets;
+ VkImageView Attachments[1 + MaxRenderTargets];
+ uint32_t attachment = 0;
+ if(Key.DSV != VK_NULL_HANDLE)
+ Attachments[attachment++] = Key.DSV;
+ for(Uint32 rt=0; rt < Key.NumRenderTargets; ++rt)
+ Attachments[attachment++] = Key.RTVs[rt];
+ VERIFY_EXPR(attachment == FramebufferCI.attachmentCount);
+ FramebufferCI.pAttachments = Attachments;
+ FramebufferCI.width = width;
+ FramebufferCI.height = height;
+ FramebufferCI.layers = layers;
+ auto Framebuffer = m_DeviceVk.GetLogicalDevice().CreateFramebuffer(FramebufferCI);
+ VkFramebuffer fb = Framebuffer;
+
+ auto new_it = m_Cache.insert(std::make_pair(Key, std::move(Framebuffer)));
+ VERIFY(new_it.second, "New framebuffer must be inserted into the map");
+
+ m_RenderPassToKeyMap.emplace(Key.Pass, Key);
+ if(Key.DSV != VK_NULL_HANDLE)
+ m_ViewToKeyMap.emplace(Key.DSV, Key);
+ for(Uint32 rt=0; rt < Key.NumRenderTargets; ++rt)
+ if(Key.RTVs[rt] != VK_NULL_HANDLE)
+ m_ViewToKeyMap.emplace(Key.RTVs[rt], Key);
+
+ return fb;
+ }
+}
+
+FramebufferCache::~FramebufferCache()
+{
+ VERIFY(m_Cache.empty(), "All framebuffers must be released");
+ VERIFY(m_ViewToKeyMap.empty(), "All image views must be released and the cache must be notified");
+ VERIFY(m_RenderPassToKeyMap.empty(), "All render passes must be released and the cache must be notified");
+}
+
+void FramebufferCache::OnDestroyImageView(VkImageView ImgView)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ auto equal_range = m_ViewToKeyMap.equal_range(ImgView);
+ for(auto it = equal_range.first; it != equal_range.second; ++it)
+ {
+ auto fb_it = m_Cache.find(it->second);
+ // Multiple image views may be associated with the same key.
+ // The framebuffer is deleted whenever any of the image views is deleted
+ if(fb_it != m_Cache.end())
+ {
+ m_DeviceVk.SafeReleaseVkObject(std::move(fb_it->second));
+ m_Cache.erase(fb_it);
+ }
+ }
+ m_ViewToKeyMap.erase(equal_range.first, equal_range.second);
+}
+
+void FramebufferCache::OnDestroyRenderPass(VkRenderPass Pass)
+{
+ std::lock_guard<std::mutex> Lock(m_Mutex);
+ auto equal_range = m_RenderPassToKeyMap.equal_range(Pass);
+ for (auto it = equal_range.first; it != equal_range.second; ++it)
+ {
+ auto fb_it = m_Cache.find(it->second);
+ // Multiple image views may be associated with the same key.
+ // The framebuffer is deleted whenever any of the image views or render pass is destroyed
+ if (fb_it != m_Cache.end())
+ {
+ m_DeviceVk.SafeReleaseVkObject(std::move(fb_it->second));
+ m_Cache.erase(fb_it);
+ }
+ }
+ m_RenderPassToKeyMap.erase(equal_range.first, equal_range.second);
+}
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 17a9216a..3785ba0e 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -439,6 +439,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
PipelineStateVkImpl::~PipelineStateVkImpl()
{
auto pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ pDeviceVkImpl->GetFramebufferCache().OnDestroyRenderPass(m_RenderPass);
pDeviceVkImpl->SafeReleaseVkObject(std::move(m_RenderPass));
pDeviceVkImpl->SafeReleaseVkObject(std::move(m_Pipeline));
pDeviceVkImpl->SafeReleaseVkObject(std::move(m_PipelineLayout));
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index cb90a89d..f6dcdf51 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -76,7 +76,8 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters *pRefCounters,
m_StaleVkObjects(STD_ALLOCATOR_RAW_MEM(ReleaseQueueElemType, GetRawAllocator(), "Allocator for queue<ReleaseQueueElemType>")),/*,
m_UploadHeaps(STD_ALLOCATOR_RAW_MEM(UploadHeapPoolElemType, GetRawAllocator(), "Allocator for vector<unique_ptr<DynamicUploadHeap>>"))
*/
- m_CmdBufferPool(m_LogicalVkDevice->GetSharedPtr(), pCmdQueue->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
+ m_CmdBufferPool(m_LogicalVkDevice->GetSharedPtr(), pCmdQueue->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT),
+ m_FramebufferCache(*this)
{
m_DeviceCaps.DevType = DeviceType::Vulkan;
m_DeviceCaps.MajorVersion = 1;
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
index 48536542..432ead97 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureViewVkImpl.cpp
@@ -43,6 +43,8 @@ TextureViewVkImpl::TextureViewVkImpl( IReferenceCounters *pRefCounters,
TextureViewVkImpl::~TextureViewVkImpl()
{
auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ if(m_Desc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL || m_Desc.ViewType == TEXTURE_VIEW_RENDER_TARGET)
+ pDeviceVkImpl->GetFramebufferCache().OnDestroyImageView(m_ImageView);
pDeviceVkImpl->SafeReleaseVkObject(std::move(m_ImageView));
}