HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RV_VKDescriptorSet.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: RV_VKDescriptorSet.h ( RV Library, C++)
7  *
8  * COMMENTS:
9  * Descriptor Sets for Vulkan Pipelines
10  *
11  * Note on naming: trying to keep the naming a little less
12  * confusing than the Vulkan types:
13  * A Descriptor is a single resource in the shader
14  * A Descriptor Binding is a named binding point for
15  * a set of descriptors with the same type
16  * e.g. for array bindings, each element is a descriptor,
17  * for non-arrays the binding is 1 descriptor
18  * A Descriptor [Set/Layout] is a collection of bindings
19  * A Descriptor Set Layout is just an object descibing the layout
20  * A Descriptor Set is the actual object bindable to the pipeline
21  * A Pipeline Layout is a collection of Sets (+ Push Constant ranges)
22  *
23  * Trying to use these terms consistently, as they are less verboase than
24  * the Vulkan types:
25  * [RV Name] [Vulkan Name]
26  * PipelineLayout -> PipelineLayout
27  * DescriptorSet -> DescriptorSet
28  * DescriptorLayout -> DescriptorSetLayout
29  * DescriptorBinding* -> DescriptorSetLayoutBinding*
30  *
31  * * VkDescriptorSetLayoutBinding struct describes binding,
32  * (i.e. is the layout info). There is no object representing
33  * a binding itself, only whole sets
34  *
35  * ALSO adding the uniform, which isn't part of the spec. Uniform refers
36  * struct members for UBO and SSBO types, or the binding itself for other
37  * types: but with extra type info (e.g. the type of sampler/image)
38  *
39  * */
40 
41 #ifndef RV_VKDescriptorSet_h
42 #define RV_VKDescriptorSet_h
43 
44 #include "RV_API.h"
45 
46 #include <SYS/SYS_Hash.h>
47 #include <UT/UT_Array.h>
48 #include <UT/UT_ArrayStringMap.h>
49 #include <UT/UT_Map.h>
50 #include <UT/UT_Lock.h>
51 #include <UT/UT_Set.h>
52 #include <UT/UT_SmallArray.h>
53 #include <UT/UT_StringHolder.h>
54 #include <UT/UT_UniquePtr.h>
55 #include <UT/UT_RWLock.h>
56 
57 #include <VE/VE_VK.h>
58 #include "RV_Type.h"
59 #include "RV_TypePtrs.h"
60 
61 class RV_Instance;
62 class RV_VKCommandBuffer;
64 
65 void
67  int &out_typesize, // size of base type in bytes (e.g 4 or 8)
68  bool &out_is_int, // whether base type is int or float
69  int &out_size, // size of vector type (must do: out_size * out_col_num for matrix size)
70  int &out_align, // alignment of vector elment
71  int &out_vec_num, // number of vector elements
72  int &out_col_num // number of columns
73  );
74 
75 bool
77 
78 // -----------------
79 // RV_Uniform
80 //
81 // Will be used for UBO members, push constants, opaque-type bindings, etc.
82 /// Type info for a single variable in a shader
84 {
85 public:
86  RV_Uniform() = default;
87 
88  // ctor for opaque type
90  const UT_StringHolder &name,
92  uint32_t count,
93  uint32_t set,
94  uint32_t binding)
95  : RV_Uniform(name, type, count, set, binding,
96  0, 0, 0, 0, UT_Array<RV_Uniform>(), false)
97  {}
98 
99  // ctor for struct members
101  const UT_StringHolder &name,
103  uint32_t count,
104  uint32_t set,
105  uint32_t binding,
106  uint32_t offset,
107  uint32_t base_size,
108  uint32_t array_stride,
109  uint32_t matrix_stride,
110  const UT_Array<RV_Uniform>& members,
111  bool is_active)
112  : myName(name)
113  , myType(type)
114  , arraySize(count)
115  , set(set)
116  , binding(binding)
117  , offset(offset)
118  , baseSize(base_size)
119  , arrayStride(array_stride)
120  , matrixStride(matrix_stride)
121  , members(members)
122  , myIsActive(is_active)
123  {}
124 
125  /// Returns true if there is an SSBO array size for the variable
126  bool isRuntimeArray() const { return arraySize == 0; }
127 
128  // General properties
131  uint32_t arraySize = 1;
132 
133  // Locational info within set
134  uint32_t set = 0;
135  uint32_t binding = 0;
136 
137  // Properties only for Struct Members
138  /// byte offset of member in buffer block
139  uint32_t offset = 0;
140  /// size of base type. Will be raw size for vector/scalar/struct
141  /// and column vec size for matrix
142  uint32_t baseSize = 0;
143  /// offset between elements in an array
144  uint32_t arrayStride = 0;
145  /// offset between columns in a matrix
146  uint32_t matrixStride = 0;
147  /// list of members for struct types
149  // Whether or not the uniform is accessed in shader
150  bool myIsActive = true;
151 };
152 
153 // -----------------
154 // RV_VKDescriptorBinding
155 //
156 // A single named binding point in a descriptor set
157 // Also contains RV_Uniforms with extra type info
159 {
160  RV_VKDescriptorBinding() = default;
161 
163  const UT_StringHolder& name,
165  uint32_t count,
167  uint32_t binding,
168  uint32_t set,
169  bool read_only,
170  RV_UniformType uniform_type);
171 
173  const UT_StringHolder& name,
174  VkDescriptorType type,
175  uint32_t count,
176  VkShaderStageFlags stages,
177  uint32_t binding,
178  uint32_t set,
179  bool read_only,
180  uint32_t buffer_size,
181  const UT_Array<RV_Uniform>& members);
182 
183  bool compare(
184  const RV_VKDescriptorBinding& other,
185  bool compare_uniforms_types,
186  bool compare_uniforms_names,
187  bool compare_binding_location,
188  bool compare_binding_stages,
189  UT_WorkBuffer *msg = nullptr) const;
190 
191  void merge(const RV_VKDescriptorBinding& other);
192 
193  inline bool isValid() const
194  {
195  return myCount > 0;
196  }
197 
198  // Basic Descriptor Type info
200  uint32_t myCount = 0;
201 
202  // Locational info, required for set creation
204  uint32_t myBindingNumber;
205 
206  // Extra info Provided by reflection
207  uint32_t mySetNumber;
209  uint32_t myBufferSize;
212 };
213 
214 // -----------------
215 // RV_VKDescriptorSetInfo
216 //
217 // Info used to create a DescriptorSetLayout object
219 {
220 public:
221  RV_VKDescriptorSetInfo() = default;
224  int set,
225  const UT_Array<RV_VKDescriptorBinding>& bindings);
226 
227  // Non-const modifiers MUST invalidate hash
228  bool mergeDescriptorSet(const RV_VKDescriptorSetInfo &set);
229  void addBinding(const RV_VKDescriptorBinding& binding);
230 
231  bool isValid() const;
232 
233  // Fill Vulkan create info
234  void fillCreateInfo(
237 
238  bool isCompatibleToBind(const RV_VKDescriptorSetInfo& other) const;
239  bool isCompatibleToMerge(const RV_VKDescriptorSetInfo& other) const;
240  bool isCompatibleToCopy(const RV_VKDescriptorSetInfo& other) const;
241 
242  bool compare( const RV_VKDescriptorSetInfo& other,
243  bool allow_missing_bindings,
244  bool allow_different_stages,
245  bool allow_different_names,
246  UT_WorkBuffer* msg) const;
247 
248  int getSetNumber() const { return mySet; }
249 
250  bool validLayoutID() const { return myHashValid && myLayoutId != -1; }
251  exint getLayoutID() const { return myLayoutId; }
252 
253  bool hasBinding(uint32_t b_num) const
254  {
255  return b_num < myBindings.size() &&
256  myBindings(b_num).isValid();
257  }
258  const UT_Array<RV_VKDescriptorBinding>& getBindings() const { return myBindings; }
259 
260  void print() const;
261  void printDiff(const RV_VKDescriptorSetInfo& other, const char* label="") const;
262 
263  bool operator== (const RV_VKDescriptorSetInfo& other) const
264  { return compare(other, false, false, false, nullptr); }
265 
266 public:
267  // Saves hash AND fetches unique ID for layoud from global ID cache
268  void saveHash(RV_Instance* inst);
269  bool isHashValid() const { return myHashValid; }
270 
271  SYS_HashType calcHash() const;
272  SYS_HashType getHash() const;
273 private:
274  int mySet = -1;
277 
278  friend class RV_VKDescriptorSet;
279 
280 private:
281  bool myHashValid = false;
282  size_t myHash = 0;
283  exint myLayoutId = -1;
284 };
285 
287 {
288  return in.getHash();
289 }
290 
291 // -----------------
292 // RV_VKDescriptorLayout
293 //
294 // RAII wrapper for VKDescriptorSetLayout
296 {
297 public:
298  VkDescriptorSetLayout getVkDescriptorSetLayout() const
299  {
300  return myVkDescriptorSetLayout;
301  }
302 
303  static RV_VKDescriptorLayoutPtr create(
304  RV_Instance* inst,
305  const RV_VKDescriptorSetInfo* info);
306 
308  : myInst(other.myInst)
309  , myVkDescriptorSetLayout(other.myVkDescriptorSetLayout)
310  {
311  other.myVkDescriptorSetLayout = nullptr;
312  other.myVkDescriptorSetLayout = VK_NULL_HANDLE;
313  }
314 
318 
320 
321 private:
322  struct PassKey {};
323 public:
325  RV_Instance* inst,
326  VkDescriptorSetLayout vk_layout,
327  const PassKey&)
328  : myInst(inst), myVkDescriptorSetLayout(vk_layout)
329  {
330  }
331 
332 private:
333  RV_Instance* myInst = nullptr;
334  VkDescriptorSetLayout myVkDescriptorSetLayout = VK_NULL_HANDLE;
335 };
336 
337 // ------------------------
338 // RV_VKDescriptorSetUpdates
339 //
340 // Grouped set of updates to apply to a descriptor set
341 // Doesn't have any knowledge of the DescriptorSetLayout
343 {
344 public:
345  bool hasBinding(uint32_t binding, uint32_t element = 0);
346 
347  // NOTE: specific descriptor type for buffer are left out
348  // They will be set from the layout when the updates
349  // are committed
350  void bindBuffer(
351  uint32_t binding,
352  uint32_t element,
353  VkBuffer vk_buf,
355  VkDeviceSize offset = 0,
357 
358  void bindImage(
359  uint32_t binding,
360  uint32_t element,
361  VkImageView img,
362  VkSampler sampler,
363  VkImageLayout layout,
364  VkDescriptorType type);
365 
366  void bindBufferView(
367  uint32_t binding,
368  uint32_t element,
369  VkBufferView buffer_view,
370  VkDescriptorType type);
371 
372  void bindAccelStruct(
373  uint32_t binding,
374  uint32_t element,
375  VkAccelerationStructureKHR accel_struct);
376 
377  void copyBinding(
378  uint32_t dst_binding,
379  uint32_t dst_element,
380  uint32_t src_binding,
381  uint32_t src_element,
382  uint32_t count = 1);
383 
384  bool isDirty() const;
385 
386  void clear();
387 
390  RV_VKDescriptorSetUpdates() = default;
392 private:
393  // Vk Descriptor Set Updaate Descriptions
396 
397  //
398  // stored as arrays to ptrs, so the memory locations can't move
399  // if the array grows
402  UT_Array<UT_UniquePtr<VkBufferView>> myBufferViewWrites;
405 
406  friend class RV_VKDescriptorSet;
407 };
408 
409 // --------------------
410 // RV_VKDescriptorSet
411 //
412 // RAII Wrapper for VkDescriptorSet object
413 // and also contains RV_VKDescriptorSetInfo used to create it
415 {
416 public:
417  static UT_UniquePtr<RV_VKDescriptorSet> create(
418  RV_Instance* inst,
419  class RV_DescriptorAllocator& allocator,
420  const RV_VKDescriptorSetInfo& info,
421  RV_VKDescriptorSetUpdates& descriptor_writes,
422  const RV_VKDescriptorLayout *layout = nullptr,
423  const RV_VKDescriptorSet *copy_src = nullptr,
424  const char* name = nullptr);
425 
427  RV_Instance* inst,
428  VkDescriptorSet vk_set,
429  const RV_VKDescriptorSetInfo& info,
431  exint pool_index);
432 
433  void destroy(RV_Instance* inst);
434 
436 
437  RV_VKDescriptorSet(const RV_VKDescriptorSet&) = delete;
439 
440  VkDescriptorSet getVkDescriptorSet() { return myVkDescriptorSet; }
441  const RV_ResourceID &getID() const { return myId; }
442  const RV_VKDescriptorSetInfo* getInfo() const { return myInfo; };
443 
444  bool bindSet(
445  RV_Instance* inst,
446  RV_VKCommandBuffer* cb,
447  const RV_VKPipelineLayout* pipe_layout) const;
448 
449 private:
450  // UpdateSet should only be called once after creation, to simplify.
451  // If some descriptors need to be changes, a new set must be allocated
452  void updateSet(
453  RV_VKDescriptorSetUpdates& set_updates,
454  const RV_VKDescriptorSet* copy_src = nullptr);
455 
456  RV_Instance* myInst;
457  VkDescriptorSet myVkDescriptorSet;
458  const RV_VKDescriptorSetInfo* myInfo;
459  RV_ResourceID myId;
460 
461  exint myPoolIdx;
462  exint myLayoutId;
463 
464  // NOTE: DON'T directly access, may be NULL if set created
465  // with externally owned layout. Shouldn't need to access,
466  // but `vkUpdateDescriptorSets()` CAN implicity access the
467  // layout used to create dst/src arguments, so we need
468  // to keep it around, instead of destroying immediately,
469  // if it was created just-in-time during our creation
470  // TODO: probably just always provide externally
472 };
473 
474 // --------------------
475 // RV_VKDescriptorPool
476 //
477 // Wrapper for VkDescriptorPool object used to allocate sets
479 {
480 public:
482  RV_Instance* inst,
484  VkDescriptorPool vk_desc_pool)
485  : myInst(inst), mySizes(sizes), myVkDescPool(vk_desc_pool)
486  {}
487 
489 
490  VkResult allocateSet(VkDescriptorSetLayout layout, VkDescriptorSet& set);
491  VkResult freeSet(VkDescriptorSet set);
492  bool containsSet(VkDescriptorSet set) const;
493 
494  static RV_VKDescriptorPoolPtr createPool(
495  RV_Instance* inst,
496  uint32_t max_sets,
498 
499  // create with random size ratios
500  static RV_VKDescriptorPoolPtr createPool(
501  RV_Instance* inst,
502  uint32_t max_sets);
503 
504  bool myHasSpace = true;
505  exint mySetCount = 0;
506  exint mySetUpperLimit = 0;
507 private:
508  UT_Lock myLock;
509  VkDescriptorPool myVkDescPool = VK_NULL_HANDLE;
510  RV_Instance* myInst = nullptr;
513 
514  friend RV_DescriptorAllocator;
515 };
516 
517 // ------------------------
518 // RV_DescriptorAllocator
519 //
520 // Higher level object to handle descriptor set allocations
521 // Used by RV_VKDescriptorSet::create to create Sets, and
522 // allocates more Descriptor Pools as needed
523 //
524 // TODO: track owned allocations for cleanup ?
526 {
527 public:
528 
530 
531  std::pair<VkDescriptorSet, exint> allocateVkDescriptorSet(
532  VkDescriptorSetLayout vk_layout);
533 
534  void freeVkDescriptorSet(VkDescriptorSet vk_set, int pool_idx = -1);
535 
537 
538  RV_DescriptorAllocator() = delete;
541 
542  exint getIdForSetLayout(const RV_VKDescriptorSetInfo& info);
544  {
548  };
549 
550  const RV_VKDescriptorSetInfo* getSetLayoutFromId(exint id);
551  const RV_VKDescriptorLayout* getSetLayoutObjectFromId(exint id);
552  const UT_ArrayStringMap<int>* getBindingTableFromId(exint id);
553  CachedSetLayoutInfo getCachedSetInfoFromId(exint id);
554 
555  exint getNumPools() const { return myPools.size(); }
556 
557 private:
558  bool allocateNewPool();
559 
560  RV_Instance* myInst;
562  uint32_t mySetSize;
563 
564  UT_Lock myPoolLock;
566 
567  UT_Array<int> myPoolsWithSpace;
568 
569  // Lock access of `layoutIdCache` and `myNextId` behind `myIdCacheLock`
570  // TODO: look into using more general cache class?
571  UT_Lock myIdCacheLock2;
572  exint myNextId = 1;
577 };
578 
579 #endif
const RV_VKDescriptorSetInfo * mySetLayout
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
Definition: glcorearb.h:2621
const RV_VKDescriptorSetInfo * getInfo() const
RV_Uniform(const UT_StringHolder &name, RV_UniformType type, uint32_t count, uint32_t set, uint32_t binding, uint32_t offset, uint32_t base_size, uint32_t array_stride, uint32_t matrix_stride, const UT_Array< RV_Uniform > &members, bool is_active)
GLuint GLsizei const GLchar * label
Definition: glcorearb.h:2545
#define VK_NULL_HANDLE
Definition: vulkan_core.h:45
VkResult
Definition: vulkan_core.h:139
GLbitfield stages
Definition: glcorearb.h:1931
VkShaderStageFlags myStages
const RV_ResourceID & getID() const
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, float failrelative, float warnrelative, ROI roi={}, int nthreads=0)
int64 exint
Definition: SYS_Types.h:125
std::size_t SYS_HashType
Define the type for hash values.
Definition: SYS_Hash.h:19
void RVgetUniformSize(RV_UniformType type, int &out_typesize, bool &out_is_int, int &out_size, int &out_align, int &out_vec_num, int &out_col_num)
GLuint sampler
Definition: glcorearb.h:1656
VkDescriptorSet getVkDescriptorSet()
constexpr auto in(type t, int set) -> bool
Definition: core.h:611
UT_UniquePtr< RV_VKDescriptorPool > RV_VKDescriptorPoolPtr
Definition: RV_TypePtrs.h:67
UT_Array< RV_Uniform > myUniforms
UT_UniquePtr< RV_VKDescriptorLayout > RV_VKDescriptorLayoutPtr
Definition: RV_TypePtrs.h:68
UT_StringHolder myName
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
VkDescriptorType
Definition: vulkan_core.h:2048
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
bool RVtryToUseUpdateAfterBind()
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
#define VK_WHOLE_SIZE
Definition: vulkan_core.h:131
GLintptr offset
Definition: glcorearb.h:665
const RV_VKDescriptorLayout * mySetLayoutObject
constexpr auto set(type rhs) -> int
Definition: core.h:610
bool isRuntimeArray() const
Returns true if there is an SSBO array size for the variable.
RV_UniformType
Definition: RV_Type.h:240
SYS_HashType hash_value(const RV_VKDescriptorSetInfo &in)
const UT_ArrayStringMap< int > * myBindingTable
#define RV_API
Definition: RV_API.h:10
RV_Uniform(const UT_StringHolder &name, RV_UniformType type, uint32_t count, uint32_t set, uint32_t binding)
GLuint const GLchar * name
Definition: glcorearb.h:786
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:48
GLint void * img
Definition: glcorearb.h:556
const UT_Array< RV_VKDescriptorBinding > & getBindings() const
RV_VKDescriptorLayout(RV_Instance *inst, VkDescriptorSetLayout vk_layout, const PassKey &)
VkFlags VkDescriptorSetLayoutCreateFlags
Definition: vulkan_core.h:2693
GLsizeiptr size
Definition: glcorearb.h:664
VkImageLayout
Definition: vulkan_core.h:1250
LeafData & operator=(const LeafData &)=delete
UT_Array< RV_Uniform > members
list of members for struct types
uint64_t VkDeviceSize
Definition: vulkan_core.h:95
bool hasBinding(uint32_t b_num) const
SYS_HashType getHash() const
OutGridT XformOp bool bool MergePolicy merge
RV_VKDescriptorLayout(RV_VKDescriptorLayout &&other)
FMT_INLINE void print(format_string< T...> fmt, T &&...args)
Definition: core.h:2903
VkDescriptorSetLayout getVkDescriptorSetLayout() const
Type info for a single variable in a shader.
GLint GLsizei count
Definition: glcorearb.h:405
RV_VKDescriptorPool(RV_Instance *inst, const UT_Array< VkDescriptorPoolSize > &sizes, VkDescriptorPool vk_desc_pool)
VkFlags VkShaderStageFlags
Definition: vulkan_core.h:2660