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 // -----------------
76 // RV_Uniform
77 //
78 // Will be used for UBO members, push constants, opaque-type bindings, etc.
79 /// Type info for a single variable in a shader
81 {
82 public:
83  RV_Uniform() = default;
84 
85  // ctor for opaque type
87  const UT_StringHolder &name,
89  uint32_t count,
90  uint32_t set,
91  uint32_t binding)
92  : RV_Uniform(name, type, count, set, binding,
93  0, 0, 0, 0, UT_Array<RV_Uniform>(), false)
94  {}
95 
96  // ctor for struct members
98  const UT_StringHolder &name,
100  uint32_t count,
101  uint32_t set,
102  uint32_t binding,
103  uint32_t offset,
104  uint32_t base_size,
105  uint32_t array_stride,
106  uint32_t matrix_stride,
107  const UT_Array<RV_Uniform>& members,
108  bool is_active)
109  : myName(name)
110  , myType(type)
111  , arraySize(count)
112  , set(set)
113  , binding(binding)
114  , offset(offset)
115  , baseSize(base_size)
116  , arrayStride(array_stride)
117  , matrixStride(matrix_stride)
118  , members(members)
119  , myIsActive(is_active)
120  {}
121 
122  /// Returns true if there is an SSBO array size for the variable
123  bool isRuntimeArray() const { return arraySize == 0; }
124 
125  // General properties
128  uint32_t arraySize = 1;
129 
130  // Locational info within set
131  uint32_t set = 0;
132  uint32_t binding = 0;
133 
134  // Properties only for Struct Members
135  /// byte offset of member in buffer block
136  uint32_t offset = 0;
137  /// size of base type. Will be raw size for vector/scalar/struct
138  /// and column vec size for matrix
139  uint32_t baseSize = 0;
140  /// offset between elements in an array
141  uint32_t arrayStride = 0;
142  /// offset between columns in a matrix
143  uint32_t matrixStride = 0;
144  /// list of members for struct types
146  // Whether or not the uniform is accessed in shader
147  bool myIsActive = true;
148 };
149 
150 // -----------------
151 // RV_VKDescriptorBinding
152 //
153 // A single named binding point in a descriptor set
154 // Also contains RV_Uniforms with extra type info
156 {
157  RV_VKDescriptorBinding() = default;
158 
160  const UT_StringHolder& name,
162  uint32_t count,
164  uint32_t binding,
165  uint32_t set,
166  RV_UniformType uniform_type);
167 
169  const UT_StringHolder& name,
170  VkDescriptorType type,
171  uint32_t count,
172  VkShaderStageFlags stages,
173  uint32_t binding,
174  uint32_t set,
175  uint32_t buffer_size,
176  const UT_Array<RV_Uniform>& members);
177 
178  bool compare(
179  const RV_VKDescriptorBinding& other,
180  bool compare_uniforms_types,
181  bool compare_uniforms_names,
182  bool compare_binding_location,
183  bool compare_binding_stages,
184  UT_WorkBuffer *msg = nullptr) const;
185 
186  void merge(const RV_VKDescriptorBinding& other);
187 
188  inline bool isValid() const
189  {
190  return myCount > 0;
191  }
192 
193  // Basic Descriptor Type info
195  uint32_t myCount = 0;
196 
197  // Locational info, required for set creation
199  uint32_t myBindingNumber;
200 
201  // Extra info Provided by reflection
202  uint32_t mySetNumber;
204  uint32_t myBufferSize;
206 };
207 
208 // -----------------
209 // RV_VKDescriptorSetInfo
210 //
211 // Info used to create a DescriptorSetLayout object
213 {
214 public:
215  RV_VKDescriptorSetInfo() = default;
218  int set,
219  const UT_Array<RV_VKDescriptorBinding>& bindings);
220 
221  // Non-const modifiers MUST invalidate hash
222  bool mergeDescriptorSet(const RV_VKDescriptorSetInfo &set);
223  void addBinding(const RV_VKDescriptorBinding& binding);
224 
225  bool isValid() const;
226 
227  // Fill Vulkan create info
228  void fillCreateInfo(
231 
232  bool isCompatibleToBind(const RV_VKDescriptorSetInfo& other) const;
233  bool isCompatibleToMerge(const RV_VKDescriptorSetInfo& other) const;
234  bool isCompatibleToCopy(const RV_VKDescriptorSetInfo& other) const;
235 
236  bool compare( const RV_VKDescriptorSetInfo& other,
237  bool allow_missing_bindings,
238  bool allow_different_stages,
239  bool allow_different_names,
240  UT_WorkBuffer* msg) const;
241 
242  int getSetNumber() const { return mySet; }
243 
244  exint getLayoutID() const { return myLayoutId; }
245 
246  bool hasBinding(uint32_t b_num) const
247  {
248  return b_num < myBindings.size() &&
249  myBindings(b_num).isValid();
250  }
251  const UT_Array<RV_VKDescriptorBinding>& getBindings() const { return myBindings; }
252 
253  void print() const;
254  void printDiff(const RV_VKDescriptorSetInfo& other, const char* label="") const;
255 
256  bool operator== (const RV_VKDescriptorSetInfo& other) const
257  { return compare(other, false, false, false, nullptr); }
258 
259 public:
260  // Saves hash AND fetches unique ID for layoud from global ID cache
261  void saveHash(RV_Instance* inst);
262  bool isHashValid() const { return myHashValid; }
263 
264  SYS_HashType calcHash() const;
265  SYS_HashType getHash() const;
266 private:
267  int mySet = -1;
270 
271  friend class RV_VKDescriptorSet;
272 
273 private:
274  bool myHashValid = false;
275  size_t myHash;
276  exint myLayoutId;
277 };
278 
280 {
281  return in.getHash();
282 }
283 
284 // -----------------
285 // RV_VKDescriptorLayout
286 //
287 // RAII wrapper for VKDescriptorSetLayout
289 {
290 public:
291  VkDescriptorSetLayout getVkDescriptorSetLayout() const
292  {
293  return myVkDescriptorSetLayout;
294  }
295 
296  static RV_VKDescriptorLayoutPtr create(
297  RV_Instance* inst,
298  const RV_VKDescriptorSetInfo* info);
299 
301  : myInst(other.myInst)
302  , myVkDescriptorSetLayout(other.myVkDescriptorSetLayout)
303  {
304  other.myVkDescriptorSetLayout = nullptr;
305  other.myVkDescriptorSetLayout = VK_NULL_HANDLE;
306  }
307 
311 
313 
314 private:
315  struct PassKey {};
316 public:
318  RV_Instance* inst,
319  VkDescriptorSetLayout vk_layout,
320  const PassKey&)
321  : myInst(inst), myVkDescriptorSetLayout(vk_layout)
322  {
323  }
324 
325 private:
326  RV_Instance* myInst = nullptr;
327  VkDescriptorSetLayout myVkDescriptorSetLayout = VK_NULL_HANDLE;
328 };
329 
330 // ------------------------
331 // RV_VKDescriptorSetUpdates
332 //
333 // Grouped set of updates to apply to a descriptor set
334 // Doesn't have any knowledge of the DescriptorSetLayout
336 {
337 public:
338  bool hasBinding(uint32_t binding, uint32_t element = 0);
339 
340  // NOTE: specific descriptor type for buffer are left out
341  // They will be set from the layout when the updates
342  // are committed
343  void bindBuffer(
344  uint32_t binding,
345  uint32_t element,
346  VkBuffer vk_buf,
348  VkDeviceSize offset = 0,
350 
351  void bindImage(
352  uint32_t binding,
353  uint32_t element,
354  VkImageView img,
355  VkSampler sampler,
356  VkImageLayout layout,
357  VkDescriptorType type);
358 
359  void bindBufferView(
360  uint32_t binding,
361  uint32_t element,
362  VkBufferView buffer_view,
363  VkDescriptorType type);
364 
365  void bindAccelStruct(
366  uint32_t binding,
367  uint32_t element,
368  VkAccelerationStructureKHR accel_struct);
369 
370  void copyBinding(
371  uint32_t dst_binding,
372  uint32_t dst_element,
373  uint32_t src_binding,
374  uint32_t src_element,
375  uint32_t count = 1);
376 
377  bool isDirty() const;
378 
379  void clear();
380 
383  RV_VKDescriptorSetUpdates() = default;
385 private:
386  // Vk Descriptor Set Updaate Descriptions
389 
390  //
391  // stored as arrays to ptrs, so the memory locations can't move
392  // if the array grows
395  UT_Array<UT_UniquePtr<VkBufferView>> myBufferViewWrites;
398 
399  friend class RV_VKDescriptorSet;
400 };
401 
402 // --------------------
403 // RV_VKDescriptorSet
404 //
405 // RAII Wrapper for VkDescriptorSet object
406 // and also contains RV_VKDescriptorSetInfo used to create it
408 {
409 public:
410  static UT_UniquePtr<RV_VKDescriptorSet> create(
411  RV_Instance* inst,
412  class RV_DescriptorAllocator& allocator,
413  const RV_VKDescriptorSetInfo& info,
414  RV_VKDescriptorSetUpdates& descriptor_writes,
415  const RV_VKDescriptorLayout *layout = nullptr,
416  const RV_VKDescriptorSet *copy_src = nullptr,
417  const char* name = nullptr);
418 
420  RV_Instance* inst,
421  VkDescriptorSet vk_set,
422  const RV_VKDescriptorSetInfo& info,
424  exint pool_index);
425 
427 
428  RV_VKDescriptorSet(const RV_VKDescriptorSet&) = delete;
430 
431  VkDescriptorSet getVkDescriptorSet() { return myVkDescriptorSet; }
432  const RV_ResourceID &getID() const { return myId; }
433  const RV_VKDescriptorSetInfo* getInfo() const { return myInfo; };
434 
435  bool bindSet(
436  RV_Instance* inst,
437  RV_VKCommandBuffer* cb,
438  const RV_VKPipelineLayout* pipe_layout) const;
439 
440 private:
441  // UpdateSet should only be called once after creation, to simplify.
442  // If some descriptors need to be changes, a new set must be allocated
443  void updateSet(
444  RV_VKDescriptorSetUpdates& set_updates,
445  const RV_VKDescriptorSet* copy_src = nullptr);
446 
447  RV_Instance* myInst;
448  VkDescriptorSet myVkDescriptorSet;
449  const RV_VKDescriptorSetInfo* myInfo;
450  RV_ResourceID myId;
451 
452  exint myPoolIdx;
453  exint myLayoutId;
454 
455  // NOTE: DON'T directly access, may be NULL if set created
456  // with externally owned layout. Shouldn't need to access,
457  // but `vkUpdateDescriptorSets()` CAN implicity access the
458  // layout used to create dst/src arguments, so we need
459  // to keep it around, instead of destroying immediately,
460  // if it was created just-in-time during our creation
461  // TODO: probably just always provide externally
463 };
464 
465 // --------------------
466 // RV_VKDescriptorPool
467 //
468 // Wrapper for VkDescriptorPool object used to allocate sets
470 {
471 public:
473  RV_Instance* inst,
475  VkDescriptorPool vk_desc_pool)
476  : myInst(inst), mySizes(sizes), myVkDescPool(vk_desc_pool)
477  {}
478 
480 
481  VkResult allocateSet(VkDescriptorSetLayout layout, VkDescriptorSet& set);
482  VkResult freeSet(VkDescriptorSet set);
483  bool containsSet(VkDescriptorSet set) const;
484 
485  static RV_VKDescriptorPoolPtr createPool(
486  RV_Instance* inst,
487  uint32_t max_sets,
489 
490  // create with random size ratios
491  static RV_VKDescriptorPoolPtr createPool(
492  RV_Instance* inst,
493  uint32_t max_sets);
494 
495  bool myHasSpace = true;
496  exint mySetCount = 0;
497  exint mySetUpperLimit = 0;
498 private:
499  UT_Lock myLock;
500  VkDescriptorPool myVkDescPool = VK_NULL_HANDLE;
501  RV_Instance* myInst = nullptr;
504 
505  friend RV_DescriptorAllocator;
506 };
507 
508 // ------------------------
509 // RV_DescriptorAllocator
510 //
511 // Higher level object to handle descriptor set allocations
512 // Used by RV_VKDescriptorSet::create to create Sets, and
513 // allocates more Descriptor Pools as needed
514 //
515 // TODO: track owned allocations for cleanup ?
517 {
518 public:
519 
521 
522  std::pair<VkDescriptorSet, exint> allocateVkDescriptorSet(
523  VkDescriptorSetLayout vk_layout);
524 
525  void freeVkDescriptorSet(VkDescriptorSet vk_set, int pool_idx = -1);
526 
528 
529  RV_DescriptorAllocator() = delete;
532 
533  exint getIdForSetLayout(const RV_VKDescriptorSetInfo& info);
534  const RV_VKDescriptorSetInfo* getSetLayoutFromId(exint id);
535 
536  exint getNumPools() const { return myPools.size(); }
537 
538 private:
539  bool allocateNewPool();
540 
541  RV_Instance* myInst;
543  uint32_t mySetSize;
544 
545  UT_Lock myPoolLock;
547 
548  UT_Array<int> myPoolsWithSpace;
549 
550  // Lock access of `layoutIdCache` and `myNextId` behind `myIdCacheLock`
551  // TODO: look into using more general cache class?
552  UT_Lock myIdCacheLock2;
553  exint myNextId = 1;
556 };
557 
558 #endif
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
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
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:332
SYS_HashType hash_value(const RV_VKDescriptorSetInfo &in)
#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:44
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