DescriptorSet.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Gr/Vulkan/Common.h>
  7. #include <AnKi/Gr/Vulkan/BufferImpl.h>
  8. #include <AnKi/Gr/Vulkan/TextureImpl.h>
  9. #include <AnKi/Gr/Vulkan/TextureViewImpl.h>
  10. #include <AnKi/Gr/Vulkan/SamplerImpl.h>
  11. #include <AnKi/Gr/Vulkan/AccelerationStructureImpl.h>
  12. #include <AnKi/Util/WeakArray.h>
  13. #include <AnKi/Util/BitSet.h>
  14. namespace anki {
  15. // Forward
  16. class DSThreadAllocator;
  17. class DSLayoutCacheEntry;
  18. /// @addtogroup vulkan
  19. /// @{
  20. class alignas(8) DescriptorBinding
  21. {
  22. public:
  23. ShaderTypeBit m_stageMask = ShaderTypeBit::NONE;
  24. DescriptorType m_type = DescriptorType::COUNT;
  25. U8 m_binding = MAX_U8;
  26. U8 m_arraySizeMinusOne = 0;
  27. Array<U8, 3> m_padding = {};
  28. };
  29. static_assert(sizeof(DescriptorBinding) == 8, "Should be packed because it will be hashed");
  30. class DescriptorSetLayoutInitInfo
  31. {
  32. public:
  33. WeakArray<DescriptorBinding> m_bindings;
  34. };
  35. class DescriptorSetLayout
  36. {
  37. friend class DescriptorSetFactory;
  38. friend class DescriptorSetState;
  39. public:
  40. VkDescriptorSetLayout getHandle() const
  41. {
  42. ANKI_ASSERT(m_handle);
  43. return m_handle;
  44. }
  45. Bool isCreated() const
  46. {
  47. return m_handle != VK_NULL_HANDLE;
  48. }
  49. Bool operator==(const DescriptorSetLayout& b) const
  50. {
  51. return m_entry == b.m_entry;
  52. }
  53. Bool operator!=(const DescriptorSetLayout& b) const
  54. {
  55. return !operator==(b);
  56. }
  57. private:
  58. VkDescriptorSetLayout m_handle = VK_NULL_HANDLE;
  59. DSLayoutCacheEntry* m_entry = nullptr;
  60. };
  61. class TextureSamplerBinding
  62. {
  63. public:
  64. VkImageView m_imgViewHandle;
  65. VkSampler m_samplerHandle;
  66. VkImageLayout m_layout;
  67. };
  68. class TextureBinding
  69. {
  70. public:
  71. VkImageView m_imgViewHandle;
  72. VkImageLayout m_layout;
  73. };
  74. class SamplerBinding
  75. {
  76. public:
  77. VkSampler m_samplerHandle;
  78. };
  79. class BufferBinding
  80. {
  81. public:
  82. VkBuffer m_buffHandle;
  83. PtrSize m_offset;
  84. PtrSize m_range;
  85. };
  86. class ImageBinding
  87. {
  88. public:
  89. VkImageView m_imgViewHandle;
  90. };
  91. class AsBinding
  92. {
  93. public:
  94. VkAccelerationStructureKHR m_accelerationStructureHandle;
  95. };
  96. class AnyBinding
  97. {
  98. public:
  99. Array<U64, 2> m_uuids;
  100. union
  101. {
  102. TextureSamplerBinding m_texAndSampler;
  103. TextureBinding m_tex;
  104. SamplerBinding m_sampler;
  105. BufferBinding m_buff;
  106. ImageBinding m_image;
  107. AsBinding m_accelerationStructure;
  108. };
  109. DescriptorType m_type;
  110. };
  111. static_assert(std::is_trivial<AnyBinding>::value, "Shouldn't have constructor for perf reasons");
  112. class AnyBindingExtended
  113. {
  114. public:
  115. union
  116. {
  117. AnyBinding m_single;
  118. AnyBinding* m_array;
  119. };
  120. U32 m_arraySize;
  121. };
  122. static_assert(std::is_trivial<AnyBindingExtended>::value, "Shouldn't have constructor for perf reasons");
  123. /// Descriptor set thin wraper.
  124. class DescriptorSet
  125. {
  126. friend class DescriptorSetFactory;
  127. friend class BindlessDescriptorSet;
  128. friend class DescriptorSetState;
  129. public:
  130. VkDescriptorSet getHandle() const
  131. {
  132. ANKI_ASSERT(m_handle);
  133. return m_handle;
  134. }
  135. private:
  136. VkDescriptorSet m_handle = VK_NULL_HANDLE;
  137. };
  138. /// A state tracker of descriptors.
  139. class DescriptorSetState
  140. {
  141. friend class DescriptorSetFactory;
  142. public:
  143. void init(StackAllocator<U8>& alloc)
  144. {
  145. m_alloc = alloc;
  146. }
  147. void setLayout(const DescriptorSetLayout& layout)
  148. {
  149. if(layout.isCreated())
  150. {
  151. m_layoutDirty = m_layout != layout;
  152. }
  153. else
  154. {
  155. m_layoutDirty = true;
  156. }
  157. m_layout = layout;
  158. }
  159. void bindTextureAndSampler(U32 binding, U32 arrayIdx, const TextureView* texView, const Sampler* sampler,
  160. VkImageLayout layout)
  161. {
  162. const TextureViewImpl& viewImpl = static_cast<const TextureViewImpl&>(*texView);
  163. ANKI_ASSERT(viewImpl.getTextureImpl().isSubresourceGoodForSampling(viewImpl.getSubresource()));
  164. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  165. b = {};
  166. b.m_type = DescriptorType::COMBINED_TEXTURE_SAMPLER;
  167. b.m_uuids[0] = viewImpl.getHash();
  168. b.m_uuids[1] = ptrToNumber(static_cast<const SamplerImpl*>(sampler)->m_sampler->getHandle());
  169. b.m_texAndSampler.m_imgViewHandle = viewImpl.getHandle();
  170. b.m_texAndSampler.m_samplerHandle = static_cast<const SamplerImpl*>(sampler)->m_sampler->getHandle();
  171. b.m_texAndSampler.m_layout = layout;
  172. m_dirtyBindings.set(binding);
  173. unbindBindlessDSet();
  174. }
  175. void bindTexture(U32 binding, U32 arrayIdx, const TextureView* texView, VkImageLayout layout)
  176. {
  177. const TextureViewImpl& viewImpl = static_cast<const TextureViewImpl&>(*texView);
  178. ANKI_ASSERT(viewImpl.getTextureImpl().isSubresourceGoodForSampling(viewImpl.getSubresource()));
  179. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  180. b = {};
  181. b.m_type = DescriptorType::TEXTURE;
  182. b.m_uuids[0] = b.m_uuids[1] = viewImpl.getHash();
  183. b.m_tex.m_imgViewHandle = viewImpl.getHandle();
  184. b.m_tex.m_layout = layout;
  185. m_dirtyBindings.set(binding);
  186. unbindBindlessDSet();
  187. }
  188. void bindSampler(U32 binding, U32 arrayIdx, const Sampler* sampler)
  189. {
  190. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  191. b = {};
  192. b.m_type = DescriptorType::SAMPLER;
  193. b.m_uuids[0] = b.m_uuids[1] = ptrToNumber(static_cast<const SamplerImpl*>(sampler)->m_sampler->getHandle());
  194. b.m_sampler.m_samplerHandle = static_cast<const SamplerImpl*>(sampler)->m_sampler->getHandle();
  195. m_dirtyBindings.set(binding);
  196. unbindBindlessDSet();
  197. }
  198. void bindUniformBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range)
  199. {
  200. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  201. b = {};
  202. b.m_type = DescriptorType::UNIFORM_BUFFER;
  203. b.m_uuids[0] = b.m_uuids[1] = buff->getUuid();
  204. b.m_buff.m_buffHandle = static_cast<const BufferImpl*>(buff)->getHandle();
  205. b.m_buff.m_offset = offset;
  206. b.m_buff.m_range = range;
  207. m_dirtyBindings.set(binding);
  208. unbindBindlessDSet();
  209. }
  210. void bindStorageBuffer(U32 binding, U32 arrayIdx, const Buffer* buff, PtrSize offset, PtrSize range)
  211. {
  212. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  213. b = {};
  214. b.m_type = DescriptorType::STORAGE_BUFFER;
  215. b.m_uuids[0] = b.m_uuids[1] = buff->getUuid();
  216. b.m_buff.m_buffHandle = static_cast<const BufferImpl*>(buff)->getHandle();
  217. b.m_buff.m_offset = offset;
  218. b.m_buff.m_range = range;
  219. m_dirtyBindings.set(binding);
  220. unbindBindlessDSet();
  221. }
  222. void bindImage(U32 binding, U32 arrayIdx, const TextureView* texView)
  223. {
  224. ANKI_ASSERT(texView);
  225. const TextureViewImpl* impl = static_cast<const TextureViewImpl*>(texView);
  226. ANKI_ASSERT(impl->getTextureImpl().isSubresourceGoodForImageLoadStore(impl->getSubresource()));
  227. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  228. b = {};
  229. b.m_type = DescriptorType::IMAGE;
  230. ANKI_ASSERT(impl->getHash());
  231. b.m_uuids[0] = b.m_uuids[1] = impl->getHash();
  232. b.m_image.m_imgViewHandle = impl->getHandle();
  233. m_dirtyBindings.set(binding);
  234. unbindBindlessDSet();
  235. }
  236. void bindAccelerationStructure(U32 binding, U32 arrayIdx, const AccelerationStructure* as)
  237. {
  238. AnyBinding& b = getBindingToPopulate(binding, arrayIdx);
  239. b = {};
  240. b.m_type = DescriptorType::ACCELERATION_STRUCTURE;
  241. b.m_uuids[0] = b.m_uuids[1] = as->getUuid();
  242. b.m_accelerationStructure.m_accelerationStructureHandle =
  243. static_cast<const AccelerationStructureImpl*>(as)->getHandle();
  244. m_dirtyBindings.set(binding);
  245. unbindBindlessDSet();
  246. }
  247. /// Forget all the rest of the bindings and bind the whole bindless descriptor set.
  248. void bindBindlessDescriptorSet()
  249. {
  250. m_bindlessDSetBound = true;
  251. m_bindlessDSetDirty = true;
  252. }
  253. private:
  254. StackAllocator<U8> m_alloc;
  255. DescriptorSetLayout m_layout;
  256. Array<AnyBindingExtended, MAX_BINDINGS_PER_DESCRIPTOR_SET> m_bindings;
  257. U64 m_lastHash = 0;
  258. BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U32> m_dirtyBindings = {true};
  259. BitSet<MAX_BINDINGS_PER_DESCRIPTOR_SET, U32> m_bindingSet = {false};
  260. Bool m_layoutDirty = true;
  261. Bool m_bindlessDSetDirty = true;
  262. Bool m_bindlessDSetBound = false;
  263. /// Only DescriptorSetFactory should call this.
  264. /// @param hash If hash is zero then the DS doesn't need rebind.
  265. void flush(U64& hash, Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets, U32& dynamicOffsetCount,
  266. Bool& bindlessDSet);
  267. void unbindBindlessDSet()
  268. {
  269. m_bindlessDSetBound = false;
  270. }
  271. AnyBinding& getBindingToPopulate(U32 bindingIdx, U32 arrayIdx)
  272. {
  273. ANKI_ASSERT(bindingIdx < MAX_BINDINGS_PER_DESCRIPTOR_SET);
  274. AnyBindingExtended& extended = m_bindings[bindingIdx];
  275. AnyBinding* out;
  276. const Bool bindingIsSet = m_bindingSet.get(bindingIdx);
  277. m_bindingSet.set(bindingIdx);
  278. extended.m_arraySize = (!bindingIsSet) ? 0 : extended.m_arraySize;
  279. if(ANKI_LIKELY(arrayIdx == 0 && extended.m_arraySize <= 1))
  280. {
  281. // Array idx is zero, most common case
  282. out = &extended.m_single;
  283. extended.m_arraySize = 1;
  284. }
  285. else if(arrayIdx < extended.m_arraySize)
  286. {
  287. // It's (or was) an array and there enough space in thar array
  288. out = &extended.m_array[arrayIdx];
  289. }
  290. else
  291. {
  292. // Need to grow
  293. const U32 newSize = max(extended.m_arraySize * 2, arrayIdx + 1);
  294. AnyBinding* newArr = m_alloc.newArray<AnyBinding>(newSize);
  295. if(extended.m_arraySize == 1)
  296. {
  297. newArr[0] = extended.m_single;
  298. }
  299. else if(extended.m_arraySize > 1)
  300. {
  301. // Copy old to new.
  302. memcpy(newArr, extended.m_array, sizeof(AnyBinding) * extended.m_arraySize);
  303. }
  304. // Zero the rest
  305. memset(newArr + extended.m_arraySize, 0, sizeof(AnyBinding) * (newSize - extended.m_arraySize));
  306. extended.m_arraySize = newSize;
  307. extended.m_array = newArr;
  308. // Return
  309. out = &extended.m_array[arrayIdx];
  310. }
  311. ANKI_ASSERT(out);
  312. return *out;
  313. }
  314. };
  315. /// Creates new descriptor set layouts and descriptor sets.
  316. class DescriptorSetFactory
  317. {
  318. friend class DSLayoutCacheEntry;
  319. friend class DSThreadAllocator;
  320. public:
  321. DescriptorSetFactory() = default;
  322. ~DescriptorSetFactory();
  323. ANKI_USE_RESULT Error init(const GrAllocator<U8>& alloc, VkDevice dev, U32 bindlessTextureCount,
  324. U32 bindlessImageCount);
  325. void destroy();
  326. /// @note It's thread-safe.
  327. ANKI_USE_RESULT Error newDescriptorSetLayout(const DescriptorSetLayoutInitInfo& init, DescriptorSetLayout& layout);
  328. /// @note It's thread-safe.
  329. ANKI_USE_RESULT Error newDescriptorSet(ThreadId tid, StackAllocator<U8>& tmpAlloc, DescriptorSetState& state,
  330. DescriptorSet& set, Bool& dirty,
  331. Array<PtrSize, MAX_BINDINGS_PER_DESCRIPTOR_SET>& dynamicOffsets,
  332. U32& dynamicOffsetCount);
  333. void endFrame()
  334. {
  335. ++m_frameCount;
  336. }
  337. /// Bind a sampled image.
  338. /// @note It's thread-safe.
  339. U32 bindBindlessTexture(const VkImageView view, const VkImageLayout layout);
  340. /// Bind a storage image.
  341. /// @note It's thread-safe.
  342. U32 bindBindlessImage(const VkImageView view);
  343. /// @note It's thread-safe.
  344. void unbindBindlessTexture(U32 idx);
  345. /// @note It's thread-safe.
  346. void unbindBindlessImage(U32 idx);
  347. private:
  348. class BindlessDescriptorSet;
  349. GrAllocator<U8> m_alloc;
  350. VkDevice m_dev = VK_NULL_HANDLE;
  351. U64 m_frameCount = 0;
  352. DynamicArray<DSLayoutCacheEntry*> m_caches;
  353. SpinLock m_cachesMtx; ///< Not a mutex because after a while there will be no reason to lock
  354. BindlessDescriptorSet* m_bindless = nullptr;
  355. U32 m_bindlessTextureCount = MAX_U32;
  356. U32 m_bindlessImageCount = MAX_U32;
  357. };
  358. /// @}
  359. } // end namespace anki