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_RWLock.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_Type.h"
34 #include "RV_VKDescriptorSet.h"
35 #include "RV_VKPipeline.h"
36 #include "RV_VKPipelineLayout.h"
37 
38 class RV_Render;
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  /// Get list of the descriptor set layout IDs in this shader, with -1
100  /// for indices that don't have a set
101  const UT_Array<exint> &layoutIds() const { return mySetLayoutIds; }
102 
103  // ------------------------------------
104  // Sets
105 
106  /// The number of descriptor sets in the shader
107  int getMaxSetNumber() const
108  {
109  return myLayout->getInfo().myDescriptorSets.size() - 1;
110  }
111  /// Query if set 'set_num' is used by the shader
112  bool hasSet(int set_num) const
113  {
114  return set_num >= 0
115  && set_num < myLayout->getInfo().myDescriptorSets.size()
116  && myLayout->getInfo().myDescriptorSets[set_num].isValid();
117  }
118 
119  /// Return true if 'set' is compatable with the set layout in this shader.
120  bool isSetCompatible(const RV_ShaderVariableSet& set) const;
121 
122  /// Query information on set 'set_num'
123  const RV_VKDescriptorSetInfo* getSetInfo(int set_num) const
124  {
125  return hasSet(set_num)
126  ? &getLayout().getInfo().myDescriptorSets[set_num]
127  : nullptr;
128  }
129  /// Create a shader varaible set (descriptor set) for set 'set_num'
130  UT_UniquePtr<RV_ShaderVariableSet> createSet(RV_Instance* inst, int set_num)
131  const;
132 
133  // ------------------------------------
134  // Full Layout
135 
136  /// The layout of all sets and inputs of the shader
137  const RV_VKPipelineLayout& getLayout() const { return *myLayout; }
138 
139  // ------------------------------------
140  // Bindings
141 
142  /// Query if a binding named 'name' exists
143  bool hasBinding(const UT_StringRef& name) const;
144  /// Return a binding at index 'binding' for set index 'set'
145  const RV_VKDescriptorBinding* getBinding(int set, int binding) const;
146  /// Return a binding for 'name'
147  const RV_VKDescriptorBinding* getBinding(const UT_StringRef& name) const;
148  /// Return the list of set bindings
149  const UT_Array<const RV_VKDescriptorBinding*>& getBindingList() const;
150 
151  // ------------------------------------
152  // Uniforms
153 
154  /// Query if the uniform named 'name' exists
155  bool hasUniform(const UT_StringRef& name) const;
156  /// Return type, size, and offset information about the uniform
157  const RV_Uniform* getUniform(const UT_StringRef& name) const;
158  /// Return a list of all uniforms in this shader
159  const UT_Array<const RV_Uniform*>& getUniformList() const;
160 
161  // ------------------------------------
162  // Push Constants
163 
164  /// Query if push constant with 'name' exists
165  bool hasPushConstant(const UT_StringRef& name) const;
166  /// Fetch the push constant 'name' with an optional array index
167  const RV_Uniform* getPushConstant(const UT_StringRef& name, int* opt_idx) const;
168  const UT_Array<RV_VKPushConstantRange>& getPushConstantRanges() const;
169 
170  /// Debug print message
171  virtual void print() const {};
172 protected:
173  // ~~~~~~~~~~~~~
174  // Helper functions to load pipeline layouts
175 
176  // Create Shader from prog file, using pre-compiled spir-v if found
177  // or compiling if no spir-v found, and sources have been copied to hfs
178  // NOTE: providing extra defines forces compilation
179  static RV_VKPipelineLayoutPtr loadShaderProgram(
180  RV_Instance* inst,
181  const char* program,
182  const char* extra_defines = nullptr);
183 
184  // -------------------------------
185  // Attributes
186  // info shared between shader program, geometry, descriptor set, pipeline
188  // mapping of input name to place in table
190 
191  // -------------------------------
192  // Layout info:
193  // Pipeline Layout for shader
196 
197  // -------------------------------
198  // Uniforms
200  /// Mapping of uniform names, to indices in myUniforms
202 
203  // -------------------------------
204  // Bindings
206  /// mapping of binding name to set + binding number
208 
209  // -------------------------------
210  // Push Constants:
213 
215 
216  friend RV_Geometry;
218 };
219 
220 // ~~~~~~~~~~~
221 // RV_ShaderProgram
222 //
223 // Represents a single shader program that can be bound to the render state
224 // Holds pipeline layout and collection of cached pipeline objects
225 //
226 // Creates pipeline objects just before use, since actually pipeline construction
227 // requires knowledge of render state.
228 //
229 // Must be thread-safe (so the same pipeline can be used in multiple threads)
230 //
231 // Does not store active descriptorsets, but has helper functions to bind them,
232 // check them, and commit them to the render state
233 //
234 // Usually used with an RV_Geometry object to draw geometry
235 
236 // Shader works with lazy binding. Setting shader writes it to render state
237 // but no changes made to command buffer state until `commitBinding()` called
238 // -- usually called just before usage
239 
240 // Commit the shader to the Command Buffer. Must:
241 // - build final pipeline
242 // - commit descriptor set writes
243 // - bind shader
244 // - bind descriptor sets
245 //
246 
247 /// A single graphics shader program that can be bound to the render state
248 /// Holds pipeline layout and collection of cached pipeline objects
250 {
251 public:
252  /// Create Shader from prog file, using pre-compiled spir-v if found
253  /// or compiling if no spir-v found, and sources have been copied to hfs
254  /// NOTE: providing extra defines forces compilation
256  RV_Instance* inst,
257  const char* program,
258  const char* extra_defines = nullptr);
259 
260  /// Create Shader using GLSL to SPIR-V compiler object
261  static RV_ShaderProgram* createShaderProgram(
262  RV_Instance* inst,
264  const char* name = nullptr);
265 
266  /// Create Shader using list of SPIR-V binary filenames
267  static RV_ShaderProgram* createShaderProgram(
268  RV_Instance* inst,
269  const UT_StringArray& filenames,
270  const char* name = nullptr);
271 
272  // Create Shader using list of SPIR-V modules
273  static RV_ShaderProgram* createShaderProgram(
274  RV_Instance* inst,
276  const char* name = nullptr);
277 
278  // Create shader program directly from pipeline layout object
279  static RV_ShaderProgram* createShaderProgram(
280  RV_Instance* inst,
281  RV_VKPipelineLayoutPtr layout);
282 
283  /// Type of the shader, Graphics or Compute
284  RV_ShaderType getShaderType() const override
285  {
286  return RV_SHADER_GRAPHICS;
287  };
288 
289  ~RV_ShaderProgram() override;
290 
291 
292  // TODO: rename: commitRenderState or compileState
293 
294  /// Finalize all set bindings in preparation for a draw
295  bool prepareForDraw(
296  RV_Render* r,
297  const RV_VKPipelineStateInfo& pipe_state,
298  const RV_VKPipelineInputInfo& pipe_input);
299 
300  // ------------------------------------
301  // Attributes
302 
303  /// Query if a vertex shader input 'name' exists
304  bool hasAttribute(const UT_StringRef& name) const;
305  /// Query the information about a vertex shader input
306  bool getAttribute(const UT_StringRef& name,
307  int& out_location,
308  RV_GPUType& out_type,
309  int& out_vec_size) const;
310  /// The list of vertex shader inputs (attributes)
312  {
313  return myInputs;
314  }
315 
316  /// The list and state of vertex shader inputs (attributes)
318  {
319  return myInputState;
320  }
321 
322  /// Debug Print function; dump all shader variable sets and inputs/outputs
323  void print() const override;
324 
325 private:
326 
328 
329  // Cache of pipeline objects already created for this shader
330  // and the pipeline state they were created for
331  // TODO: hash pipeline state for faster lookup
333  PipelineCreateInfo;
334 
336  PipelineCache;
337 
338  RV_VKPipeline* searchCache(
339  const PipelineCache &cache,
340  const RV_VKPipelineStateInfo& pipe_state,
341  const RV_VKPipelineInputInfo& pipe_input);
342 
343  RV_VKPipeline* addToCache(
344  PipelineCache &cache,
345  const RV_VKPipelineStateInfo& pipe_state,
346  const RV_VKPipelineInputInfo& pipe_input,
347  UT_UniquePtr<RV_VKPipeline> new_pipe);
348 
349  PipelineCache myMainPipelineCache;
350  PipelineCache myThreadedPipelineCache;
351 
352  // Lock for accessing pipeline cache accross multiple threads
353  UT_Lock myPipelineCacheLock;
354 
355  // -------------------------------
356  // Attributes
357  // info shared between shader program, geometry, descriptor set, pipeline
359  RV_ShaderInputState myInputState;
360  // mapping of input name to place in table
362 
363 
364  friend RV_Geometry;
365  friend RV_ShaderVariableSet;
366 };
367 
368 
369 // ~~~~~~~~~~~
370 // RV_ShaderCompute
371 //
372 /// Compute shader object
374 {
375 public:
376  // /Create Shader from prog file, using pre-compiled spir-v if found
377  /// or compiling if no spir-v found, and sources have been copied to hfs
378  /// NOTE: providing extra defines forces compilation
380  RV_Instance* inst,
381  const char* program,
382  const char* extra_defines = nullptr);
383 
384  /// Create Shader using GLSL to SPIR-V compiler object
385  static RV_ShaderCompute* createShaderProgram(
386  RV_Instance* inst,
388 
389  /// Create Shader using list of SPIR-V binary filenames
390  static RV_ShaderCompute* createShaderProgram(
391  RV_Instance* inst,
392  const UT_StringArray& filenames);
393 
394  /// Create Shader using list of SPIR-V modules
395  static RV_ShaderCompute* createShaderProgram(
396  RV_Instance* inst,
398 
399  // Create shader program directly from pipeline layout object
400  static RV_ShaderCompute* createShaderProgram(
401  RV_Instance* inst,
402  RV_VKPipelineLayoutPtr layout);
403 
404  RV_ShaderType getShaderType() const override
405  { return RV_SHADER_COMPUTE; };
406 
407  ~RV_ShaderCompute() override;
408 
410  { return myLayout->getInfo().myWorkGroupSize; }
411 
413  { return myLayout->getInfo().myWorkGroupIsSpecConst; }
414 
415  bool prepareForDraw(
416  RV_Instance* inst,
417  RV_VKCommandBuffer* cb);
418 
419  // Debug Print function
420  void print() const override;
421 
422 protected:
423 
425  RV_Instance* inst,
426  RV_VKPipelineLayoutPtr pipe_layout,
427  RV_VKPipelinePtr pipeline);
428 
430 };
431 
432 #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
bool hasWorkGroupSpecializationConst() const
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'.
const UT_Vector3i & getWorkGroupSize() const
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.
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)
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:44
const RV_ShaderInputState & getInputState() const
The list and state of vertex shader inputs (attributes)
RV_ShaderType
Definition: RV_Type.h:484
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
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.