HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ShaderGraph.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_SHADERGRAPH_H
7 #define MATERIALX_SHADERGRAPH_H
8 
9 /// @file
10 /// Shader graph class
11 
13 
19 
20 #include <MaterialXCore/Document.h>
21 #include <MaterialXCore/Node.h>
22 
24 
25 class Syntax;
26 class ShaderGraphEdge;
28 class GenOptions;
29 
30 /// An internal input socket in a shader graph,
31 /// used for connecting internal nodes to the outside
33 
34 /// An internal output socket in a shader graph,
35 /// used for connecting internal nodes to the outside
37 
38 /// A shared pointer to a shader graph
39 using ShaderGraphPtr = shared_ptr<class ShaderGraph>;
40 
41 /// @class ShaderGraph
42 /// Class representing a graph (DAG) for shader generation
44 {
45  public:
46  /// Constructor.
47  ShaderGraph(const ShaderGraph* parent, const string& name, ConstDocumentPtr document, const StringSet& reservedWords);
48 
49  /// Desctructor.
50  virtual ~ShaderGraph() { }
51 
52  /// Create a new shader graph from an element.
53  /// Supported elements are outputs and shader nodes.
54  static ShaderGraphPtr create(const ShaderGraph* parent, const string& name, ElementPtr element,
55  GenContext& context);
56 
57  /// Create a new shader graph from a nodegraph.
58  static ShaderGraphPtr create(const ShaderGraph* parent, const NodeGraph& nodeGraph,
59  GenContext& context);
60 
61  /// Return true if this node is a graph.
62  bool isAGraph() const override { return true; }
63 
64  /// Get an internal node by name
65  ShaderNode* getNode(const string& name);
66 
67  /// Get an internal node by name
68  const ShaderNode* getNode(const string& name) const;
69 
70  /// Get a vector of all nodes in order
71  const vector<ShaderNode*>& getNodes() const { return _nodeOrder; }
72 
73  /// Get number of input sockets
74  size_t numInputSockets() const { return numOutputs(); }
75 
76  /// Get number of output sockets
77  size_t numOutputSockets() const { return numInputs(); }
78 
79  /// Get socket by index
82  const ShaderGraphInputSocket* getInputSocket(size_t index) const { return getOutput(index); }
83  const ShaderGraphOutputSocket* getOutputSocket(size_t index = 0) const { return getInput(index); }
84 
85  /// Get socket by name
86  ShaderGraphInputSocket* getInputSocket(const string& name) { return getOutput(name); }
87  ShaderGraphOutputSocket* getOutputSocket(const string& name) { return getInput(name); }
88  const ShaderGraphInputSocket* getInputSocket(const string& name) const { return getOutput(name); }
89  const ShaderGraphOutputSocket* getOutputSocket(const string& name) const { return getInput(name); }
90 
91  /// Get vector of sockets
92  const vector<ShaderGraphInputSocket*>& getInputSockets() const { return _outputOrder; }
93  const vector<ShaderGraphOutputSocket*>& getOutputSockets() const { return _inputOrder; }
94 
95  /// Create a new node in the graph
96  ShaderNode* createNode(const Node& node, GenContext& context);
97 
98  /// Add input/output sockets
99  ShaderGraphInputSocket* addInputSocket(const string& name, const TypeDesc* type);
100  ShaderGraphOutputSocket* addOutputSocket(const string& name, const TypeDesc* type);
101 
102  /// Return an iterator for traversal upstream from the given output
103  static ShaderGraphEdgeIterator traverseUpstream(ShaderOutput* output);
104 
105  /// Return the map of unique identifiers used in the scope of this graph.
106  IdentifierMap& getIdentifierMap() { return _identifiers; }
107 
108  protected:
109  static ShaderGraphPtr createSurfaceShader(
110  const string& name,
111  const ShaderGraph* parent,
112  NodePtr node,
113  GenContext& context,
114  ElementPtr& root);
115 
116  /// Create node connections corresponding to the connection between a pair of elements.
117  /// @param downstreamElement Element representing the node to connect to.
118  /// @param upstreamElement Element representing the node to connect from
119  /// @param connectingElement If non-null, specifies the element on on the downstream node to connect to.
120  /// @param context Context for generation.
121  void createConnectedNodes(const ElementPtr& downstreamElement,
122  const ElementPtr& upstreamElement,
123  ElementPtr connectingElement,
124  GenContext& context);
125 
126  /// Add a node to the graph
127  void addNode(ShaderNodePtr node);
128 
129  /// Add input sockets from an interface element (nodedef, nodegraph or node)
130  void addInputSockets(const InterfaceElement& elem, GenContext& context);
131 
132  /// Add output sockets from an interface element (nodedef, nodegraph or node)
133  void addOutputSockets(const InterfaceElement& elem);
134 
135  /// Traverse from the given root element and add all dependencies upstream.
136  /// The traversal is done in the context of a material, if given, to include
137  /// bind input elements in the traversal.
138  void addUpstreamDependencies(const Element& root, GenContext& context);
139 
140  /// Add a default geometric node and connect to the given input.
141  void addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geomprop, GenContext& context);
142 
143  /// Add a color transform node and connect to the given input.
144  void addColorTransformNode(ShaderInput* input, const ColorSpaceTransform& transform, GenContext& context);
145 
146  /// Add a color transform node and connect to the given output.
147  void addColorTransformNode(ShaderOutput* output, const ColorSpaceTransform& transform, GenContext& context);
148 
149  /// Add a unit transform node and connect to the given input.
150  void addUnitTransformNode(ShaderInput* input, const UnitTransform& transform, GenContext& context);
151 
152  /// Add a unit transform node and connect to the given output.
153  void addUnitTransformNode(ShaderOutput* output, const UnitTransform& transform, GenContext& context);
154 
155  /// Perform all post-build operations on the graph.
156  void finalize(GenContext& context);
157 
158  /// Optimize the graph, removing redundant paths.
159  void optimize(GenContext& context);
160 
161  /// Bypass a node for a particular input and output,
162  /// effectively connecting the input's upstream connection
163  /// with the output's downstream connections.
164  void bypass(GenContext& context, ShaderNode* node, size_t inputIndex, size_t outputIndex = 0);
165 
166  /// Sort the nodes in topological order.
167  /// @throws ExceptionFoundCycle if a cycle is encountered.
168  void topologicalSort();
169 
170  /// Calculate scopes for all nodes in the graph
171  void calculateScopes();
172 
173  /// For inputs and outputs in the graph set the variable names to be used
174  /// in generated code. Making sure variable names are valid and unique
175  /// to avoid name conflicts during shader generation.
176  void setVariableNames(GenContext& context);
177 
178  /// Populates the input or output color transform map if the provided input/parameter
179  /// has a color space attribute and has a type of color3 or color4.
180  string populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort, ValueElementPtr element, const string& targetColorSpace, bool asInput);
181 
182  /// Populates the appropriate unit transform map if the provided input/parameter or output
183  /// has a unit attribute and is of the supported type
184  void populateUnitTransformMap(UnitSystemPtr unitSystem, ShaderPort* shaderPort, ValueElementPtr element, const string& targetUnitSpace, bool asInput);
185 
186  /// Break all connections on a node
187  void disconnect(ShaderNode* node) const;
188 
190  std::unordered_map<string, ShaderNodePtr> _nodeMap;
191  std::vector<ShaderNode*> _nodeOrder;
193 
194  // Temporary storage for inputs that require color transformations
195  std::unordered_map<ShaderInput*, ColorSpaceTransform> _inputColorTransformMap;
196  // Temporary storage for inputs that require unit transformations
197  std::unordered_map<ShaderInput*, UnitTransform> _inputUnitTransformMap;
198 
199  // Temporary storage for outputs that require color transformations
200  std::unordered_map<ShaderOutput*, ColorSpaceTransform> _outputColorTransformMap;
201  // Temporary storage for outputs that require unit transformations
202  std::unordered_map<ShaderOutput*, UnitTransform> _outputUnitTransformMap;
203 };
204 
205 /// @class ShaderGraphEdge
206 /// An edge returned during shader graph traversal.
208 {
209  public:
211  upstream(up),
212  downstream(down)
213  {}
216 };
217 
218 /// @class ShaderGraphEdgeIterator
219 /// Iterator class for traversing edges between nodes in a shader graph.
221 {
222  public:
225 
226  bool operator==(const ShaderGraphEdgeIterator& rhs) const
227  {
228  return _upstream == rhs._upstream &&
229  _downstream == rhs._downstream &&
230  _stack == rhs._stack;
231  }
232  bool operator!=(const ShaderGraphEdgeIterator& rhs) const
233  {
234  return !(*this == rhs);
235  }
236 
237  /// Dereference this iterator, returning the current output in the traversal.
239  {
240  return ShaderGraphEdge(_upstream, _downstream);
241  }
242 
243  /// Iterate to the next edge in the traversal.
244  /// @throws ExceptionFoundCycle if a cycle is encountered.
245  ShaderGraphEdgeIterator& operator++();
246 
247  /// Return a reference to this iterator to begin traversal
249  {
250  return *this;
251  }
252 
253  /// Return the end iterator.
254  static const ShaderGraphEdgeIterator& end();
255 
256  private:
257  void extendPathUpstream(ShaderOutput* upstream, ShaderInput* downstream);
258  void returnPathDownstream(ShaderOutput* upstream);
259 
260  ShaderOutput* _upstream;
261  ShaderInput* _downstream;
262  using StackFrame = std::pair<ShaderOutput*, size_t>;
263  std::vector<StackFrame> _stack;
264  std::set<ShaderOutput*> _path;
265 };
266 
268 
269 #endif
std::unordered_map< ShaderInput *, UnitTransform > _inputUnitTransformMap
Definition: ShaderGraph.h:197
ShaderGraphEdge operator*() const
Dereference this iterator, returning the current output in the traversal.
Definition: ShaderGraph.h:238
ShaderGraphInputSocket * getInputSocket(size_t index)
Get socket by index.
Definition: ShaderGraph.h:80
friend class ShaderGraph
Definition: ShaderNode.h:532
vector< ShaderInput * > _inputOrder
Definition: ShaderNode.h:523
bool operator==(const ShaderGraphEdgeIterator &rhs) const
Definition: ShaderGraph.h:226
std::unordered_map< string, ShaderNodePtr > _nodeMap
Definition: ShaderGraph.h:190
#define MATERIALX_NAMESPACE_BEGIN
Definition: Generated.h:23
ShaderOutput * getOutput(size_t index=0)
Definition: ShaderNode.h:475
Definition: Node.h:52
ShaderInput * getInput(size_t index)
Get inputs/outputs by index.
Definition: ShaderNode.h:474
GLenum GLenum GLenum input
Definition: glew.h:14162
shared_ptr< class UnitSystem > UnitSystemPtr
A shared pointer to a UnitSystem.
Definition: UnitSystem.h:26
vector< ShaderOutput * > _outputOrder
Definition: ShaderNode.h:526
ShaderGraphOutputSocket * getOutputSocket(const string &name)
Definition: ShaderGraph.h:87
size_t numOutputs() const
Definition: ShaderNode.h:471
#define MX_GENSHADER_API
Definition: Export.h:18
GLuint const GLchar * name
Definition: glcorearb.h:786
const vector< ShaderGraphOutputSocket * > & getOutputSockets() const
Definition: ShaderGraph.h:93
ShaderGraphOutputSocket * getOutputSocket(size_t index=0)
Definition: ShaderGraph.h:81
const ShaderGraphInputSocket * getInputSocket(size_t index) const
Definition: ShaderGraph.h:82
std::vector< ShaderNode * > _nodeOrder
Definition: ShaderGraph.h:191
bool operator!=(const ShaderGraphEdgeIterator &rhs) const
Definition: ShaderGraph.h:232
ShaderGraphEdgeIterator & begin()
Return a reference to this iterator to begin traversal.
Definition: ShaderGraph.h:248
size_t numInputSockets() const
Get number of input sockets.
Definition: ShaderGraph.h:74
GLuint GLenum GLenum transform
Definition: glew.h:15055
ShaderGraphEdge(ShaderOutput *up, ShaderInput *down)
Definition: ShaderGraph.h:210
shared_ptr< class ColorManagementSystem > ColorManagementSystemPtr
A shared pointer to a ColorManagementSystem.
ShaderGraphInputSocket * getInputSocket(const string &name)
Get socket by name.
Definition: ShaderGraph.h:86
shared_ptr< class ShaderNode > ShaderNodePtr
Shared pointer to a ShaderNode.
Definition: ShaderNode.h:35
ShaderInput * downstream
Definition: ShaderGraph.h:215
GLuint GLuint end
Definition: glcorearb.h:475
static ShaderNodePtr create(const ShaderGraph *parent, const string &name, const NodeDef &nodeDef, GenContext &context)
Create a new node from a nodedef.
shared_ptr< class ShaderGraph > ShaderGraphPtr
A shared pointer to a shader graph.
Definition: ShaderGraph.h:39
const ShaderGraphOutputSocket * getOutputSocket(size_t index=0) const
Definition: ShaderGraph.h:83
const ShaderGraphOutputSocket * getOutputSocket(const string &name) const
Definition: ShaderGraph.h:89
size_t numOutputSockets() const
Get number of output sockets.
Definition: ShaderGraph.h:77
virtual ~ShaderGraph()
Desctructor.
Definition: ShaderGraph.h:50
std::unordered_map< ShaderOutput *, ColorSpaceTransform > _outputColorTransformMap
Definition: ShaderGraph.h:200
ShaderOutput * upstream
Definition: ShaderGraph.h:214
bool isAGraph() const override
Return true if this node is a graph.
Definition: ShaderGraph.h:62
IdentifierMap _identifiers
Definition: ShaderGraph.h:192
const vector< ShaderNode * > & getNodes() const
Get a vector of all nodes in order.
Definition: ShaderGraph.h:71
GA_API const UT_StringHolder up
std::unordered_map< string, size_t > IdentifierMap
Definition: Syntax.h:34
GLuint index
Definition: glcorearb.h:786
const ShaderGraphInputSocket * getInputSocket(const string &name) const
Definition: ShaderGraph.h:88
const vector< ShaderGraphInputSocket * > & getInputSockets() const
Get vector of sockets.
Definition: ShaderGraph.h:92
std::set< string > StringSet
A set of strings.
Definition: Library.h:61
std::unordered_map< ShaderOutput *, UnitTransform > _outputUnitTransformMap
Definition: ShaderGraph.h:202
shared_ptr< Element > ElementPtr
A shared pointer to an Element.
Definition: Element.h:30
shared_ptr< ValueElement > ValueElementPtr
A shared pointer to a ValueElement.
Definition: Element.h:40
#define MATERIALX_NAMESPACE_END
Definition: Generated.h:24
std::unordered_map< ShaderInput *, ColorSpaceTransform > _inputColorTransformMap
Definition: ShaderGraph.h:195
size_t numInputs() const
Get number of inputs/outputs.
Definition: ShaderNode.h:470
type
Definition: core.h:1059
Definition: Syntax.h:39
ConstDocumentPtr _document
Definition: ShaderGraph.h:189
shared_ptr< const Document > ConstDocumentPtr
A shared pointer to a const Document.
Definition: Document.h:24
IdentifierMap & getIdentifierMap()
Return the map of unique identifiers used in the scope of this graph.
Definition: ShaderGraph.h:106
shared_ptr< Node > NodePtr
A shared pointer to a Node.
Definition: Node.h:24