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_Map.h>
49 #include <UT/UT_StringHolder.h>
50 #include <UT/UT_UniquePtr.h>
51 #include <UT/UT_RWLock.h>
52 
53 #include "RV_VK.h"
54 #include "RV_Type.h"
55 
56 class RV_Instance;
57 class RV_VKCommandBuffer;
59 
60 void
62  int &out_typesize, // size of base type in bytes (e.g 4 or 8)
63  bool &out_is_int, // whether base type is int or float
64  int &out_size, // size of vector type (must do: out_size * out_col_num for matrix size)
65  int &out_align, // alignment of vector elment
66  int &out_vec_num, // number of vector elements
67  int &out_col_num // number of columns
68  );
69 
70 // -----------------
71 // RV_Uniform
72 //
73 // Will be used for UBO members, push constants, opaque-type bindings, etc.
74 /// Type info for a single variable in a shader
76 {
77 public:
78  RV_Uniform() = default;
79 
80  // ctor for opaque type
82  const UT_StringHolder &name,
84  uint32_t count,
85  uint32_t set,
86  uint32_t binding)
87  : RV_Uniform(name, type, count, set, binding,
88  0, 0, 0, 0, UT_Array<RV_Uniform>(), false)
89  {}
90 
91  // ctor for struct members
93  const UT_StringHolder &name,
95  uint32_t count,
96  uint32_t set,
97  uint32_t binding,
98  uint32_t offset,
99  uint32_t base_size,
100  uint32_t array_stride,
101  uint32_t matrix_stride,
103  bool is_active)
104  : myName(name)
105  , myType(type)
106  , arraySize(count)
107  , set(set)
108  , binding(binding)
109  , offset(offset)
110  , baseSize(base_size)
111  , arrayStride(array_stride)
112  , matrixStride(matrix_stride)
113  , members(members)
114  , myIsActive(is_active)
115  {}
116 
117  /// Returns true if there is an SSBO array size for the variable
118  bool isRuntimeArray() const { return arraySize == 0; }
119 
120  // General properties
123  uint32_t arraySize = 1;
124 
125  // Locational info within set
126  uint32_t set = 0;
127  uint32_t binding = 0;
128 
129  // Properties only for Struct Members
130  /// byte offset of member in buffer block
131  uint32_t offset = 0;
132  /// size of base type. Will be raw size for vector/scalar/struct
133  /// and column vec size for matrix
134  uint32_t baseSize = 0;
135  /// offset between elements in an array
136  uint32_t arrayStride = 0;
137  /// offset between columns in a matrix
138  uint32_t matrixStride = 0;
139  /// list of members for struct types
141  // Whether or not the uniform is accessed in shader
142  bool myIsActive = true;
143  // list of members for struct type
145 };
146 
147 // -----------------
148 // RV_VKDescriptorBinding
149 //
150 // A single named binding point in a descriptor set
151 // Also contains RV_Uniforms with extra type info
153 {
154  bool isValid() const;
155 
156  RV_VKDescriptorBinding() = default;
157 
159  const UT_StringHolder& name,
161  uint32_t count,
163  uint32_t binding,
164  uint32_t set,
165  RV_UniformType uniform_type);
166 
168  const UT_StringHolder& name,
169  VkDescriptorType type,
170  uint32_t count,
171  VkShaderStageFlags stages,
172  uint32_t binding,
173  uint32_t set,
174  uint32_t buffer_size,
175  const UT_Array<RV_Uniform>& members);
176 
177  bool isCompatibleToMerge();
178  bool isCompatibleToBind();
179 
180  bool compare(
181  const RV_VKDescriptorBinding& other,
182  bool compare_uniforms_types,
183  bool compare_uniforms_names,
184  bool compare_binding_location,
185  bool compare_binding_stages) const;
186 
187  void merge(const RV_VKDescriptorBinding& other);
188 
189  // Basic Descriptor Type info
191  uint32_t myCount = 0;
192 
193  // Locational info, required for set creation
195  uint32_t myBindingNumber;
196 
197  // Extra info Provided by reflection
198  uint32_t mySetNumber;
200  uint32_t myBufferSize;
202 };
203 
204 // -----------------
205 // RV_VKDescriptorSetInfo
206 //
207 // Info used to create a DescriptorSetLayout object
209 {
210 public:
211  RV_VKDescriptorSetInfo() = default;
212  RV_VKDescriptorSetInfo(int set);
214  int set,
215  const UT_Array<RV_VKDescriptorBinding>& bindings);
216 
218 
219  // Non-const modifiers MUST invalidate hash
220  bool mergeDescriptorSet(const RV_VKDescriptorSetInfo &set);
221  void addBinding(const RV_VKDescriptorBinding& binding);
222 
223  bool isValid() const;
224 
225  // Fill Vulkan create info
226  void fillCreateInfo(
229 
230  bool isCompatibleToBind(const RV_VKDescriptorSetInfo& other) const;
231  bool isCompatibleToMerge(const RV_VKDescriptorSetInfo& other) const;
232  bool isCompatibleToCopy(const RV_VKDescriptorSetInfo& other) const;
233 
234  bool compare( const RV_VKDescriptorSetInfo& other,
235  bool allow_missing_bindings,
236  bool allow_different_stages) const;
237 
238  int getSetNumber() const { return mySet; }
239 
240  exint getLayoutID() const { return myLayoutId; }
241 
242  bool hasBinding(uint32_t b_num) const
243  {
244  return b_num < myBindings.size() &&
245  myBindings(b_num).isValid();
246  }
247  const UT_Array<RV_VKDescriptorBinding>& getBindings() const { return myBindings; }
248 
249  void print() const;
250 
251 public:
252  // Saves hash AND fetches unique ID for layoud from global ID cache
253  void saveHash(RV_Instance* inst);
254  bool isHashValid() const { return myHashValid; }
255 
256  friend SYS_HashType calc_hash(const RV_VKDescriptorSetInfo& in);
258 
259  friend bool operator==( const RV_VKDescriptorSetInfo& lhs,
260  const RV_VKDescriptorSetInfo& rhs);
261 private:
262  int mySet = -1;
265 
266  friend class RV_VKDescriptorSet;
267 
268 private:
269  bool myHashValid = false;
270  size_t myHash;
271  exint myLayoutId;
272 };
273 
274 // -----------------
275 // RV_VKDescriptorLayout
276 //
277 // RAII wrapper for VKDescriptorSetLayout
279 {
280 public:
281  VkDescriptorSetLayout getVkDescriptorSetLayout() const
282  {
283  return myVkDescriptorSetLayout;
284  }
285 
286  static RV_VKDescriptorLayout* create(
287  RV_Instance* inst,
288  const RV_VKDescriptorSetInfo* info);
289 
291  : myInst(other.myInst)
292  , myVkDescriptorSetLayout(other.myVkDescriptorSetLayout)
293  {
294  other.myVkDescriptorSetLayout = nullptr;
295  other.myVkDescriptorSetLayout = VK_NULL_HANDLE;
296  }
297 
299  RV_VKDescriptorLayout &operator=(const RV_VKDescriptorLayout&) = delete;
300  RV_VKDescriptorLayout &operator=(const RV_VKDescriptorLayout&&) = delete;
301 
303 
304 private:
305  RV_VKDescriptorLayout(RV_Instance* inst, VkDescriptorSetLayout vk_layout)
306  : myInst(inst), myVkDescriptorSetLayout(vk_layout)
307  {
308  }
309 
310  RV_Instance* myInst = nullptr;
311  VkDescriptorSetLayout myVkDescriptorSetLayout = VK_NULL_HANDLE;
312 };
313 
314 // ------------------------
315 // RV_VKDescriptorSetUpdates
316 //
317 // Grouped set of updates to apply to a descriptor set
318 // Doesn't have any knowledge of the DescriptorSetLayout
320 {
321 public:
322  bool hasBinding(uint32_t binding, uint32_t element = 0);
323 
324  // NOTE: specific descriptor type for buffer are left out
325  // They will be set from the layout when the updates
326  // are committed
327  void bindBuffer(
328  uint32_t binding,
329  uint32_t element,
330  VkBuffer vk_buf,
332  VkDeviceSize offset = 0,
334 
335  void bindImage(
336  uint32_t binding,
337  uint32_t element,
338  VkImageView img,
339  VkSampler sampler,
340  VkImageLayout layout,
341  VkDescriptorType type);
342 
343  void bindBufferView(
344  uint32_t binding,
345  uint32_t element,
346  VkBufferView buffer_view,
347  VkDescriptorType type);
348 
349  void copyBinding(
350  uint32_t dst_binding,
351  uint32_t dst_element,
352  uint32_t src_binding,
353  uint32_t src_element,
354  uint32_t count = 1);
355 
356  bool isDirty() const;
357 
358  void clear();
359 
362  RV_VKDescriptorSetUpdates() = default;
364 private:
365  // Vk Descriptor Set Updaate Descriptions
368 
369  //
370  // stored as arrays to ptrs, so the memory locations can't move
371  // if the array grows
374  UT_Array<UT_UniquePtr<VkBufferView>> myBufferViewWrites;
375 
376  friend class RV_VKDescriptorSet;
377 };
378 
379 // --------------------
380 // RV_VKDescriptorSet
381 //
382 // RAII Wrapper for VkDescriptorSet object
383 // and also contains RV_VKDescriptorSetInfo used to create it
385 {
386 public:
387  static RV_VKDescriptorSet* create(
388  RV_Instance* inst,
389  class RV_DescriptorAllocator& allocator,
390  const RV_VKDescriptorSetInfo& info,
391  RV_VKDescriptorSetUpdates& descriptor_writes,
392  const RV_VKDescriptorLayout *layout = nullptr,
393  const RV_VKDescriptorSet *copy_src = nullptr,
394  const char* name = nullptr);
395 
397  RV_Instance* inst,
398  VkDescriptorSet vk_set,
399  const RV_VKDescriptorSetInfo& info,
401 
403 
404  VkDescriptorSet getVkDescriptorSet() { return myVkDescriptorSet; }
405  const RV_VKDescriptorSetInfo* getInfo() const { return &myInfo; }
406 
407  bool bindSet(
408  RV_Instance* inst,
409  RV_VKCommandBuffer* cb,
410  const RV_VKPipelineLayout* pipe_layout);
411 
412 private:
413  // UpdateSet should only be called once after creation, to simplify.
414  // If some descriptors need to be changes, a new set must be allocated
415  void updateSet(
416  RV_VKDescriptorSetUpdates& set_updates,
417  const RV_VKDescriptorSet* copy_src = nullptr);
418 
419  RV_Instance* myInst;
420  VkDescriptorSet myVkDescriptorSet;
421  RV_VKDescriptorSetInfo myInfo;
422 
423  // NOTE: DON'T directly access, may be NULL if set created
424  // with externally owned layout. Shouldn't need to access,
425  // but `vkUpdateDescriptorSets()` CAN implicity access the
426  // layout used to create dst/src arguments, so we need
427  // to keep it around, instead of destroying immediately,
428  // if it was created just-in-time during our creation
429  // TODO: probably just always provide externally
431 };
432 
433 // --------------------
434 // RV_VKDescriptorPool
435 //
436 // Wrapper for VkDescriptorPool object used to allocate sets
438 {
439 public:
441  RV_Instance* inst,
443  VkDescriptorPool vk_desc_pool)
444  : myInst(inst), mySizes(sizes), myVkDescPool(vk_desc_pool)
445  {}
446 
447 
449 
450  VkResult allocateSet(VkDescriptorSetLayout layout, VkDescriptorSet& set);
451  VkResult freeSet(VkDescriptorSet set);
452 
453  static RV_VKDescriptorPool* createPool(
454  RV_Instance* inst,
455  uint32_t max_sets,
457 
458  // create with random size ratios
459  static RV_VKDescriptorPool* createPool(
460  RV_Instance* inst,
461  uint32_t max_sets);
462 
463 private:
464  VkDescriptorPool myVkDescPool = VK_NULL_HANDLE;
465  RV_Instance* myInst = nullptr;
467 };
468 
469 // ------------------------
470 // RV_DescriptorAllocator
471 //
472 // Higher level object to handle descriptor set allocations
473 // Used by RV_VKDescriptorSet::create to create Sets, and
474 // allocates more Descriptor Pools as needed
475 //
476 // TODO: track owned allocations for cleanup ?
477 // TODO: synchronize access ? or have per-RV_Render
479 {
480 public:
481 
483 
484  void allocateNewPool();
485 
486  VkDescriptorSet allocateVkDescriptorSet(VkDescriptorSetLayout vk_layout);
487  void freeVkDescriptorSet(VkDescriptorSet vk_set);
488 
490 
491  RV_DescriptorAllocator() = delete;
494 
495  exint getIdForSetLayout(const RV_VKDescriptorSetInfo& info);
496 private:
497  RV_Instance* myInst;
499  uint32_t mySetSize;
500 
502  UT_Map<VkDescriptorSet, int> mySetToPoolTable;
503 
504  // Lock access of `layoutIdCache` and `myNextId` behind `myIdCacheLock`
505  // TODO: look into using more general cache class?
506  UT_RWLock myIdCacheLock;
507  exint myNextId = 1;
509 };
510 
511 #endif
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
Definition: glcorearb.h:2621
const RV_VKDescriptorSetInfo * getInfo() const
uint32_t arraySize
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)
#define VK_NULL_HANDLE
Definition: vulkan_core.h:45
VkResult
Definition: vulkan_core.h:139
GLbitfield stages
Definition: glcorearb.h:1931
VkShaderStageFlags myStages
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()
RV_Uniform()=default
UT_Array< RV_Uniform > myUniforms
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
uint32_t matrixStride
offset between columns in a matrix
VkDescriptorType
Definition: vulkan_core.h:2048
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
CompareResults OIIO_API compare(const ImageBuf &A, const ImageBuf &B, float failthresh, float warnthresh, ROI roi={}, int nthreads=0)
#define VK_WHOLE_SIZE
Definition: vulkan_core.h:131
GLintptr offset
Definition: glcorearb.h:665
bool isRuntimeArray() const
Returns true if there is an SSBO array size for the variable.
RV_UniformType
Definition: RV_Type.h:262
void merge(const RV_VKDescriptorBinding &other)
#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)
bool compare(const RV_VKDescriptorBinding &other, bool compare_uniforms_types, bool compare_uniforms_names, bool compare_binding_location, bool compare_binding_stages) const
RV_UniformType myType
GLuint const GLchar * name
Definition: glcorearb.h:786
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:36
GLint void * img
Definition: glcorearb.h:556
const UT_Array< RV_VKDescriptorBinding > & getBindings() const
VkFlags VkDescriptorSetLayoutCreateFlags
Definition: vulkan_core.h:2693
GLsizeiptr size
Definition: glcorearb.h:664
VkImageLayout
Definition: vulkan_core.h:1250
UT_Array< RV_Uniform > members
list of members for struct types
UT_Array< RV_Uniform > myMembers
uint64_t VkDeviceSize
Definition: vulkan_core.h:95
bool hasBinding(uint32_t b_num) const
bool isValid() const
RV_VKDescriptorLayout(RV_VKDescriptorLayout &&other)
Reader/Writer mutex class.
Definition: UT_RWLock.h:48
RV_VKDescriptorBinding()=default
size_t hash_value(const CH_ChannelRef &ref)
type
Definition: core.h:1059
FMT_INLINE void print(format_string< T...> fmt, T &&...args)
Definition: core.h:2976
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
uint32_t arrayStride
offset between elements in an array