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 #include <typeinfo>
18 
19 #include "RV_API.h"
20 
21 #include <utility>
22 
23 #include <UT/UT_Array.h>
24 #include <UT/UT_ArrayStringMap.h>
25 #include <UT/UT_Lock.h>
26 #include <UT/UT_StringArray.h>
27 #include <UT/UT_StringHolder.h>
28 #include <UT/UT_Tuple.h>
29 #include <UT/UT_UniquePtr.h>
30 
31 #include <VE/VE_VK.h>
32 #include "RV_Type.h"
33 #include "RV_VKPipeline.h"
34 
35 class RV_Render;
36 class RV_Geometry;
37 class RV_Instance;
39 class RV_VKCommandBuffer;
40 class RV_VKShader;
41 class RV_VKShaderModule;
42 
43 class RV_VKAttributeInfo;
48 
49 class RV_Uniform;
50 class RV_VKDescriptorSet;
55 
56 // load definition of a UBO from a .blk file
58  RV_Instance* inst,
59  const char* block,
60  int set = 0,
61  int binding_num = 0);
62 
63 // Convenience function for loading definitions of shader blocks
64 // compile a shader with the src code in `code`, and returns the descriptor
65 // binding at set 0, binding num 0
67  RV_Instance* inst,
68  const char* code,
69  const char* name,
70  int set = 0,
71  int binding_num = 0);
72 
74 {
75 public:
77  RV_GPUType type, int vec_size)
78  : myName(name), myLocation(location)
79  , myType(type), myVecSize(vec_size)
80  {}
81 
85  int myVecSize;
86 };
87 
89 {
90 public:
92  : myDefaultAttributes(0)
93  {}
94 
95  // Bitfield of which attributes match the default definition
97 
98  // Full info for custom attribs
101 };
102 
103 // ~~~~~~~~~~~
104 // RV_ShaderProgramBase
105 //
106 /// class for shared functionality between different types of shaders:
107 /// mainly accessing the the pipeline layout. Other shader types
108 /// can build on extra functionality, e.g. input attributes for Graphics
110 {
111 public:
113  virtual ~RV_ShaderProgramBase();
114 
115  /// Set a descriptive name for the shader
116  void setName(const UT_StringHolder &name) { myName = name; }
117  /// Descriptive name of the shader
118  const UT_StringHolder &name() const { return myName; }
119 
120  /// Type of shader - graphics or compute
121  virtual RV_ShaderType getShaderType() const = 0;
122 
123  /// Get list of the descriptor set layout IDs in this shader, with -1
124  /// for indices that don't have a set
125  const UT_Array<exint> &layoutIds() const { return mySetLayoutIds; }
126 
127  // ------------------------------------
128  // Sets
129 
130  /// The number of descriptor sets in the shader
131  int getMaxSetNumber() const;
132 
133  /// Query if set 'set_num' is used by the shader
134  bool hasSet(int set_num) const;
135 
136  /// Return true if 'set' is compatable with the set layout in this shader.
137  bool isSetCompatible(const RV_ShaderVariableSet& set) const;
138 
139  /// Query information on set 'set_num'
140  const RV_VKDescriptorSetInfo* getSetInfo(int set_num) const;
141 
142  /// Create a shader variable set (descriptor set) for set 'set_num'
143  UT_UniquePtr<RV_ShaderVariableSet> createSet(RV_Instance* inst, int set_num)
144  const;
145 
146  // ------------------------------------
147  // Full Layout
148 
149  /// The layout of all sets and inputs of the shader
150  const RV_VKPipelineLayout& getLayout() const { return *myLayout; }
151 
152  // ------------------------------------
153  // Bindings
154 
155  /// Query if a binding named 'name' exists
156  bool hasBinding(const UT_StringRef& name) const;
157  /// Return a binding at index 'binding' for set index 'set'
158  const RV_VKDescriptorBinding* getBinding(int set, int binding) const;
159  /// Return a binding for 'name'
160  const RV_VKDescriptorBinding* getBinding(const UT_StringRef& name) const;
161  /// Return the list of set bindings
162  const UT_Array<const RV_VKDescriptorBinding*>& getBindingList() const;
163 
164  // ------------------------------------
165  // Uniforms
166 
167  /// Query if the uniform named 'name' exists
168  bool hasUniform(const UT_StringRef& name) const;
169  /// Return type, size, and offset information about the uniform
170  const RV_Uniform* getUniform(const UT_StringRef& name) const;
171  /// Return a list of all uniforms in this shader
172  const UT_Array<const RV_Uniform*>& getUniformList() const;
173 
174  // ------------------------------------
175  // Push Constants
176 
177  /// Query if push constant with 'name' exists
178  bool hasPushConstant(const UT_StringRef& name) const;
179  /// Fetch the push constant 'name' with an optional array index
180  const RV_Uniform* getPushConstant(const UT_StringRef& name, int* opt_idx) const;
181  const UT_Array<RV_VKPushConstantRange>& getPushConstantRanges() const;
182 
183  /// Debug print message
184  virtual void print() const {};
185 protected:
186  // ~~~~~~~~~~~~~
187  // Helper functions to load pipeline layouts
188 
189  // Create Shader from prog file, using pre-compiled spir-v if found
190  // or compiling if no spir-v found, and sources have been copied to hfs
191  // NOTE: providing extra defines forces compilation
192  static RV_VKPipelineLayoutPtr loadShaderProgram(
193  RV_Instance* inst,
194  const char* program,
195  const char* extra_defines = nullptr);
196 
197  // -------------------------------
198  // Attributes
199  // info shared between shader program, geometry, descriptor set, pipeline
201  // mapping of input name to place in table
203 
204  // -------------------------------
205  // Layout info:
206  // Pipeline Layout for shader
209 
210  // -------------------------------
211  // Uniforms
213  /// Mapping of uniform names, to indices in myUniforms
215 
216  // -------------------------------
217  // Bindings
219  /// mapping of binding name to set + binding number
221 
222  // -------------------------------
223  // Push Constants:
226 
228 
229  friend RV_Geometry;
231 };
232 
233 // ~~~~~~~~~~~
234 // RV_ShaderProgram
235 //
236 // Represents a single shader program that can be bound to the render state
237 // Holds pipeline layout and collection of cached pipeline objects
238 //
239 // Creates pipeline objects just before use, since actually pipeline construction
240 // requires knowledge of render state.
241 //
242 // Must be thread-safe (so the same pipeline can be used in multiple threads)
243 //
244 // Does not store active descriptorsets, but has helper functions to bind them,
245 // check them, and commit them to the render state
246 //
247 // Usually used with an RV_Geometry object to draw geometry
248 
249 // Shader works with lazy binding. Setting shader writes it to render state
250 // but no changes made to command buffer state until `commitBinding()` called
251 // -- usually called just before usage
252 
253 // Commit the shader to the Command Buffer. Must:
254 // - build final pipeline
255 // - commit descriptor set writes
256 // - bind shader
257 // - bind descriptor sets
258 //
259 
260 /// A single graphics shader program that can be bound to the render state
261 /// Holds pipeline layout and collection of cached pipeline objects
263 {
264 public:
265  /// Create Shader from prog file, using pre-compiled spir-v if found
266  /// or compiling if no spir-v found, and sources have been copied to hfs
267  /// NOTE: providing extra defines forces compilation
269  RV_Instance* inst,
270  const char* program,
271  const char* extra_defines = nullptr);
272 
273  /// Create Shader using GLSL to SPIR-V compiler object
274  static RV_ShaderProgram* createShaderProgram(
275  RV_Instance* inst,
277  const char* name = nullptr);
278 
279  /// Create Shader using list of SPIR-V binary filenames
280  static RV_ShaderProgram* createShaderProgram(
281  RV_Instance* inst,
282  const UT_StringArray& filenames,
283  const char* name = nullptr);
284 
285  // Create Shader using list of SPIR-V modules
286  static RV_ShaderProgram* createShaderProgram(
287  RV_Instance* inst,
289  const char* name = nullptr);
290 
291  // Create shader program directly from pipeline layout object
292  static RV_ShaderProgram* createShaderProgram(
293  RV_Instance* inst,
294  RV_VKPipelineLayoutPtr layout);
295 
296  /// Type of the shader, Graphics or Compute
297  RV_ShaderType getShaderType() const override
298  {
299  return RV_SHADER_GRAPHICS;
300  };
301 
302  ~RV_ShaderProgram() override;
303 
304 
305  // TODO: rename: commitRenderState or compileState
306 
307  /// Finalize all set bindings in preparation for a draw
308  bool prepareForDraw(
309  RV_Render* r,
310  const RV_VKPipelineStateInfo& pipe_state,
311  const RV_VKPipelineInputInfo& pipe_input);
312 
313  // ------------------------------------
314  // Attributes
315 
316  /// Query if a vertex shader input 'name' exists
317  bool hasAttribute(const UT_StringRef& name) const;
318  /// Query the information about a vertex shader input
319  bool getAttribute(const UT_StringRef& name,
320  int& out_location,
321  RV_GPUType& out_type,
322  int& out_vec_size) const;
323  /// The list of vertex shader inputs (attributes)
325  {
326  return myInputs;
327  }
328 
329  /// The list and state of vertex shader inputs (attributes)
331  {
332  return myInputState;
333  }
334 
335  /// Debug Print function; dump all shader variable sets and inputs/outputs
336  void print() const override;
337 
338 private:
339 
341 
342  // Cache of pipeline objects already created for this shader
343  // and the pipeline state they were created for
344  // TODO: hash pipeline state for faster lookup
346  PipelineCreateInfo;
347 
349  PipelineCache;
350 
351  RV_VKPipeline* searchCache(
352  const PipelineCache &cache,
353  const RV_VKPipelineStateInfo& pipe_state,
354  const RV_VKPipelineInputInfo& pipe_input);
355 
356  RV_VKPipeline* addToCache(
357  PipelineCache &cache,
358  const RV_VKPipelineStateInfo& pipe_state,
359  const RV_VKPipelineInputInfo& pipe_input,
360  UT_UniquePtr<RV_VKPipeline> new_pipe);
361 
362  PipelineCache myMainPipelineCache;
363  PipelineCache myThreadedPipelineCache;
364 
365  // Lock for accessing pipeline cache accross multiple threads
366  UT_Lock myPipelineCacheLock;
367 
368  // -------------------------------
369  // Attributes
370  // info shared between shader program, geometry, descriptor set, pipeline
372  RV_ShaderInputState myInputState;
373  // mapping of input name to place in table
375 
376 
377  friend RV_Geometry;
378  friend RV_ShaderVariableSet;
379 };
380 
381 
382 // ~~~~~~~~~~~
383 // RV_ShaderCompute
384 //
385 /// Compute shader object
387 {
388 public:
389  // /Create Shader from prog file, using pre-compiled spir-v if found
390  /// or compiling if no spir-v found, and sources have been copied to hfs
391  /// NOTE: providing extra defines forces compilation
393  RV_Instance* inst,
394  const char* program,
395  const char* extra_defines = nullptr);
396 
397  /// Create Shader using GLSL to SPIR-V compiler object
398  static RV_ShaderCompute* createShaderProgram(
399  RV_Instance* inst,
401 
402  /// Create Shader using list of SPIR-V binary filenames
403  static RV_ShaderCompute* createShaderProgram(
404  RV_Instance* inst,
405  const UT_StringArray& filenames);
406 
407  /// Create Shader using list of SPIR-V modules
408  static RV_ShaderCompute* createShaderProgram(
409  RV_Instance* inst,
411 
412  // Create shader program directly from pipeline layout object
413  static RV_ShaderCompute* createShaderProgram(
414  RV_Instance* inst,
415  RV_VKPipelineLayoutPtr layout);
416 
417  RV_ShaderType getShaderType() const override
418  { return RV_SHADER_COMPUTE; };
419 
420  ~RV_ShaderCompute() override;
421 
422  const UT_Vector3i &getWorkGroupSize() const;
423 
424  bool hasWorkGroupSpecializationConst() const;
425 
426  bool prepareForDraw(
427  RV_Instance* inst,
428  RV_VKCommandBuffer* cb);
429 
430  // Debug Print function
431  void print() const override;
432 
433 protected:
434 
436  RV_Instance* inst,
437  RV_VKPipelineLayoutPtr pipe_layout,
438  RV_VKPipelinePtr pipeline);
439 
441 };
442 
443 #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
std::tuple< Types...> UT_Tuple
Definition: UT_Tuple.h:53
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.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
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
constexpr auto set(type rhs) -> int
Definition: core.h:610
RAII wrapper class for VkPipeline.
const UT_Array< exint > & layoutIds() const
RV_API RV_VKDescriptorBinding loadShaderBlock(RV_Instance *inst, const char *block, int set=0, int binding_num=0)
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
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:48
const RV_ShaderInputState & getInputState() const
The list and state of vertex shader inputs (attributes)
RV_ShaderType
Definition: RV_Type.h:418
UT_StringHolder myName
RAII wrapper class for Vk Shader Module.
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
UT_SmallArray< exint, 8 *sizeof(exint)> mySetLayoutIds
RV_ShaderInput(const UT_StringHolder &name, int location, RV_GPUType type, int vec_size)
RV_GPUType
Definition: RV_Type.h:40
UT_UniquePtr< RV_VKPipelineLayout > RV_VKPipelineLayoutPtr
Definition: RV_TypePtrs.h:72
UT_ArrayStringMap< int > myPushConstTable
UT_UniquePtr< RV_VKPipeline > myPipeline
const RV_VKPipelineLayout & getLayout() const
The layout of all sets and inputs of the shader.
UT_UniquePtr< RV_VKPipeline > RV_VKPipelinePtr
Definition: RV_TypePtrs.h:73
UT_Array< const RV_Uniform * > myUniforms
GLboolean r
Definition: glcorearb.h:1222
Type info for a single variable in a shader.
GLbitfield GLuint program
Definition: glcorearb.h:1931
RV_API RV_VKDescriptorBinding loadShaderSnippet(RV_Instance *inst, const char *code, const char *name, int set=0, int binding_num=0)
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.