HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RV_ShaderBlock.h
Go to the documentation of this file.
1 
2 /*
3  * PROPRIETARY INFORMATION. This software is proprietary to
4  * Side Effects Software Inc., and is not to be reproduced,
5  * transmitted, or disclosed in any way without written permission.
6  *
7  * NAME: RV_ShaderBlock.h ( RV Library, C++)
8  *
9  * COMMENTS:
10  * Class to handle Shader SSBO and UBO blocks
11  */
12 
13 #ifndef RV_ShaderBlock_h
14 #define RV_ShaderBlock_h
15 
16 #include "RV_API.h"
17 #include "RV_Instance.h"
18 #include "RV_VKBuffer.h"
19 #include "RV_VKDescriptorSet.h"
20 #include "RV_VKShaderModule.h"
21 
22 #include <VE/VE_VK.h>
23 
24 #include <UT/UT_Array.h>
25 #include <UT/UT_Map.h>
26 #include <UT/UT_Matrix2.h>
27 #include <UT/UT_Matrix3.h>
28 #include <UT/UT_Matrix4.h>
29 #include <UT/UT_NonCopyable.h>
30 #include <UT/UT_Span.h>
31 #include <UT/UT_String.h>
32 #include <UT/UT_StringMap.h>
33 #include <UT/UT_Vector2.h>
34 #include <UT/UT_Vector3.h>
35 #include <UT/UT_Vector4.h>
36 #include <UT/UT_VectorTypes.h>
37 #include <UT/UT_WorkBuffer.h>
38 
39 #include <typeinfo>
40 #include <utility>
41 
42 
43 class RV_Render;
44 class RV_ShaderProgram;
45 class GR_Uniforms;
46 
47 #if 0
48 struct UniformLocation
49 {
50  // name lookup
51  UniformLocation(const char* name)
52  : owned_stringref(name), name(&owned_stringref)
53  {
54  }
55  UniformLocation(const UT_StringRef& name)
56  : name(&name)
57  {
58  }
59 
60  // index lookup
61  UniformLocation(int idx)
62  : owned_idx(idx), idx(&owned_idx)
63  {
64  }
65 
66  // name lookup and store index
67  UniformLocation(const char* name, int* idx)
68  : owned_stringref(name), name(&owned_stringref), idx(idx)
69  {
70  }
71  UniformLocation(const UT_StringRef& name, int* idx)
72  : name(&name), idx(idx)
73  {
74  }
75 
76  UT_StringRef owned_stringref;
77  const UT_StringRef* name = nullptr;
78  int owned_idx;
79  int* idx = nullptr;
80 };
81 #endif
82 
83 // Helper class to hold type-checked bind functions for the RV_Uniform class
84 // and RV_PushConstants
85 // Must be inherited by a child class to be used
86 // Relies on the child class implementing:
87 // - getUniform(): to return the uniform
88 // - copyToBuffer(): to set data of the uniform if checks pass
89 // - copyToBufferStride(): to set uniforms that need to have
90 // padding between elements (e.g. vec3 arrays, mat3)
91 
92 /// Helper tie-in class for binding functions for UBOs and SSBOs
94 {
95 public:
96 
98 
99  /// Set the value of the uniform 'name' with a block of memory
100  bool bindUniform(const UT_StringRef& name,
102  const void* data, exint data_size,
103  int array_index = 0,
104  int array_range = 1,
105  int* opt_idx = nullptr);
106 
107  /// Copy the data for uniform 'name' into the buffer. If name does not
108  /// exist in the buffer, or its type/array size doesn't match,
109  /// bind...() will return false. If its value is not different from the
110  /// current value in the block, it will not cause an upload.
111  /// Shader Storage Blocks can have open-ended arrays, and variables within
112  /// those arrays can specify their array index with 'array_index'.
113  bool bindInt(const UT_StringRef& name, int v,
114  int array_index = 0,
115  int* opt_idx = nullptr);
116  /// Bind a single float value.
117  bool bindFloat(const UT_StringRef& name, fpreal32 v,
118  int array_index = 0,
119  int* opt_idx = nullptr);
120  /// Bind a single double value. GPU must support native FP64 values.
121  bool bindDouble(const UT_StringRef& name, fpreal64 v,
122  int array_index = 0,
123  int* opt_idx = nullptr);
124  /// Bind a single handle value to a sampler. GPU must support bindless
125  /// textures.
126  bool bindUint64(const UT_StringRef& name,
127  uint64 v,
128  int array_index = 0,
129  int* opt_idx = nullptr);
130 
131  /// Set values for a fixed-length integer array.
132  bool bindInts(const UT_StringRef& name,
133  const int *valarray,
134  int array_size,
135  int array_index = 0,
136  int* opt_idx = nullptr);
137  /// Set values for a fixed-length float array.
138  bool bindFloats(const UT_StringRef& name,
139  const fpreal32 *valarray,
140  int array_size,
141  int array_index = 0,
142  int* opt_idx = nullptr);
143 
144  /// Set values for a fixed-length double array.
145  bool bindDoubles(const UT_StringRef& name,
146  const fpreal64 *valarray,
147  int array_size,
148  int array_index = 0,
149  int* opt_idx = nullptr);
150  /// Set values for a uint64 handle array.
151  bool bindUint64s(const UT_StringRef& name,
152  const uint64 *valarray,
153  int array_size,
154  int array_index = 0,
155  int* opt_idx = nullptr);
156 
157  /// vec3 is a little different, as it is padded to vec4 in uniform blocks.
158  /// SSBOs with std420 packing should use bindVector().
159 
160  /// bind a series of ivec3s, using std140 packing (padded to ivec4)
161  bool bindIntVector3(const UT_StringRef& name,
162  const int *valarray,
163  int array_size,
164  int array_index = 0,
165  int* opt_idx = nullptr);
166 
167  /// bind a series of vec3s, using std140 packing (padded to ivec4)
168  bool bindVector3(const UT_StringRef& name,
169  const fpreal32 *valarray,
170  int array_size,
171  int array_index = 0,
172  int* opt_idx = nullptr);
173 
174  /// bind a series of dvec3s, using std140 packing (padded to ivec4)
175  bool bindDVector3(const UT_StringRef& name,
176  const fpreal64 *valarray,
177  int array_size,
178  int array_index = 0,
179  int* opt_idx = nullptr);
180 
181  /// Bind a single vec2 uniform value.
182  bool bindVector(const UT_StringRef& name,
183  const UT_Vector2F &v,
184  int array_index = 0,
185  int* opt_idx = nullptr);
186  /// Bind a single vec3 uniform value.
187  bool bindVector(const UT_StringRef& name,
188  const UT_Vector3F &v,
189  int array_index = 0,
190  int* opt_idx = nullptr);
191  /// Bind a single vec4 uniform value.
192  bool bindVector(const UT_StringRef& name,
193  const UT_Vector4F &v,
194  int array_index = 0,
195  int* opt_idx = nullptr);
196 
197  /// Bind a single dvec2 uniform value.
198  bool bindVector(const UT_StringRef& name,
199  const UT_Vector2D &v,
200  int array_index = 0,
201  int* opt_idx = nullptr);
202 
203  /// Set a single dvec3 uniform value.
204  bool bindVector(const UT_StringRef& name,
205  const UT_Vector3D &v,
206  int array_index = 0,
207  int* opt_idx = nullptr);
208  /// Set a single dvec4 uniform value.
209  bool bindVector(const UT_StringRef& name,
210  const UT_Vector4D &v,
211  int array_index = 0,
212  int* opt_idx = nullptr);
213 
214  /// Bind a single ivec2 uniform value.
215  bool bindVector(const UT_StringRef& name,
216  const UT_Vector2i &v,
217  int array_index = 0,
218  int* opt_idx = nullptr);
219 
220  /// Set a single ivec3 uniform value.
221  bool bindVector(const UT_StringRef& name,
222  const UT_Vector3i &v,
223  int array_index = 0,
224  int* opt_idx = nullptr);
225  /// Set a single ivec4 uniform value.
226  bool bindVector(const UT_StringRef& name,
227  const UT_Vector4i &v,
228  int array_index = 0,
229  int* opt_idx = nullptr);
230 
231  /// Set a single 2x2 matrix value.
232  bool bindMatrix(const UT_StringRef& name,
233  const UT_Matrix2F &m,
234  int array_index = 0,
235  int* opt_idx = nullptr);
236  /// Set a single 3x3 matrix value.
237  bool bindMatrix(const UT_StringRef& name,
238  const UT_Matrix3F &m,
239  int array_index = 0,
240  int* opt_idx = nullptr);
241 
242  /// Set a single 4x4 matrix value.
243  bool bindMatrix(const UT_StringRef& name,
244  const UT_Matrix4F &m,
245  int array_index = 0,
246  int* opt_idx = nullptr);
247 
248  /// Set a single 2x2 matrix value (dmat2).
249  bool bindMatrix(const UT_StringRef& name,
250  const UT_Matrix2D &m,
251  int array_index = 0,
252  int* opt_idx = nullptr);
253 
254  /// Set a single 3x3 matrix value (dmat3).
255  bool bindMatrix(const UT_StringRef& name,
256  const UT_Matrix3D &m,
257  int array_index = 0,
258  int* opt_idx = nullptr);
259 
260  /// Set a single 4x4 matrix value (dmat4).
261  bool bindMatrix(const UT_StringRef& name,
262  const UT_Matrix4D &m,
263  int array_index = 0,
264  int* opt_idx = nullptr);
265 
266 protected:
267  virtual const RV_Uniform *getUniform(
268  const UT_StringRef& name,
269  int* opt_idx) = 0;
270 
271  // Debug Print functions
272  static void printMemberValue(
273  UT_WorkBuffer &out_msg,
274  const RV_Uniform& u,
275  int base_offset, int fixed_size, void *data,
276  RV_ShaderProgram *opt_shr = nullptr);
277  static void printMemberList(
278  const UT_Array<RV_Uniform>& u,
279  int indent, int base_offset, int array_length, int fixed_size,
280  void *data, RV_ShaderProgram *opt_shr = nullptr);
281 
282  // Virtual Interface for child classes
283 
284  /// Copy array of data into the CPU buffer
285  virtual void copyToBuffer(
286  const void *data,
287  int size, int offset,
288  const char* name)
289  = 0;
290 
291  /// Copy data into the CPU buffer with a specified stride.
292  /// incoming data is tightly packed, with padding added in
293  /// the buffer to match stride
294  virtual void copyToBufferStride(
295  const void *data,
296  int len,
297  int size,
298  int stride,
299  int offset,
300  const char* name)
301  = 0;
302 
303  // Protected ctor and dtor so base class can't be instantiated
304  // And static asserts so it MUST be inherited by BLOCK_T
305  RV_ShaderBindFuncs() = default;
306  virtual ~RV_ShaderBindFuncs();
307 };
308 
309 // Class Representing a Shader variable block, either UBO or SSBO
310 //
311 // Manages buffer and provides interface for querying, and setting
312 // uniforms. Requires DescriptorBinding description to initialize,
313 // but only manages buffer. Must be bound into Descriptor Set separately
314 //
316 {
317 public:
319 
320  /// Create the shader block (either a UBO or SSBO) for the binding in a set.
321  static RV_ShaderBlock* create(
322  RV_Instance* inst,
323  const RV_VKDescriptorBinding& binding_layout,
324  const char* name = nullptr,
325  uint32_t array_size = 0,
326  VkBufferUsageFlags additional_usage_flag = 0x00);
327 
328  /// Create the shader block (either a UBO or SSBO) for the binding in a set.
329  static RV_ShaderBlock* createCPUMapped(
330  RV_Instance* inst,
331  const RV_VKDescriptorBinding& binding_layout,
332  const char* name = nullptr,
333  uint32_t array_size = 0,
334  bool cpu_mapped = false,
335  VkBufferUsageFlags additional_usage_flag = 0x00);
336 
337  ~RV_ShaderBlock() override;
338 
339  /// Return the buffer object that backs this UBO or SSBO
340  RV_VKBuffer* getBufferObject() { return myBufferObject.get(); }
341 
342  /// Return the ptr to the CPU copy of buffer data, which must be downloaded
343  /// with downloadBuffer to see the most recent value
344  const void* getCPUBuffer() { return myData; }
345 
346  /// commits any changes to the buffer object, creating the buffer object
347  /// if required.
348  bool uploadBuffer(RV_Render* r);
349 
350  /// Fetches the contents of the GL buffer into the main mem block contained
351  /// by this class.
352  void downloadBuffer(RV_Render *r);
353 
354  /// returns the size of the buffer for UBO blocks and the
355  /// non-dynamically-sized part of the buffer for SSBOs
356  int getFixedSize() { return myFixedSize; }
357 
358  /// returns the size of the buffer for UBO blocks and the
359  /// dynamically-sized part of the buffer for SSBOs
360  exint getSize() const;
361 
362  // Whether this block requires uploading to the GPU.
363  bool isDirty() const { return myDirtyFlag; }
364 
365  /// compare whether this block is compatible with a shader's binding
366  bool isCompatible(const RV_VKDescriptorBinding& binding) const;
367 
368  /// get the binding location of the binding used to create this block
369  int getBindingNum() const { return myBindingNum; }
370 
371  /// Copy a bunch of bytes to the buffer. If size=0, it assumes the full
372  /// buffer size (or remaining size if ofset!=-0)
373  bool fillBuffer(const void *data, int offset=0, int size=0);
374 
375 
376  /// Array length of variably sized arrays for SSBOs.
377  int getArrayLength() const { return myArrayLength; }
378 
379  /// Offset in buffer of variably sized arrays for SSBOs.
380  int getArrayOffset() const { return myUniforms.last().offset; }
381 
382  /// Copy a bunch of bytes to the variable array component of the SSBO
383  bool uploadArray(RV_Render* r,
384  const void* data,
385  exint size,
386  exint offset = 0);
387 
388  /// Download bytes from the buffer variable array component of the SSBO
389  bool downloadArray(RV_Render* r,
390  void* data,
391  exint size,
392  exint offset = 0);
393 
394  /// Copy a bunch of bytes to the variable array component of the SSBO
395  /// where data can be any type used to construct a span
396  template<typename T>
398  const T &data,
399  exint offset = 0)
400  {
401  // `T` must be a `UT_Span` or convertable into a `UT_Span`
403  return uploadArray(r, span.data(), span.size_bytes(), offset);
404  }
405 
406  /// Download bytes from the buffer variable array component of the SSBO
407  /// where data can be any type used to construct a span
408  template<typename T>
410  T &data,
411  exint offset = 0)
412  {
413  // `T` must be a `UT_Span` or convertable into a `UT_Span`
415  return downloadArray(r, span.data(), span.size_bytes(), offset);
416  }
417 
418  // See `RV_ShaderBindFuncs` for bind functions
419 
420  // Debug Print functions
421  void print(RV_ShaderProgram *opt_shr = nullptr) const;
422 
423 private:
424  int getUniformIndex(const UT_StringRef& name);
425  const RV_Uniform* getUniform(const UT_StringRef& name, int* opt_idx) override;
426 
427  /// Copy array of data into the CPU buffer
428  void copyToBuffer(
429  const void *data,
430  int size,
431  int offset,
432  const char* name) override;
433 
434  /// Copy data into the CPU buffer with a specified stride.
435  /// incoming data is tightly packed, with padding added in
436  /// the buffer to match stride
437  void copyToBufferStride(
438  const void *data,
439  int len,
440  int size,
441  int stride,
442  int offset,
443  const char* name) override;
444 
446  RV_VKBufferPtr buffer_object,
447  void *buffer,
448  int size,
449  const char *instance_name,
450  int32 binding_num,
451  const UT_Array<RV_Uniform> &uniforms,
452  uint32_t array_length,
453  bool is_storage);
454 
455  /// Buffer Data
456  UT_UniquePtr<RV_VKBuffer> myBufferObject;
457  void *myData;
458  bool myDirtyFlag;
459  bool myIsStorage;
460 
461  // Uniform Reflection
462  UT_StringHolder myInstanceName;
463  int myBindingNum = -1;
464  UT_Array<RV_Uniform> myUniforms;
465 
466  UT_StringMap<int> myUniformsIndexMap;
467  UT_StringMap<int> myUniformsInstanceIndexMap;
468 
469  // Size of the fixed part of the buffer
470  int myFixedSize;
471 
472  // Size of the fully allocated buffer
473  int mySize;
474 
475  // for buffer storage objects, which can have a non-array section at the
476  // beginning of the block (fixed), followed by array data at the end
477  // (variable). myArrayLength determines the number of entries in the array.
478 
479  int myVariableSize;
480  int myArrayLength;
481 
482 
483  // =====================
484  // WIP: caching builtin uniforms offsets for faster upload
485 public:
486  bool bindUniform(int idx,
488  const void* data, exint data_size,
489  int array_index = 0);
490 
491  // Bring in interface version of `bindUniform` so it isn't hidden
493 
495  friend GR_Uniforms;
496 };
497 
498 /// Class Representing the Push Constants used by the pipeline
499 /// Will be owned by directly by the RV_Render, and gets holds
500 /// a ptr to the RV_Render owning it
501 ///
502 /// Does not have its own layout, instead uses the layout of the
503 /// shader bound to RV_Render at the time 'bind' is called
505 {
506 public:
508  ~RV_PushConstants() override;
509 
510  /// Write all bound values to the push constant memory
511  bool upload(RV_Render* r);
512 
513  /// Whether this block requires uploading to the GPU.
514  bool isDirty() const { return myDirtyFlag; }
515  /// Force the block to be re-uploaded to the GPU, even if not dirtied
516  void forceDirty() { myDirtyFlag = true; }
517 
518  /// Copy a bunch of bytes to the buffer. If size=0, it assumes the full
519  /// buffer size (or remaining size if ofset!=-0)
520  bool fillBuffer(const void *data, int offset=0, int size=0);
521 
522  void print(RV_ShaderProgramBase *sh) const;
523 
524 private:
525  const RV_Uniform* getUniform(const UT_StringRef& name, int* opt_idx)
526  override;
527 
528  /// Copy array of data into the CPU buffer
529  void copyToBuffer(
530  const void *data,
531  int size,
532  int offset,
533  const char* name) override;
534 
535  /// Copy data into the CPU buffer with a specified stride.
536  /// incoming data is tightly packed, with padding added in
537  /// the buffer to match stride
538  void copyToBufferStride(
539  const void *data,
540  int len,
541  int size,
542  int stride,
543  int offset,
544  const char* name) override;
545 
546  bool myDirtyFlag = true;
547  RV_Render* myR;
548  void* myData;
549  int mySize;
550 };
551 
552 #endif
void print(RV_ShaderProgramBase *sh) const
int int32
Definition: SYS_Types.h:39
VkFlags VkBufferUsageFlags
Definition: vulkan_core.h:2515
Helper tie-in class for binding functions for UBOs and SSBOs.
constexpr span< ElementType, Extent > make_span(span< ElementType, Extent > s) noexcept
Definition: UT_Span.h:559
bool isDirty() const
UT_UniquePtr< RV_VKBuffer > RV_VKBufferPtr
Definition: RV_TypePtrs.h:63
const GLdouble * v
Definition: glcorearb.h:837
~RV_PushConstants() override
void forceDirty()
Force the block to be re-uploaded to the GPU, even if not dirtied.
friend RV_ShaderBindFuncs
Definition: span.h:74
int64 exint
Definition: SYS_Types.h:125
const void * getCPUBuffer()
unsigned long long uint64
Definition: SYS_Types.h:117
float fpreal32
Definition: SYS_Types.h:200
GLuint buffer
Definition: glcorearb.h:660
RV_VKBuffer * getBufferObject()
Return the buffer object that backs this UBO or SSBO.
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
double fpreal64
Definition: SYS_Types.h:201
bool uploadArray(RV_Render *r, const T &data, exint offset=0)
int getArrayOffset() const
Offset in buffer of variably sized arrays for SSBOs.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
bool fillBuffer(const void *data, int offset=0, int size=0)
GLintptr offset
Definition: glcorearb.h:665
bool bindUniform(const UT_StringRef &name, RV_UniformType type, const void *data, exint data_size, int array_index=0, int array_range=1, int *opt_idx=nullptr)
Set the value of the uniform 'name' with a block of memory.
virtual void copyToBuffer(const void *data, int size, int offset, const char *name)=0
Copy array of data into the CPU buffer.
RV_UniformType
Definition: RV_Type.h:332
int getArrayLength() const
Array length of variably sized arrays for SSBOs.
RV_PushConstants(RV_Render *r)
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:872
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
#define RV_API
Definition: RV_API.h:10
virtual const RV_Uniform * getUniform(const UT_StringRef &name, int *opt_idx)=0
bool downloadArray(RV_Render *r, T &data, exint offset=0)
GLuint const GLchar * name
Definition: glcorearb.h:786
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:44
int getBindingNum() const
get the binding location of the binding used to create this block
GLsizeiptr size
Definition: glcorearb.h:664
virtual void copyToBufferStride(const void *data, int len, int size, int stride, int offset, const char *name)=0
constexpr size_type size_bytes() const noexcept
Definition: span.h:187
bool upload(RV_Render *r)
Write all bound values to the push constant memory.
GLboolean r
Definition: glcorearb.h:1222
set of parameters sent to GR_Primitive::update()
Definition: GR_Uniforms.h:56
A vulkan buffer object.
Definition: RV_VKBuffer.h:81
bool isDirty() const
Whether this block requires uploading to the GPU.
FMT_INLINE void print(format_string< T...> fmt, T &&...args)
Definition: core.h:2903
Type info for a single variable in a shader.
constexpr pointer data() const noexcept
Definition: span.h:190
UT_Array< int > myBuiltinArrayIdxToLocalIdx
Definition: format.h:1821