DescriptorSet.h 11 KB

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