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  ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr);
117 
118  /// Add an existing shader port to this block.
119  void add(ShaderPortPtr port);
120 
121  private:
122  string _name;
123  string _instance;
124  std::unordered_map<string, ShaderPortPtr> _variableMap;
125  vector<ShaderPort*> _variableOrder;
126 };
127 
128 /// @class ShaderStage
129 /// A shader stage, containing the state and
130 /// resulting source code for the stage.
132 {
133  public:
134  using FunctionCallId = std::pair<const ShaderNode*, int>;
135  struct Scope
136  {
138  std::set<FunctionCallId> functions;
140  punctuation(p) { }
141  };
142 
143  public:
144  /// Contructor.
145  ShaderStage(const string& name, ConstSyntaxPtr syntax);
146 
147  /// Return the stage name.
148  const string& getName() const { return _name; }
149 
150  /// Return the stage function name.
151  const string& getFunctionName() const { return _functionName; }
152 
153  /// Set the stage source code.
154  void setSourceCode(const string& code) { _code = code; }
155 
156  /// Return the stage source code.
157  const string& getSourceCode() const { return _code; }
158 
159  /// Create a new uniform variable block.
160  VariableBlockPtr createUniformBlock(const string& name, const string& instance = EMPTY_STRING);
161 
162  /// Create a new input variable block.
163  VariableBlockPtr createInputBlock(const string& name, const string& instance = EMPTY_STRING);
164 
165  /// Create a new output variable block.
166  VariableBlockPtr createOutputBlock(const string& name, const string& instance = EMPTY_STRING);
167 
168  /// Return the uniform variable block with given name.
169  VariableBlock& getUniformBlock(const string& name);
170 
171  /// Return the uniform variable block with given name.
172  const VariableBlock& getUniformBlock(const string& name) const;
173 
174  /// Return the input variable block with given name.
175  VariableBlock& getInputBlock(const string& name);
176 
177  /// Return the input variable block with given name.
178  const VariableBlock& getInputBlock(const string& name) const;
179 
180  /// Return the output variable block with given name.
181  VariableBlock& getOutputBlock(const string& name);
182 
183  /// Return the output variable block with given name.
184  const VariableBlock& getOutputBlock(const string& name) const;
185 
186  /// Return the constant variable block.
187  VariableBlock& getConstantBlock();
188 
189  /// Return the constant variable block.
190  const VariableBlock& getConstantBlock() const;
191 
192  /// Return a map of all uniform blocks.
194  {
195  return _uniforms;
196  }
197 
198  /// Return a map of all input blocks.
200  {
201  return _inputs;
202  }
203 
204  /// Return a map of all output blocks.
206  {
207  return _outputs;
208  }
209 
210  /// Return a set of all include files
211  const StringSet& getIncludes() const
212  {
213  return _includes;
214  }
215 
216  /// Return a set of all source dependencies
218  {
219  return _sourceDependencies;
220  }
221 
222  /// Start a new scope using the given bracket type.
223  void beginScope(Syntax::Punctuation punc = Syntax::CURLY_BRACKETS);
224 
225  /// End the current scope.
226  void endScope(bool semicolon = false, bool newline = true);
227 
228  /// Start a new line.
229  void beginLine();
230 
231  /// End the current line.
232  void endLine(bool semicolon = true);
233 
234  /// Add a newline character.
235  void newLine();
236 
237  /// Add a string.
238  void addString(const string& str);
239 
240  /// Add a single line of code, optionally appending a semicolon.
241  void addLine(const string& str, bool semicolon = true);
242 
243  /// Add a single line code comment.
244  void addComment(const string& str);
245 
246  /// Add a block of code.
247  void addBlock(const string& str, const FilePath& sourceFilename, GenContext& context);
248 
249  /// Add the contents of an include file if not already present.
250  void addInclude(const FilePath& includeFilename, const FilePath& sourceFilename, GenContext& context);
251 
252  /// Add a source file dependency for dependency tracking purposes
253  void addSourceDependency(const FilePath& file);
254 
255  /// Add a value.
256  template <typename T>
257  void addValue(const T& value)
258  {
259  StringStream str;
260  str << value;
261  _code += str.str();
262  }
263 
264  /// Add the function definition for a node's implementation.
265  void addFunctionDefinition(const ShaderNode& node, GenContext& context);
266 
267  /// Add the function call for the given node.
268  /// This will register the function as being called in the current scope, and code for the
269  /// function call will be added to the stage. If emitCode is set to false the code for the
270  /// function call will be omitted.
271  void addFunctionCall(const ShaderNode& node, GenContext& context, bool emitCode = true);
272 
273  /// Return true if the function for the given node has been emitted in the current scope.
274  bool isEmitted(const ShaderNode& node, GenContext& context) const;
275 
276  /// Set stage function name.
277  void setFunctionName(const string& functionName)
278  {
279  _functionName = functionName;
280  }
281 
282  private:
283  /// Name of the stage
284  const string _name;
285 
286  /// Name of the stage main function
287  string _functionName;
288 
289  /// Syntax for the type of shader to generate.
290  ConstSyntaxPtr _syntax;
291 
292  /// Current indentation level.
293  int _indentations;
294 
295  /// Current scope.
296  vector<Scope> _scopes;
297 
298  /// Set of include files that has been included.
299  StringSet _includes;
300 
301  /// Set of source file dependencies from source code nodes
302  StringSet _sourceDependencies;
303 
304  /// Set of hash ID's for functions that has been defined.
305  std::set<size_t> _definedFunctions;
306 
307  /// Block holding constant variables for this stage.
308  VariableBlock _constants;
309 
310  /// Map of blocks holding uniform variables for this stage.
311  VariableBlockMap _uniforms;
312 
313  /// Map of blocks holding input variables for this stage.
314  VariableBlockMap _inputs;
315 
316  /// Map of blocks holding output variables for this stage.
317  VariableBlockMap _outputs;
318 
319  /// Resulting source code for this stage.
320  string _code;
321 
322  friend class ShaderGenerator;
323 };
324 
325 /// Shared pointer to a ShaderStage
326 using ShaderStagePtr = std::shared_ptr<ShaderStage>;
327 
328 /// Utility function for adding a new shader port to a uniform block.
329 inline ShaderPort* addStageUniform(const string& block,
330  const TypeDesc* type,
331  const string& name,
332  ShaderStage& stage)
333 {
334  VariableBlock& uniforms = stage.getUniformBlock(block);
335  return uniforms.add(type, name);
336 }
337 
338 /// Utility function for adding a new shader port to an input block.
339 inline ShaderPort* addStageInput(const string& block,
340  const TypeDesc* type,
341  const string& name,
342  ShaderStage& stage)
343 {
344  VariableBlock& inputs = stage.getInputBlock(block);
345  return inputs.add(type, name);
346 }
347 
348 /// Utility function for adding a new shader port to an output block.
349 inline ShaderPort* addStageOutput(const string& block,
350  const TypeDesc* type,
351  const string& name,
352  ShaderStage& stage)
353 {
354  VariableBlock& outputs = stage.getOutputBlock(block);
355  return outputs.add(type, name);
356 }
357 
358 /// Utility function for adding a connector block between stages.
359 inline void addStageConnectorBlock(const string& block,
360  const string& instance,
361  ShaderStage& from,
362  ShaderStage& to)
363 {
364  from.createOutputBlock(block, instance);
365  to.createInputBlock(block, instance);
366 }
367 
368 /// Utility function for adding a variable to a stage connector block.
369 inline void addStageConnector(const string& block,
370  const TypeDesc* type,
371  const string& name,
372  ShaderStage& from,
373  ShaderStage& to)
374 {
375  addStageOutput(block, type, name, from);
376  addStageInput(block, type, name, to);
377 }
378 
380 
381 #endif
void addStageConnector(const string &block, const TypeDesc *type, const string &name, ShaderStage &from, ShaderStage &to)
Utility function for adding a variable to a stage connector block.
Definition: ShaderStage.h:369
void addStageConnectorBlock(const string &block, const string &instance, ShaderStage &from, ShaderStage &to)
Utility function for adding a connector block between stages.
Definition: ShaderStage.h:359
Definition: File.h:26
void addValue(const T &value)
Add a value.
Definition: ShaderStage.h:257
#define MATERIALX_NAMESPACE_BEGIN
Definition: Generated.h:25
ShaderPort * addStageInput(const string &block, const TypeDesc *type, const string &name, ShaderStage &stage)
Utility function for adding a new shader port to an input block.
Definition: ShaderStage.h:339
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:329
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:205
#define MX_GENSHADER_API
Definition: Export.h:18
const VariableBlockMap & getInputBlocks() const
Return a map of all input blocks.
Definition: ShaderStage.h:199
const string & getName() const
Return the stage name.
Definition: ShaderStage.h:148
void setSourceCode(const string &code)
Set the stage source code.
Definition: ShaderStage.h:154
std::shared_ptr< VariableBlock > VariableBlockPtr
Shared pointer to a VariableBlock.
Definition: ShaderStage.h:52
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:139
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.
ShaderPort * operator[](size_t index)
Return a variable by index.
Definition: ShaderStage.h:88
ShaderPort * add(const TypeDesc *type, const string &name, ValuePtr value=nullptr)
Add a new shader port to this block.
const StringSet & getIncludes() const
Return a set of all include files.
Definition: ShaderStage.h:211
GLuint const GLchar * name
Definition: glcorearb.h:786
void setFunctionName(const string &functionName)
Set stage function name.
Definition: ShaderStage.h:277
MX_GENSHADER_API const string PIXEL
Syntax::Punctuation punctuation
Definition: ShaderStage.h:137
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:138
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:193
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
ShaderPort * addStageOutput(const string &block, const TypeDesc *type, const string &name, ShaderStage &stage)
Utility function for adding a new shader port to an output block.
Definition: ShaderStage.h:349
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:151
std::pair< const ShaderNode *, int > FunctionCallId
Definition: ShaderStage.h:134
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:217
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:157
VariableBlock(const string &name, const string &instance)
Definition: ShaderStage.h:63