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 // TM & (c) 2017 Lucasfilm Entertainment Company Ltd. and Lucasfilm Ltd.
3 // All rights reserved. See LICENSE.txt for license.
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 <MaterialXCore/Node.h>
19 
20 #include <sstream>
21 
22 // Macro for begin/end of statements to be picked up by a given shader stage.
23 // For shaders that are multi-stage all code generation statements adding code
24 // to the shader should be wrapped inside such begin/end stating its target.
25 #define BEGIN_SHADER_STAGE(stage, name) if (stage.getName() == name) {
26 #define END_SHADER_STAGE(stage, name) }
27 
29 
30 namespace Stage
31 {
32  /// Identifier for pixel stage.
33  /// This is the main stage used by all shader targets.
34  /// For single stage shader targets this is the one
35  /// and only stage.
36  /// Shader targets with multiple stages can add additional
37  /// stage identifiers to the Stage namespace.
38  extern MX_GENSHADER_API const string PIXEL;
39 }
40 
41 class VariableBlock;
42 /// Shared pointer to a VariableBlock
43 using VariableBlockPtr = std::shared_ptr<VariableBlock>;
44 /// Shared pointer to a map between string identifiers and VariableBlocks
45 using VariableBlockMap = std::unordered_map<string, VariableBlockPtr>;
46 /// A standard function predicate taking an ShaderPort pointer and returning a boolean.
47 using ShaderPortPredicate = std::function<bool(ShaderPort*)>;
48 
49 /// @class VariableBlock
50 /// A block of variables in a shader stage
52 {
53  public:
54  VariableBlock(const string& name, const string& instance) :
55  _name(name),
56  _instance(instance)
57  {}
58 
59  /// Get the name of this block.
60  const string& getName() const { return _name; }
61 
62  /// Set the name of this block.
63  void setName(const string& name) { _name = name; }
64 
65  /// Get the instance name of this block.
66  const string& getInstance() const { return _instance; }
67 
68  /// Set the instance name of this block.
69  void setInstance(const string& instance) { _instance = instance; }
70 
71  /// Return true if the block has no variables.
72  bool empty() const { return _variableOrder.empty(); }
73 
74  /// Return the number of variables in this block.
75  size_t size() const { return _variableOrder.size(); }
76 
77  /// Return a variable by index.
78  ShaderPort* operator[](size_t index) { return _variableOrder[index]; }
79 
80  /// Return a variable by index.
81  const ShaderPort* operator[](size_t index) const { return _variableOrder[index]; }
82 
83  /// Return a const reference to our variable order vector.
84  const vector<ShaderPort*>& getVariableOrder() const { return _variableOrder; }
85 
86  /// Return a variable by name. Throws exception if
87  /// no variable is found by the given name.
88  ShaderPort* operator[](const string& name);
89 
90  /// Return a variable by name. Throws exception if
91  /// no variable is found by the given name.
92  const ShaderPort* operator[](const string& name) const;
93 
94  /// Return a variable by name. Returns nullptr if
95  /// no variable is found by the given name.
96  ShaderPort* find(const string& name);
97 
98  /// Return a variable by name. Returns nullptr if
99  /// no variable is found by the given name.
100  const ShaderPort* find(const string& name) const;
101 
102  /// Find a port based on a predicate
103  ShaderPort* find(const ShaderPortPredicate& predicate);
104 
105  /// Add a new shader port to this block.
106  ShaderPort* add(const TypeDesc* type, const string& name, ValuePtr value = nullptr);
107 
108  /// Add an existing shader port to this block.
109  void add(ShaderPortPtr port);
110 
111  private:
112  string _name;
113  string _instance;
114  std::unordered_map<string, ShaderPortPtr> _variableMap;
115  vector<ShaderPort*> _variableOrder;
116 };
117 
118 
119 /// @class ShaderStage
120 /// A shader stage, containing the state and
121 /// resulting source code for the stage.
123 {
124 public:
125  using FunctionCallId = std::pair<const ShaderNode*, int>;
126  struct Scope
127  {
129  std::set<FunctionCallId> functions;
130  Scope(Syntax::Punctuation p) : punctuation(p) {}
131  };
132 
133  public:
134  /// Contructor.
135  ShaderStage(const string& name, ConstSyntaxPtr syntax);
136 
137  /// Return the stage name.
138  const string& getName() const { return _name; }
139 
140  /// Return the stage function name.
141  const string& getFunctionName() const { return _functionName; }
142 
143  /// Set the stage source code.
144  void setSourceCode(const string& code) { _code = code; }
145 
146  /// Return the stage source code.
147  const string& getSourceCode() const { return _code; }
148 
149  /// Create a new uniform variable block.
150  VariableBlockPtr createUniformBlock(const string& name, const string& instance = EMPTY_STRING);
151 
152  /// Create a new input variable block.
153  VariableBlockPtr createInputBlock(const string& name, const string& instance = EMPTY_STRING);
154 
155  /// Create a new output variable block.
156  VariableBlockPtr createOutputBlock(const string& name, const string& instance = EMPTY_STRING);
157 
158  /// Return the uniform variable block with given name.
159  VariableBlock& getUniformBlock(const string& name);
160 
161  /// Return the uniform variable block with given name.
162  const VariableBlock& getUniformBlock(const string& name) const;
163 
164  /// Return the input variable block with given name.
165  VariableBlock& getInputBlock(const string& name);
166 
167  /// Return the input variable block with given name.
168  const VariableBlock& getInputBlock(const string& name) const;
169 
170  /// Return the output variable block with given name.
171  VariableBlock& getOutputBlock(const string& name);
172 
173  /// Return the output variable block with given name.
174  const VariableBlock& getOutputBlock(const string& name) const;
175 
176  /// Return the constant variable block.
177  VariableBlock& getConstantBlock();
178 
179  /// Return the constant variable block.
180  const VariableBlock& getConstantBlock() const;
181 
182  /// Return a map of all uniform blocks.
184  {
185  return _uniforms;
186  }
187 
188  /// Return a map of all input blocks.
190  {
191  return _inputs;
192  }
193 
194  /// Return a map of all output blocks.
196  {
197  return _outputs;
198  }
199 
200  /// Start a new scope using the given bracket type.
201  void beginScope(Syntax::Punctuation punc = Syntax::CURLY_BRACKETS);
202 
203  /// End the current scope.
204  void endScope(bool semicolon = false, bool newline = true);
205 
206  /// Start a new line.
207  void beginLine();
208 
209  /// End the current line.
210  void endLine(bool semicolon = true);
211 
212  /// Add a newline character.
213  void newLine();
214 
215  /// Add a string.
216  void addString(const string& str);
217 
218  /// Add a single line of code, optionally appending a semicolon.
219  void addLine(const string& str, bool semicolon = true);
220 
221  /// Add a single line code comment.
222  void addComment(const string& str);
223 
224  /// Add a block of code.
225  void addBlock(const string& str, GenContext& context);
226 
227  /// Add the contents of an include file. Making sure it is
228  /// only included once for the shader stage.
229  void addInclude(const string& file, GenContext& context);
230 
231  /// Add a value.
232  template<typename T>
233  void addValue(const T& value)
234  {
235  StringStream str;
236  str << value;
237  _code += str.str();
238  }
239 
240  /// Add the function definition for a node's implementation.
241  void addFunctionDefinition(const ShaderNode& node, GenContext& context);
242 
243  /// Add the function call for the given node.
244  void addFunctionCall(const ShaderNode& node, GenContext& context);
245 
246  /// Return true if the function for the given node has been emitted in the current scope.
247  bool isEmitted(const ShaderNode& node, GenContext& context) const;
248 
249  /// Set stage function name.
250  void setFunctionName(const string& functionName)
251  {
252  _functionName = functionName;
253  }
254 
255  private:
256  /// Name of the stage
257  const string _name;
258 
259  /// Name of the stage main function
260  string _functionName;
261 
262  /// Syntax for the type of shader to generate.
263  ConstSyntaxPtr _syntax;
264 
265  /// Current indentation level.
266  int _indentations;
267 
268  /// Current scope.
269  vector<Scope> _scopes;
270 
271  /// Set of include files that has been included.
272  StringSet _includes;
273 
274  /// Set of hash ID's for functions that has been defined.
275  std::set<size_t> _definedFunctions;
276 
277  /// Block holding constant variables for this stage.
278  VariableBlock _constants;
279 
280  /// Map of blocks holding uniform variables for this stage.
281  VariableBlockMap _uniforms;
282 
283  /// Map of blocks holding input variables for this stage.
284  VariableBlockMap _inputs;
285 
286  /// Map of blocks holding output variables for this stage.
287  VariableBlockMap _outputs;
288 
289  /// Resulting source code for this stage.
290  string _code;
291 
292  friend class ShaderGenerator;
293 };
294 
295 /// Shared pointer to a ShaderStage
296 using ShaderStagePtr = std::shared_ptr<ShaderStage>;
297 
298 /// Utility function for adding a new shader port to a uniform block.
299 inline ShaderPort* addStageUniform(const string& block,
300  const TypeDesc* type,
301  const string& name,
302  ShaderStage& stage)
303 {
304  VariableBlock& uniforms = stage.getUniformBlock(block);
305  return uniforms.add(type, name);
306 }
307 
308 /// Utility function for adding a new shader port to an input block.
309 inline ShaderPort* addStageInput(const string& block,
310  const TypeDesc* type,
311  const string& name,
312  ShaderStage& stage)
313 {
314  VariableBlock& inputs = stage.getInputBlock(block);
315  return inputs.add(type, name);
316 }
317 
318 /// Utility function for adding a new shader port to an output block.
319 inline ShaderPort* addStageOutput(const string& block,
320  const TypeDesc* type,
321  const string& name,
322  ShaderStage& stage)
323 {
324  VariableBlock& outputs = stage.getOutputBlock(block);
325  return outputs.add(type, name);
326 }
327 
328 /// Utility function for adding a connector block between stages.
329 inline void addStageConnectorBlock(const string& block,
330  const string& instance,
331  ShaderStage& from,
332  ShaderStage& to)
333 {
334  from.createOutputBlock(block, instance);
335  to.createInputBlock(block, instance);
336 }
337 
338 /// Utility function for adding a variable to a stage connector block.
339 inline void addStageConnector(const string& block,
340  const TypeDesc* type,
341  const string& name,
342  ShaderStage& from,
343  ShaderStage& to)
344 {
345  addStageOutput(block, type, name, from);
346  addStageInput(block, type, name, to);
347 }
348 
350 
351 #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:339
void addStageConnectorBlock(const string &block, const string &instance, ShaderStage &from, ShaderStage &to)
Utility function for adding a connector block between stages.
Definition: ShaderStage.h:329
void addValue(const T &value)
Add a value.
Definition: ShaderStage.h:233
#define MATERIALX_NAMESPACE_BEGIN
Definition: Generated.h:23
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:309
bool empty() const
Return true if the block has no variables.
Definition: ShaderStage.h:72
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:299
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:195
#define MX_GENSHADER_API
Definition: Export.h:18
GLuint const GLchar * name
Definition: glcorearb.h:786
const VariableBlockMap & getInputBlocks() const
Return a map of all input blocks.
Definition: ShaderStage.h:189
const string & getName() const
Return the stage name.
Definition: ShaderStage.h:138
void setSourceCode(const string &code)
Set the stage source code.
Definition: ShaderStage.h:144
std::shared_ptr< VariableBlock > VariableBlockPtr
Shared pointer to a VariableBlock.
Definition: ShaderStage.h:43
const string & getName() const
Get the name of this block.
Definition: ShaderStage.h:60
std::function< bool(ShaderPort *)> ShaderPortPredicate
A standard function predicate taking an ShaderPort pointer and returning a boolean.
Definition: ShaderStage.h:47
Scope(Syntax::Punctuation p)
Definition: ShaderStage.h:130
std::unordered_map< string, VariableBlockPtr > VariableBlockMap
Shared pointer to a map between string identifiers and VariableBlocks.
Definition: ShaderStage.h:45
VariableBlock & getInputBlock(const string &name)
Return the input variable block with given name.
GLfloat GLfloat p
Definition: glew.h:16656
ShaderPort * operator[](size_t index)
Return a variable by index.
Definition: ShaderStage.h:78
ShaderPort * add(const TypeDesc *type, const string &name, ValuePtr value=nullptr)
Add a new shader port to this block.
void setFunctionName(const string &functionName)
Set stage function name.
Definition: ShaderStage.h:250
MX_GENSHADER_API const string PIXEL
Syntax::Punctuation punctuation
Definition: ShaderStage.h:128
const vector< ShaderPort * > & getVariableOrder() const
Return a const reference to our variable order vector.
Definition: ShaderStage.h:84
std::set< FunctionCallId > functions
Definition: ShaderStage.h:129
size_t size() const
Return the number of variables in this block.
Definition: ShaderStage.h:75
void setInstance(const string &instance)
Set the instance name of this block.
Definition: ShaderStage.h:69
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:183
void setName(const string &name)
Set the name of this block.
Definition: ShaderStage.h:63
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.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
const ShaderPort * operator[](size_t index) const
Return a variable by index.
Definition: ShaderStage.h:81
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:319
std::set< string > StringSet
A set of strings.
Definition: Library.h:61
Definition: core.h:1131
#define MATERIALX_NAMESPACE_END
Definition: Generated.h:24
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:141
std::pair< const ShaderNode *, int > FunctionCallId
Definition: ShaderStage.h:125
type
Definition: core.h:1059
std::stringstream StringStream
A string stream.
Definition: Library.h:31
const string & getInstance() const
Get the instance name of this block.
Definition: ShaderStage.h:66
shared_ptr< Value > ValuePtr
A shared pointer to a Value.
Definition: Value.h:29
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:147
VariableBlock(const string &name, const string &instance)
Definition: ShaderStage.h:54