HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShaderStage.h
Go to the documentation of this file.
1 //
2 // Copyright Contributors to the MaterialX Project
3 // SPDX-License-Identifier: Apache-2.0
4 //
5 
6 #ifndef MATERIALX_SHADERSTAGE_H
7 #define MATERIALX_SHADERSTAGE_H
8 
9 /// @file
10 /// Class related to holding information for shader stages
11 
13 
17 
18 #include <MaterialXFormat/File.h>
19 
20 #include <MaterialXCore/Node.h>
21 
22 #include <sstream>
23 
24 // Restrict a scoped block of statements to a specific shader stage, as
25 // is required for multi-stage shading languages. Statements within
26 // the block will only be emitted when processing the given stage.
27 #define DEFINE_SHADER_STAGE(stage, name) if (stage.getName() == name)
28 
29 // These macros are deprecated, and should be replaced with DEFINE_SHADER_STAGE.
30 #define BEGIN_SHADER_STAGE(stage, name) \
31  if (stage.getName() == name) \
32  {
33 #define END_SHADER_STAGE(stage, name) }
34 
36 
37 namespace Stage
38 {
39 
40 /// Identifier for pixel stage.
41 /// This is the main stage used by all shader targets.
42 /// For single stage shader targets this is the one
43 /// and only stage.
44 /// Shader targets with multiple stages can add additional
45 /// stage identifiers to the Stage namespace.
46 extern MX_GENSHADER_API const string PIXEL;
47 
48 } // namespace Stage
49 
50 class VariableBlock;
51 /// Shared pointer to a VariableBlock
52 using VariableBlockPtr = std::shared_ptr<VariableBlock>;
53 /// Shared pointer to a map between string identifiers and VariableBlocks
54 using VariableBlockMap = std::unordered_map<string, VariableBlockPtr>;
55 /// A standard function predicate taking an ShaderPort pointer and returning a boolean.
56 using ShaderPortPredicate = std::function<bool(ShaderPort*)>;
57 
58 /// @class VariableBlock
59 /// A block of variables in a shader stage
61 {
62  public:
63  VariableBlock(const string& name, const string& instance) :
64  _name(name),
65  _instance(instance)
66  {
67  }
68 
69  /// Get the name of this block.
70  const string& getName() const { return _name; }
71 
72  /// Set the name of this block.
73  void setName(const string& name) { _name = name; }
74 
75  /// Get the instance name of this block.
76  const string& getInstance() const { return _instance; }
77 
78  /// Set the instance name of this block.
79  void setInstance(const string& instance) { _instance = instance; }
80 
81  /// Return true if the block has no variables.
82  bool empty() const { return _variableOrder.empty(); }
83 
84  /// Return the number of variables in this block.
85  size_t size() const { return _variableOrder.size(); }
86 
87  /// Return a variable by index.
88  ShaderPort* operator[](size_t index) { return _variableOrder[index]; }
89 
90  /// Return a variable by index.
91  const ShaderPort* operator[](size_t index) const { return _variableOrder[index]; }
92 
93  /// Return a const reference to our variable order vector.
94  const vector<ShaderPort*>& getVariableOrder() const { return _variableOrder; }
95 
96  /// Return a variable by name. Throws exception if
97  /// no variable is found by the given name.
98  ShaderPort* operator[](const string& name);
99 
100  /// Return a variable by name. Throws exception if
101  /// no variable is found by the given name.
102  const ShaderPort* operator[](const string& name) const;
103 
104  /// Return a variable by name. Returns nullptr if
105  /// no variable is found by the given name.
106  ShaderPort* find(const string& name);
107 
108  /// Return a variable by name. Returns nullptr if
109  /// no variable is found by the given name.
110  const ShaderPort* find(const string& name) const;
111 
112  /// Find a port based on a predicate
113  ShaderPort* find(const ShaderPortPredicate& predicate);
114 
115  /// Add a new shader port to this block.
116  /// @param type The desired shader port type
117  /// @param name The shader port name
118  /// @param value The value to attach to the shader port
119  /// @param shouldWiden When false, an exception is thrown if the type of the existing port with
120  /// the same name does not match the requested type. When true, the types can mismatch, and the
121  /// type of any existing port is widened to match the requested type when necessary.
122  /// @return A new shader port, or a pre-existing shader port with the same name.
123  ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr, bool shouldWiden = false);
124 
125  /// Add an existing shader port to this block.
126  void add(ShaderPortPtr port);
127 
128  private:
129  string _name;
130  string _instance;
131  std::unordered_map<string, ShaderPortPtr> _variableMap;
132  vector<ShaderPort*> _variableOrder;
133 };
134 
135 /// @class ShaderStage
136 /// A shader stage, containing the state and
137 /// resulting source code for the stage.
139 {
140  public:
141  using FunctionCallId = std::pair<const ShaderNode*, int>;
142  struct Scope
143  {
145  std::set<FunctionCallId> functions;
147  punctuation(p) { }
148  };
149 
150  public:
151  /// Contructor.
152  ShaderStage(const string& name, ConstSyntaxPtr syntax);
153 
154  /// Return the stage name.
155  const string& getName() const { return _name; }
156 
157  /// Return the stage function name.
158  const string& getFunctionName() const { return _functionName; }
159 
160  /// Set the stage source code.
161  void setSourceCode(const string& code) { _code = code; }
162 
163  /// Return the stage source code.
164  const string& getSourceCode() const { return _code; }
165 
166  /// Create a new uniform variable block.
167  VariableBlockPtr createUniformBlock(const string& name, const string& instance = EMPTY_STRING);
168 
169  /// Create a new input variable block.
170  VariableBlockPtr createInputBlock(const string& name, const string& instance = EMPTY_STRING);
171 
172  /// Create a new output variable block.
173  VariableBlockPtr createOutputBlock(const string& name, const string& instance = EMPTY_STRING);
174 
175  /// Return the uniform variable block with given name.
176  VariableBlock& getUniformBlock(const string& name);
177 
178  /// Return the uniform variable block with given name.
179  const VariableBlock& getUniformBlock(const string& name) const;
180 
181  /// Return the input variable block with given name.
182  VariableBlock& getInputBlock(const string& name);
183 
184  /// Return the input variable block with given name.
185  const VariableBlock& getInputBlock(const string& name) const;
186 
187  /// Return the output variable block with given name.
188  VariableBlock& getOutputBlock(const string& name);
189 
190  /// Return the output variable block with given name.
191  const VariableBlock& getOutputBlock(const string& name) const;
192 
193  /// Return the constant variable block.
194  VariableBlock& getConstantBlock();
195 
196  /// Return the constant variable block.
197  const VariableBlock& getConstantBlock() const;
198 
199  /// Return a map of all uniform blocks.
201  {
202  return _uniforms;
203  }
204 
205  /// Return a map of all input blocks.
207  {
208  return _inputs;
209  }
210 
211  /// Return a map of all output blocks.
213  {
214  return _outputs;
215  }
216 
217  /// Return a set of all include files
218  const StringSet& getIncludes() const
219  {
220  return _includes;
221  }
222 
223  /// Return a set of all source dependencies
225  {
226  return _sourceDependencies;
227  }
228 
229  /// Start a new scope using the given bracket type.
230  void beginScope(Syntax::Punctuation punc = Syntax::CURLY_BRACKETS);
231 
232  /// End the current scope.
233  void endScope(bool semicolon = false, bool newline = true);
234 
235  /// Start a new line.
236  void beginLine();
237 
238  /// End the current line.
239  void endLine(bool semicolon = true);
240 
241  /// Add a newline character.
242  void newLine();
243 
244  /// Add a string.
245  void addString(const string& str);
246 
247  /// Add a single line of code, optionally appending a semicolon.
248  void addLine(const string& str, bool semicolon = true);
249 
250  /// Add a single line code comment.
251  void addComment(const string& str);
252 
253  /// Add a block of code.
254  void addBlock(const string& str, const FilePath& sourceFilename, GenContext& context);
255 
256  /// Add the contents of an include file if not already present.
257  void addInclude(const FilePath& includeFilename, const FilePath& sourceFilename, GenContext& context);
258 
259  /// Add a source file dependency for dependency tracking purposes
260  void addSourceDependency(const FilePath& file);
261 
262  /// Add a value.
263  template <typename T>
264  void addValue(const T& value)
265  {
266  StringStream str;
267  str << value;
268  _code += str.str();
269  }
270 
271  /// Add the function definition for a node's implementation.
272  void addFunctionDefinition(const ShaderNode& node, GenContext& context);
273 
274  /// Add the function call for the given node.
275  /// This will register the function as being called in the current scope, and code for the
276  /// function call will be added to the stage. If emitCode is set to false the code for the
277  /// function call will be omitted.
278  void addFunctionCall(const ShaderNode& node, GenContext& context, bool emitCode = true);
279 
280  /// Return true if the function for the given node has been emitted in the current scope.
281  bool isEmitted(const ShaderNode& node, GenContext& context) const;
282 
283  /// Set stage function name.
284  void setFunctionName(const string& functionName)
285  {
286  _functionName = functionName;
287  }
288 
289  private:
290  /// Name of the stage
291  const string _name;
292 
293  /// Name of the stage main function
294  string _functionName;
295 
296  /// Syntax for the type of shader to generate.
297  ConstSyntaxPtr _syntax;
298 
299  /// Current indentation level.
300  int _indentations;
301 
302  /// Current scope.
303  vector<Scope> _scopes;
304 
305  /// Set of include files that has been included.
306  StringSet _includes;
307 
308  /// Set of source file dependencies from source code nodes
309  StringSet _sourceDependencies;
310 
311  /// Set of hash ID's for functions that has been defined.
312  std::set<size_t> _definedFunctions;
313 
314  /// Block holding constant variables for this stage.
315  VariableBlock _constants;
316 
317  /// Map of blocks holding uniform variables for this stage.
318  VariableBlockMap _uniforms;
319 
320  /// Map of blocks holding input variables for this stage.
321  VariableBlockMap _inputs;
322 
323  /// Map of blocks holding output variables for this stage.
324  VariableBlockMap _outputs;
325 
326  /// Resulting source code for this stage.
327  string _code;
328 
329  friend class ShaderGenerator;
330 };
331 
332 /// Shared pointer to a ShaderStage
333 using ShaderStagePtr = std::shared_ptr<ShaderStage>;
334 
335 /// Utility function for adding a new shader port to a uniform block.
336 inline ShaderPort* addStageUniform(const string& block,
337  const TypeDesc* type,
338  const string& name,
339  ShaderStage& stage)
340 {
341  VariableBlock& uniforms = stage.getUniformBlock(block);
342  return uniforms.add(type, name);
343 }
344 
345 /// Utility function for adding a new shader port to an input block.
346 inline ShaderPort* addStageInput(const string& block,
347  const TypeDesc* type,
348  const string& name,
349  ShaderStage& stage,
350  bool shouldWiden = false)
351 {
352  VariableBlock& inputs = stage.getInputBlock(block);
353  return inputs.add(type, name, {}, shouldWiden);
354 }
355 
356 /// Utility function for adding a new shader port to an output block.
357 inline ShaderPort* addStageOutput(const string& block,
358  const TypeDesc* type,
359  const string& name,
360  ShaderStage& stage,
361  bool shouldWiden = false)
362 {
363  VariableBlock& outputs = stage.getOutputBlock(block);
364  return outputs.add(type, name, {}, shouldWiden);
365 }
366 
367 /// Utility function for adding a connector block between stages.
368 inline void addStageConnectorBlock(const string& block,
369  const string& instance,
370  ShaderStage& from,
371  ShaderStage& to)
372 {
373  from.createOutputBlock(block, instance);
374  to.createInputBlock(block, instance);
375 }
376 
377 /// Utility function for adding a variable to a stage connector block.
378 inline void addStageConnector(const string& block,
379  const TypeDesc* type,
380  const string& name,
381  ShaderStage& from,
382  ShaderStage& to,
383  bool shouldWiden = false)
384 {
385  addStageOutput(block, type, name, from, shouldWiden);
386  addStageInput(block, type, name, to, shouldWiden);
387 }
388 
390 
391 #endif
void addStageConnectorBlock(const string &block, const string &instance, ShaderStage &from, ShaderStage &to)
Utility function for adding a connector block between stages.
Definition: ShaderStage.h:368
ShaderPort * addStageInput(const string &block, const TypeDesc *type, const string &name, ShaderStage &stage, bool shouldWiden=false)
Utility function for adding a new shader port to an input block.
Definition: ShaderStage.h:346
Definition: File.h:26
void addValue(const T &value)
Add a value.
Definition: ShaderStage.h:264
#define MATERIALX_NAMESPACE_BEGIN
Definition: Generated.h:25
GLsizei const GLfloat * value
Definition: glcorearb.h:824
bool empty() const
Return true if the block has no variables.
Definition: ShaderStage.h:82
ShaderPort * addStageUniform(const string &block, const TypeDesc *type, const string &name, ShaderStage &stage)
Utility function for adding a new shader port to a uniform block.
Definition: ShaderStage.h:336
MATERIALX_NAMESPACE_BEGIN MX_CORE_API const string EMPTY_STRING
VariableBlockPtr createOutputBlock(const string &name, const string &instance=EMPTY_STRING)
Create a new output variable block.
shared_ptr< const Syntax > ConstSyntaxPtr
Shared pointer to a constant Syntax.
Definition: Syntax.h:28
const VariableBlockMap & getOutputBlocks() const
Return a map of all output blocks.
Definition: ShaderStage.h:212
#define MX_GENSHADER_API
Definition: Export.h:18
const VariableBlockMap & getInputBlocks() const
Return a map of all input blocks.
Definition: ShaderStage.h:206
const string & getName() const
Return the stage name.
Definition: ShaderStage.h:155
void setSourceCode(const string &code)
Set the stage source code.
Definition: ShaderStage.h:161
std::shared_ptr< VariableBlock > VariableBlockPtr
Shared pointer to a VariableBlock.
Definition: ShaderStage.h:52
ShaderPort * addStageOutput(const string &block, const TypeDesc *type, const string &name, ShaderStage &stage, bool shouldWiden=false)
Utility function for adding a new shader port to an output block.
Definition: ShaderStage.h:357
const string & getName() const
Get the name of this block.
Definition: ShaderStage.h:70
std::function< bool(ShaderPort *)> ShaderPortPredicate
A standard function predicate taking an ShaderPort pointer and returning a boolean.
Definition: ShaderStage.h:56
Scope(Syntax::Punctuation p)
Definition: ShaderStage.h:146
std::unordered_map< string, VariableBlockPtr > VariableBlockMap
Shared pointer to a map between string identifiers and VariableBlocks.
Definition: ShaderStage.h:54
VariableBlock & getInputBlock(const string &name)
Return the input variable block with given name.
void addStageConnector(const string &block, const TypeDesc *type, const string &name, ShaderStage &from, ShaderStage &to, bool shouldWiden=false)
Utility function for adding a variable to a stage connector block.
Definition: ShaderStage.h:378
ShaderPort * add(const TypeDesc *type, const string &name, ValuePtr value=nullptr, bool shouldWiden=false)
ShaderPort * operator[](size_t index)
Return a variable by index.
Definition: ShaderStage.h:88
const StringSet & getIncludes() const
Return a set of all include files.
Definition: ShaderStage.h:218
GLuint const GLchar * name
Definition: glcorearb.h:786
void setFunctionName(const string &functionName)
Set stage function name.
Definition: ShaderStage.h:284
MX_GENSHADER_API const string PIXEL
Syntax::Punctuation punctuation
Definition: ShaderStage.h:144
const vector< ShaderPort * > & getVariableOrder() const
Return a const reference to our variable order vector.
Definition: ShaderStage.h:94
std::set< FunctionCallId > functions
Definition: ShaderStage.h:145
size_t size() const
Return the number of variables in this block.
Definition: ShaderStage.h:85
void setInstance(const string &instance)
Set the instance name of this block.
Definition: ShaderStage.h:79
shared_ptr< ShaderStage > ShaderStagePtr
Shared pointer to a ShaderStage.
Definition: Library.h:36
Punctuation
Punctuation types.
Definition: Syntax.h:43
const VariableBlockMap & getUniformBlocks() const
Return a map of all uniform blocks.
Definition: ShaderStage.h:200
void setName(const string &name)
Set the name of this block.
Definition: ShaderStage.h:73
GLuint index
Definition: glcorearb.h:786
shared_ptr< class ShaderPort > ShaderPortPtr
Shared pointer to a ShaderPort.
Definition: ShaderNode.h:29
VariableBlock & getUniformBlock(const string &name)
Return the uniform variable block with given name.
const ShaderPort * operator[](size_t index) const
Return a variable by index.
Definition: ShaderStage.h:91
std::set< string > StringSet
A set of strings.
Definition: Library.h:61
Definition: core.h:1131
#define MATERIALX_NAMESPACE_END
Definition: Generated.h:26
VariableBlock & getOutputBlock(const string &name)
Return the output variable block with given name.
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const string & getFunctionName() const
Return the stage function name.
Definition: ShaderStage.h:158
std::pair< const ShaderNode *, int > FunctionCallId
Definition: ShaderStage.h:141
std::stringstream StringStream
A string stream.
Definition: Library.h:31
const string & getInstance() const
Get the instance name of this block.
Definition: ShaderStage.h:76
shared_ptr< Value > ValuePtr
A shared pointer to a Value.
Definition: Value.h:29
type
Definition: core.h:1059
const StringSet & getSourceDependencies() const
Return a set of all source dependencies.
Definition: ShaderStage.h:224
VariableBlockPtr createInputBlock(const string &name, const string &instance=EMPTY_STRING)
Create a new input variable block.
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2089
const string & getSourceCode() const
Return the stage source code.
Definition: ShaderStage.h:164
VariableBlock(const string &name, const string &instance)
Definition: ShaderStage.h:63