Diligent Engine  v.2.4.g
DescriptorPoolManager.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 // Descriptor heap management utilities.
29 // See http://diligentgraphics.com/diligent-engine/architecture/d3d12/managing-descriptor-heaps/ for details
30 
31 #pragma once
32 
33 #include <vector>
34 #include <deque>
35 #include <mutex>
36 #include <atomic>
37 
39 
40 namespace Diligent
41 {
42 
43 class DescriptorSetAllocator;
44 class RenderDeviceVkImpl;
45 
46 // This class manages descriptor set allocation.
47 // The class destructor calls DescriptorSetAllocator::FreeDescriptorSet() that moves
48 // the set into the release queue.
49 // sizeof(DescriptorSetAllocation) == 32 (x64)
51 {
52 public:
53  // clang-format off
54  DescriptorSetAllocation(VkDescriptorSet _Set,
55  VkDescriptorPool _Pool,
56  Uint64 _CmdQueueMask,
57  DescriptorSetAllocator& _DescrSetAllocator)noexcept :
58  Set {_Set },
59  Pool {_Pool },
60  CmdQueueMask {_CmdQueueMask },
61  DescrSetAllocator{&_DescrSetAllocator}
62  {}
64 
67 
69  Set {rhs.Set },
70  Pool {rhs.Pool },
71  CmdQueueMask {rhs.CmdQueueMask },
72  DescrSetAllocator{rhs.DescrSetAllocator}
73  {
74  rhs.Reset();
75  }
76  // clang-format on
77 
79  {
80  Release();
81 
82  Set = rhs.Set;
83  CmdQueueMask = rhs.CmdQueueMask;
84  Pool = rhs.Pool;
85  DescrSetAllocator = rhs.DescrSetAllocator;
86 
87  rhs.Reset();
88 
89  return *this;
90  }
91 
92  explicit operator bool() const
93  {
94  return Set != VK_NULL_HANDLE;
95  }
96 
97  void Reset()
98  {
99  Set = VK_NULL_HANDLE;
100  Pool = VK_NULL_HANDLE;
101  CmdQueueMask = 0;
102  DescrSetAllocator = nullptr;
103  }
104 
105  void Release();
106 
108  {
109  Release();
110  }
111 
112  VkDescriptorSet GetVkDescriptorSet() const { return Set; }
113 
114 private:
115  VkDescriptorSet Set = VK_NULL_HANDLE;
116  VkDescriptorPool Pool = VK_NULL_HANDLE;
117  Uint64 CmdQueueMask = 0;
118  DescriptorSetAllocator* DescrSetAllocator = nullptr;
119 };
120 
121 
122 // The class manages pool of descriptor set pools
123 // ______________________________
124 // | |
125 // | DescriptorPoolManager |
126 // | |
127 // | | Pool[0] | Pool[1] | ... |
128 // |______________________________|
129 // | A
130 // GetPool() | | FreePool()
131 // V |
132 //
134 {
135 public:
136  // clang-format off
138  std::string PoolName,
139  std::vector<VkDescriptorPoolSize> PoolSizes,
140  uint32_t MaxSets,
141  bool AllowFreeing) noexcept;
143 
148  // clang-format on
149 
150  VulkanUtilities::DescriptorPoolWrapper GetPool(const char* DebugName);
151 
153 
155 
156 #ifdef DILIGENT_DEVELOPMENT
157  int32_t GetAllocatedPoolCounter() const
158  {
159  return m_AllocatedPoolCounter;
160  }
161 #endif
162 
163 protected:
165 
167  const std::string m_PoolName;
168 
169  const std::vector<VkDescriptorPoolSize> m_PoolSizes;
170  const uint32_t m_MaxSets;
171  const bool m_AllowFreeing;
172 
173  std::mutex m_Mutex;
174  std::deque<VulkanUtilities::DescriptorPoolWrapper> m_Pools;
175 
176 private:
177  void FreePool(VulkanUtilities::DescriptorPoolWrapper&& Pool);
178 
179 #ifdef DILIGENT_DEVELOPMENT
180  std::atomic_int32_t m_AllocatedPoolCounter;
181 #endif
182 };
183 
184 
185 // The class allocates descriptor sets from the main descriptor pool.
186 // Descriptors sets can be released and returned to the pool
188 {
189 public:
192  std::string PoolName,
193  std::vector<VkDescriptorPoolSize> PoolSizes,
194  uint32_t MaxSets,
195  bool AllowFreeing) noexcept :
196  // clang-format off
198  {
199  DeviceVkImpl,
200  std::move(PoolName),
201  std::move(PoolSizes),
202  MaxSets,
203  AllowFreeing
204  }
205  // clang-format on
206  {
207 #ifdef DILIGENT_DEVELOPMENT
208  m_AllocatedSetCounter = 0;
209 #endif
210  }
211 
213 
214  DescriptorSetAllocation Allocate(Uint64 CommandQueueMask, VkDescriptorSetLayout SetLayout, const char* DebugName = "");
215 
216 #ifdef DILIGENT_DEVELOPMENT
217  int32_t GetAllocatedDescriptorSetCounter() const
218  {
219  return m_AllocatedSetCounter;
220  }
221 #endif
222 
223 private:
224  void FreeDescriptorSet(VkDescriptorSet Set, VkDescriptorPool Pool, Uint64 QueueMask);
225 
226 #ifdef DILIGENT_DEVELOPMENT
227  std::atomic_int32_t m_AllocatedSetCounter;
228 #endif
229 };
230 
231 
232 // DynamicDescriptorSetAllocator manages dynamic descriptor sets. It first requests descriptor pool from
233 // the global manager and allocates descriptor sets from this pool. When space in the pool is exhausted,
234 // the class requests a new pool.
235 // The class is not thread-safe as device contexts must not be used in multiple threads simultaneously.
236 // All allocated pools are recycled at the end of every frame.
237 // ____________________________________________________________________________
238 // | |
239 // | DynamicDescriptorSetAllocator |
240 // | |
241 // | || DescriptorPool[0] | DescriptorPool[1] | ... | DescriptorPool[N] || |
242 // |__________|_________________________________________________________________|
243 // | A |
244 // | | |
245 // |Allocate() GetPool()| |FreePool()
246 // | _____|___________________V____
247 // V | |
248 // VkDescriptorSet | DescriptorPoolManager |
249 // | |
250 // | |Global dynamic buffer| |
251 // |______________________________|
252 //
254 {
255 public:
257  // clang-format off
258  m_GlobalPoolMgr{PoolMgr },
259  m_Name {std::move(Name)}
260  // clang-format on
261  {}
263 
264  VkDescriptorSet Allocate(VkDescriptorSetLayout SetLayout, const char* DebugName);
265 
266  // Releases all allocated pools that are later returned to the global pool manager.
267  // As global pool manager is hosted by the render device, the allocator can
268  // be destroyed before the pools are actually returned to the global pool manager.
269  void ReleasePools(Uint64 QueueMask);
270 
271  size_t GetAllocatedPoolCount() const { return m_AllocatedPools.size(); }
272 
273 private:
274  DescriptorPoolManager& m_GlobalPoolMgr;
275  const std::string m_Name;
276  std::vector<VulkanUtilities::DescriptorPoolWrapper> m_AllocatedPools;
277  size_t m_PeakPoolCount = 0;
278 };
279 
280 } // namespace Diligent
Diligent::DescriptorPoolManager::DescriptorPoolManager
DescriptorPoolManager(RenderDeviceVkImpl &DeviceVkImpl, std::string PoolName, std::vector< VkDescriptorPoolSize > PoolSizes, uint32_t MaxSets, bool AllowFreeing) noexcept
Definition: DescriptorPoolManager.cpp:82
Diligent::DescriptorSetAllocator
Definition: DescriptorPoolManager.hpp:187
Diligent::DescriptorSetAllocator::DescriptorSetAllocator
DescriptorSetAllocator(RenderDeviceVkImpl &DeviceVkImpl, std::string PoolName, std::vector< VkDescriptorPoolSize > PoolSizes, uint32_t MaxSets, bool AllowFreeing) noexcept
Definition: DescriptorPoolManager.hpp:191
Diligent::DynamicDescriptorSetAllocator::GetAllocatedPoolCount
size_t GetAllocatedPoolCount() const
Definition: DescriptorPoolManager.hpp:271
Diligent::DescriptorSetAllocation::operator=
DescriptorSetAllocation & operator=(const DescriptorSetAllocation &)=delete
Diligent::DynamicDescriptorSetAllocator::~DynamicDescriptorSetAllocator
~DynamicDescriptorSetAllocator()
Definition: DescriptorPoolManager.cpp:318
Diligent::RenderDeviceVkImpl
Render device implementation in Vulkan backend.
Definition: RenderDeviceVkImpl.hpp:58
Diligent::DynamicDescriptorSetAllocator
Definition: DescriptorPoolManager.hpp:253
Diligent::DescriptorPoolManager::operator=
DescriptorPoolManager & operator=(const DescriptorPoolManager &)=delete
Diligent::DescriptorSetAllocation::operator=
DescriptorSetAllocation & operator=(DescriptorSetAllocation &&rhs) noexcept
Definition: DescriptorPoolManager.hpp:78
Diligent::DescriptorSetAllocator::Allocate
DescriptorSetAllocation Allocate(Uint64 CommandQueueMask, VkDescriptorSetLayout SetLayout, const char *DebugName="")
Definition: DescriptorPoolManager.cpp:198
Diligent::Uint64
uint64_t Uint64
64-bit unsigned integer
Definition: BasicTypes.h:50
Diligent::DescriptorSetAllocation::DescriptorSetAllocation
DescriptorSetAllocation(VkDescriptorSet _Set, VkDescriptorPool _Pool, Uint64 _CmdQueueMask, DescriptorSetAllocator &_DescrSetAllocator) noexcept
Definition: DescriptorPoolManager.hpp:54
Diligent::DescriptorPoolManager::m_AllowFreeing
const bool m_AllowFreeing
Definition: DescriptorPoolManager.hpp:171
Diligent::DescriptorPoolManager::m_MaxSets
const uint32_t m_MaxSets
Definition: DescriptorPoolManager.hpp:170
Diligent::DescriptorPoolManager::m_PoolSizes
const std::vector< VkDescriptorPoolSize > m_PoolSizes
Definition: DescriptorPoolManager.hpp:169
VulkanUtilities::DescriptorPoolWrapper
DEFINE_VULKAN_OBJECT_WRAPPER(DescriptorPool) DescriptorPoolWrapper
Definition: VulkanLogicalDevice.hpp:81
Diligent::DescriptorPoolManager::m_PoolName
const std::string m_PoolName
Definition: DescriptorPoolManager.hpp:167
Diligent::DynamicDescriptorSetAllocator::Allocate
VkDescriptorSet Allocate(VkDescriptorSetLayout SetLayout, const char *DebugName)
Definition: DescriptorPoolManager.cpp:290
Diligent::DescriptorSetAllocation::DescriptorSetAllocation
DescriptorSetAllocation(DescriptorSetAllocation &&rhs) noexcept
Definition: DescriptorPoolManager.hpp:68
Diligent::DescriptorSetAllocation
Definition: DescriptorPoolManager.hpp:50
Diligent::DescriptorSetAllocator::DescriptorSetAllocation
friend class DescriptorSetAllocation
Definition: DescriptorPoolManager.hpp:190
Diligent::DescriptorPoolManager::m_Mutex
std::mutex m_Mutex
Definition: DescriptorPoolManager.hpp:173
Diligent::DescriptorPoolManager
Definition: DescriptorPoolManager.hpp:133
Diligent::DescriptorPoolManager::GetPool
VulkanUtilities::DescriptorPoolWrapper GetPool(const char *DebugName)
Definition: DescriptorPoolManager.cpp:106
Diligent::DescriptorSetAllocation::Release
void Release()
Definition: DescriptorPoolManager.cpp:35
Diligent::DynamicDescriptorSetAllocator::DynamicDescriptorSetAllocator
DynamicDescriptorSetAllocator(DescriptorPoolManager &PoolMgr, std::string Name)
Definition: DescriptorPoolManager.hpp:256
Diligent::DescriptorPoolManager::m_DeviceVkImpl
RenderDeviceVkImpl & m_DeviceVkImpl
Definition: DescriptorPoolManager.hpp:166
Diligent::DescriptorPoolManager::m_Pools
std::deque< VulkanUtilities::DescriptorPoolWrapper > m_Pools
Definition: DescriptorPoolManager.hpp:174
Diligent::DescriptorPoolManager::GetDeviceVkImpl
RenderDeviceVkImpl & GetDeviceVkImpl()
Definition: DescriptorPoolManager.hpp:154
Diligent::DynamicDescriptorSetAllocator::ReleasePools
void ReleasePools(Uint64 QueueMask)
Definition: DescriptorPoolManager.cpp:308
Diligent::DescriptorSetAllocation::DescriptorSetAllocation
DescriptorSetAllocation() noexcept
Definition: DescriptorPoolManager.hpp:63
Diligent::DescriptorSetAllocation::Reset
void Reset()
Definition: DescriptorPoolManager.hpp:97
VulkanObjectWrappers.hpp
Diligent::DescriptorPoolManager::~DescriptorPoolManager
~DescriptorPoolManager()
Definition: DescriptorPoolManager.cpp:100
Diligent::DescriptorSetAllocation::~DescriptorSetAllocation
~DescriptorSetAllocation()
Definition: DescriptorPoolManager.hpp:107
Diligent::DescriptorSetAllocation::GetVkDescriptorSet
VkDescriptorSet GetVkDescriptorSet() const
Definition: DescriptorPoolManager.hpp:112
Diligent::DescriptorSetAllocator::~DescriptorSetAllocator
~DescriptorSetAllocator()
Definition: DescriptorPoolManager.cpp:193
Diligent::DescriptorPoolManager::CreateDescriptorPool
VulkanUtilities::DescriptorPoolWrapper CreateDescriptorPool(const char *DebugName) const
Definition: DescriptorPoolManager.cpp:46
Diligent::DescriptorPoolManager::DisposePool
void DisposePool(VulkanUtilities::DescriptorPoolWrapper &&Pool, Uint64 QueueMask)
Definition: DescriptorPoolManager.cpp:124
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37