HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RV_ShaderProgram.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_ShaderProgram.h ( RV Library, C++)
8  *
9  * COMMENTS:
10  * Class to handle creating Shaders, a collection of
11  * Vulkan Pipeline Objects
12  */
13 
14 #ifndef RV_ShaderProgram_h
15 #define RV_ShaderProgram_h
16 
17 
18 #include <typeinfo>
19 
20 #include "RV_API.h"
21 
22 #include <utility>
23 
24 #include <UT/UT_Array.h>
25 #include <UT/UT_ArrayStringMap.h>
26 #include <UT/UT_Lock.h>
27 #include <UT/UT_StringArray.h>
28 #include <UT/UT_StringHolder.h>
29 #include <UT/UT_Tuple.h>
30 #include <UT/UT_UniquePtr.h>
31 
32 #include <VE/VE_VK.h>
33 #include "RV_ShaderVariableSet.h"
34 #include "RV_Type.h"
35 #include "RV_VKDescriptorSet.h"
36 #include "RV_VKPipeline.h"
37 #include "RV_VKPipelineLayout.h"
38 
39 class RV_Geometry;
40 class RV_Instance;
42 class RV_VKCommandBuffer;
43 class RV_VKShader;
44 class RV_VKShaderModule;
45 
46 // load definition of a UBO from a .blk file
47 extern RV_API RV_VKDescriptorBinding loadShaderBlock(RV_Instance *inst, const char *block);
48 
50 {
51 public:
53  RV_GPUType type, int vec_size)
54  : myName(name), myLocation(location)
55  , myType(type), myVecSize(vec_size)
56  {}
57 
61  int myVecSize;
62 };
63 
65 {
66 public:
68  : myDefaultAttributes(0)
69  {}
70 
71  // Bitfield of which attributes match the default definition
73 
74  // Full info for custom attribs
77 };
78 
79 // ~~~~~~~~~~~
80 // RV_ShaderProgramBase
81 //
82 /// class for shared functionality between different types of shaders:
83 /// mainly accessing the the pipeline layout. Other shader types
84 /// can build on extra functionality, e.g. input attributes for Graphics
86 {
87 public:
89  virtual ~RV_ShaderProgramBase();
90 
91  /// Set a descriptive name for the shader
92  void setName(const UT_StringHolder &name) { myName = name; }
93  /// Descriptive name of the shader
94  const UT_StringHolder &name() const { return myName; }
95 
96  /// Type of shader - graphics or compute
97  virtual RV_ShaderType getShaderType() const = 0;
98 
99  // ------------------------------------
100  // Sets
101 
102  /// The number of descriptor sets in the shader
103  int getMaxSetNumber() const
104  {
105  return myLayout->getInfo().myDescriptorSets.size() - 1;
106  }
107  /// Query if set 'set_num' is used by the shader
108  bool hasSet(int set_num) const
109  {
110  return set_num >= 0
111  && set_num < myLayout->getInfo().myDescriptorSets.size()
112  && myLayout->getInfo().myDescriptorSets[set_num].isValid();
113  }
114 
115  /// Return true if 'set' is compatable with the set layout in this shader.
116  bool isSetCompatible(const RV_ShaderVariableSet& set) const
117  {
118  int set_num = set.getSetNumber();
119  int other_id = set.getLayoutID();
120  UT_ASSERT(other_id != -1);
121  return mySetLayoutIds.isValidIndex(set_num) &&
122  other_id == mySetLayoutIds[set_num];
123  }
124 
125  /// Query information on set 'set_num'
126  const RV_VKDescriptorSetInfo* getSetInfo(int set_num) const
127  {
128  return hasSet(set_num)
129  ? &getLayout().getInfo().myDescriptorSets[set_num]
130  : nullptr;
131  }
132  /// Create a shader varaible set (descriptor set) for set 'set_num'
133  UT_UniquePtr<RV_ShaderVariableSet> createSet(RV_Instance* inst, int set_num)
134  const;
135 
136  // ------------------------------------
137  // Full Layout
138 
139  /// The layout of all sets and inputs of the shader
140  const RV_VKPipelineLayout& getLayout() const { return *myLayout; }
141 
142  // ------------------------------------
143  // Bindings
144 
145  /// Query if a binding named 'name' exists
146  bool hasBinding(const UT_StringRef& name) const;
147  /// Return a binding at index 'binding' for set index 'set'
148  const RV_VKDescriptorBinding* getBinding(int set, int binding) const;
149  /// Return a binding for 'name'
150  const RV_VKDescriptorBinding* getBinding(const UT_StringRef& name) const;
151  /// Return the list of set bindings
152  const UT_Array<const RV_VKDescriptorBinding*>& getBindingList() const;
153 
154  // ------------------------------------
155  // Uniforms
156 
157  /// Query if the uniform named 'name' exists
158  bool hasUniform(const UT_StringRef& name) const;
159  /// Return type, size, and offset information about the uniform
160  const RV_Uniform* getUniform(const UT_StringRef& name) const;
161  /// Return a list of all uniforms in this shader
162  const UT_Array<const RV_Uniform*>& getUniformList() const;
163 
164  // ------------------------------------
165  // Push Constants
166 
167  /// Query if push constant with 'name' exists
168  bool hasPushConstant(const UT_StringRef& name) const;
169  /// Fetch the push constant 'name' with an optional array index
170  const RV_Uniform* getPushConstant(const UT_StringRef& name, int* opt_idx) const;
171  const UT_Array<RV_VKPushConstantRange>& getPushConstantRanges() const;
172 
173  /// Debug print message
174  virtual void print() const {};
175 protected:
176  // ~~~~~~~~~~~~~
177  // Helper functions to load pipeline layouts
178 
179  // Create Shader from prog file, using pre-compiled spir-v if found
180  // or compiling if no spir-v found, and sources have been copied to hfs
181  // NOTE: providing extra defines forces compilation
182  static RV_VKPipelineLayoutPtr loadShaderProgram(
183  RV_Instance* inst,
184  const char* program,
185  const char* extra_defines = nullptr);
186 
187  // Create Shader using GLSL to SPIR-V compiler object
188  static RV_VKPipelineLayoutPtr createShaderProgram(
189  RV_Instance* inst,
191  const char* name = nullptr);
192 
193  // Create Shader using list of SPIR-V binary filenames
194  static RV_VKPipelineLayoutPtr createShaderProgram(
195  RV_Instance* inst,
196  const UT_StringArray& filenames,
197  const char* name = nullptr);
198 
199  // -------------------------------
200  // Attributes
201  // info shared between shader program, geometry, descriptor set, pipeline
203  // mapping of input name to place in table
205 
206  // -------------------------------
207  // Layout info:
208  // Pipeline Layout for shader
211 
212  // -------------------------------
213  // Uniforms
215  /// Mapping of uniform names, to indices in myUniforms
217 
218  // -------------------------------
219  // Bindings
221  /// mapping of binding name to set + binding number
223 
224  // -------------------------------
225  // Push Constants:
228 
230 
231  friend RV_Geometry;
233 };
234 
235 // ~~~~~~~~~~~
236 // RV_ShaderProgram
237 //
238 // Represents a single shader program that can be bound to the render state
239 // Holds pipeline layout and collection of cached pipeline objects
240 //
241 // Creates pipeline objects just before use, since actually pipeline construction
242 // requires knowledge of render state.
243 //
244 // Must be thread-safe (so the same pipeline can be used in multiple threads)
245 //
246 // Does not store active descriptorsets, but has helper functions to bind them,
247 // check them, and commit them to the render state
248 //
249 // Usually used with an RV_Geometry object to draw geometry
250 
251 // Shader works with lazy binding. Setting shader writes it to render state
252 // but no changes made to command buffer state until `commitBinding()` called
253 // -- usually called just before usage
254 
255 // Commit the shader to the Command Buffer. Must:
256 // - build final pipeline
257 // - commit descriptor set writes
258 // - bind shader
259 // - bind descriptor sets
260 //
261 
262 /// A single graphics shader program that can be bound to the render state
263 /// Holds pipeline layout and collection of cached pipeline objects
265 {
266 public:
267  /// Create Shader from prog file, using pre-compiled spir-v if found
268  /// or compiling if no spir-v found, and sources have been copied to hfs
269  /// NOTE: providing extra defines forces compilation
271  RV_Instance* inst,
272  const char* program,
273  const char* extra_defines = nullptr);
274 
275  /// Create Shader using GLSL to SPIR-V compiler object
277  RV_Instance* inst,
279  const char* name = nullptr);
280 
281  /// Create Shader using list of SPIR-V binary filenames
283  RV_Instance* inst,
284  const UT_StringArray& filenames,
285  const char* name = nullptr);
286 
287  // Create Shader using list of SPIR-V module filenames
289  RV_Instance* inst,
291  const char* name = nullptr);
292 
293  /// Type of the shader, Graphics or Compute
294  RV_ShaderType getShaderType() const override
295  {
296  return RV_SHADER_GRAPHICS;
297  };
298 
299  ~RV_ShaderProgram() override;
300 
301 
302  // TODO: rename: commitRenderState or compileState
303 
304  /// Finalize all set bindings in preparation for a draw
305  bool prepareForDraw(
306  RV_Instance* inst,
307  RV_VKCommandBuffer* cb,
308  const RV_VKPipelineStateInfo& pipe_state,
309  const RV_VKPipelineInputInfo& pipe_input);
310 
311  // ------------------------------------
312  // Attributes
313 
314  /// Query if a vertex shader input 'name' exists
315  bool hasAttribute(const UT_StringRef& name) const;
316  /// Query the information about a vertex shader input
317  bool getAttribute(const UT_StringRef& name,
318  int& out_location,
319  RV_GPUType& out_type,
320  int& out_vec_size) const;
321  /// The list of vertex shader inputs (attributes)
323  {
324  return myInputs;
325  }
326 
327  /// The list and state of vertex shader inputs (attributes)
329  {
330  return myInputState;
331  }
332 
333  /// Debug Print function; dump all shader variable sets and inputs/outputs
334  void print() const override;
335 
336 private:
338  RV_Instance* inst,
339  RV_VKPipelineLayoutPtr layout);
340 
342 
343  // Cache of pipeline objects already created for this shader
344  // and the pipeline state they were created for
345  // TODO: hash pipeline state for faster lookup
346  typedef UT_Tuple<
349  PipelineCreateInfo;
350 
351  UT_Array<std::pair<
352  PipelineCreateInfo,
354  myPipelineCache;
355  // Lock for accessing pipeline cache accross multiple threads
356  // TODO: add "immutable" pipeline-cache for lock-free accesss
357  UT_Lock myPipelineCacheLock;
358 
359  // -------------------------------
360  // Attributes
361  // info shared between shader program, geometry, descriptor set, pipeline
363  RV_ShaderInputState myInputState;
364  // mapping of input name to place in table
366 
367 
368  friend RV_Geometry;
369  friend RV_ShaderVariableSet;
370 };
371 
372 
373 // ~~~~~~~~~~~
374 // RV_ShaderCompute
375 //
376 /// Compute shader object
378 {
379 public:
380  // /Create Shader from prog file, using pre-compiled spir-v if found
381  /// or compiling if no spir-v found, and sources have been copied to hfs
382  /// NOTE: providing extra defines forces compilation
384  RV_Instance* inst,
385  const char* program,
386  const char* extra_defines = nullptr);
387 
388  /// Create Shader using GLSL to SPIR-V compiler object
390  RV_Instance* inst,
392 
393  /// Create Shader using list of SPIR-V binary filenames
395  RV_Instance* inst,
396  const UT_StringArray& filenames);
397 
398  /// Create Shader using list of SPIR-V module filenames
400  RV_Instance* inst,
402 
403  RV_ShaderType getShaderType() const override
404  {
405  return RV_SHADER_COMPUTE;
406  };
407 
408  bool prepareForDraw(
409  RV_Instance* inst,
410  RV_VKCommandBuffer* cb);
411 
412  // Debug Print function
413  void print() const override;
414 
415 protected:
417  RV_Instance* inst,
418  RV_VKPipelineLayoutPtr layout);
419 
421  RV_Instance* inst,
422  RV_VKPipelineLayoutPtr pipe_layout,
423  RV_VKPipelinePtr pipeline);
424 
426 };
427 
428 #endif
A collection of Vulkan UBO, SSBO, and Image shader bindings (descriptor set)
UT_Array< const RV_VKDescriptorBinding * > myBindings
int int32
Definition: SYS_Types.h:39
UT_Array< RV_ShaderInput > myInputs
RV_ShaderType getShaderType() const override
Type of the shader, Graphics or Compute.
UT_StringHolder myName
RV_GPUType myType
Object that represents drawable geometry. This object holds vertex, instancing and index buffers for ...
Definition: RV_Geometry.h:165
int getMaxSetNumber() const
The number of descriptor sets in the shader.
std::tuple< Types...> UT_Tuple
Definition: UT_Tuple.h:53
const RV_VKDescriptorSetInfo * getSetInfo(int set_num) const
Query information on set 'set_num'.
UT_ArrayStringMap< int > myInputTable
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
const UT_StringHolder & name() const
Descriptive name of the shader.
bool hasSet(int set_num) const
Query if set 'set_num' is used by the shader.
Compute shader object.
UT_ArrayStringMap< int > myInputTable
static RV_VKPipelineLayoutPtr loadShaderProgram(RV_Instance *inst, const char *program, const char *extra_defines=nullptr)
UT_Array< RV_ShaderInput > myCustomInputs
bool isSetCompatible(const RV_ShaderVariableSet &set) const
Return true if 'set' is compatable with the set layout in this shader.
RV_API RV_VKDescriptorBinding loadShaderBlock(RV_Instance *inst, const char *block)
UT_ArrayStringMap< int > myUniformTable
Mapping of uniform names, to indices in myUniforms.
#define RV_API
Definition: RV_API.h:10
UT_ArrayStringMap< std::pair< int, int > > myBindingTable
mapping of binding name to set + binding number
GLint location
Definition: glcorearb.h:805
static RV_VKPipelineLayoutPtr createShaderProgram(RV_Instance *inst, RV_VKShader &shader, const char *name=nullptr)
GLuint const GLchar * name
Definition: glcorearb.h:786
UT_UniquePtr< const RV_VKPipelineLayout > myLayout
virtual void print() const
Debug print message.
Handle to the main interface of Vulkan.
Definition: RV_Instance.h:38
const RV_ShaderInputState & getInputState() const
The list and state of vertex shader inputs (attributes)
RV_ShaderType
Definition: RV_Type.h:421
UT_StringHolder myName
int getSetNumber() const
Return the binding number of the set that this set was created with.
void setName(const UT_StringHolder &name)
Set a descriptive name for the shader.
UT_Array< const RV_Uniform * > myPushConstants
GLuint shader
Definition: glcorearb.h:785
RV_ShaderInput(const UT_StringHolder &name, int location, RV_GPUType type, int vec_size)
RV_GPUType
Definition: RV_Type.h:37
UT_UniquePtr< RV_VKPipelineLayout > RV_VKPipelineLayoutPtr
Definition: RV_TypePtrs.h:63
UT_ArrayStringMap< int > myPushConstTable
UT_UniquePtr< RV_VKPipeline > myPipeline
const RV_VKPipelineLayout & getLayout() const
The layout of all sets and inputs of the shader.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
UT_UniquePtr< RV_VKPipeline > RV_VKPipelinePtr
Definition: RV_TypePtrs.h:64
UT_Array< const RV_Uniform * > myUniforms
type
Definition: core.h:1059
Type info for a single variable in a shader.
int getLayoutID() const
Return the layout ID of the set that this set was created with.
UT_Array< exint > mySetLayoutIds
GLbitfield GLuint program
Definition: glcorearb.h:1931
const UT_Array< RV_ShaderInput > & getAttributeList() const
The list of vertex shader inputs (attributes)
RV_ShaderType getShaderType() const override
Type of shader - graphics or compute.