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 // Copyright Contributors to the MaterialX Project
3 // SPDX-License-Identifier: Apache-2.0
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  /// Apply color and unit transforms to each input of a node.
96  void applyInputTransforms(ConstNodePtr node, ShaderNodePtr shaderNode, GenContext& context);
97 
98  /// Create a new node in the graph
99  ShaderNode* createNode(ConstNodePtr node, GenContext& context);
100 
101  /// Add input/output sockets
102  ShaderGraphInputSocket* addInputSocket(const string& name, const TypeDesc* type);
103  ShaderGraphOutputSocket* addOutputSocket(const string& name, const TypeDesc* type);
104 
105  /// Add a default geometric node and connect to the given input.
106  void addDefaultGeomNode(ShaderInput* input, const GeomPropDef& geomprop, GenContext& context);
107 
108  /// Sort the nodes in topological order.
109  void topologicalSort();
110 
111  /// Return an iterator for traversal upstream from the given output
112  static ShaderGraphEdgeIterator traverseUpstream(ShaderOutput* output);
113 
114  /// Return the map of unique identifiers used in the scope of this graph.
115  IdentifierMap& getIdentifierMap() { return _identifiers; }
116 
117  protected:
118  /// Create node connections corresponding to the connection between a pair of elements.
119  /// @param downstreamElement Element representing the node to connect to.
120  /// @param upstreamElement Element representing the node to connect from
121  /// @param connectingElement If non-null, specifies the element on on the downstream node to connect to.
122  /// @param context Context for generation.
123  void createConnectedNodes(const ElementPtr& downstreamElement,
124  const ElementPtr& upstreamElement,
125  ElementPtr connectingElement,
126  GenContext& context);
127 
128  /// Add a node to the graph
129  void addNode(ShaderNodePtr node);
130 
131  /// Add input sockets from an interface element (nodedef, nodegraph or node)
132  void addInputSockets(const InterfaceElement& elem, GenContext& context);
133 
134  /// Add output sockets from an interface element (nodedef, nodegraph or node)
135  void addOutputSockets(const InterfaceElement& elem);
136 
137  /// Traverse from the given root element and add all dependencies upstream.
138  /// The traversal is done in the context of a material, if given, to include
139  /// bind input elements in the traversal.
140  void addUpstreamDependencies(const Element& root, GenContext& context);
141 
142  /// Add a color transform node and connect to the given input.
143  void addColorTransformNode(ShaderInput* input, const ColorSpaceTransform& transform, GenContext& context);
144 
145  /// Add a color transform node and connect to the given output.
146  void addColorTransformNode(ShaderOutput* output, const ColorSpaceTransform& transform, GenContext& context);
147 
148  /// Add a unit transform node and connect to the given input.
149  void addUnitTransformNode(ShaderInput* input, const UnitTransform& transform, GenContext& context);
150 
151  /// Add a unit transform node and connect to the given output.
152  void addUnitTransformNode(ShaderOutput* output, const UnitTransform& transform, GenContext& context);
153 
154  /// Perform all post-build operations on the graph.
155  void finalize(GenContext& context);
156 
157  /// Optimize the graph, removing redundant paths.
158  void optimize(GenContext& context);
159 
160  /// Bypass a node for a particular input and output,
161  /// effectively connecting the input's upstream connection
162  /// with the output's downstream connections.
163  void bypass(GenContext& context, ShaderNode* node, size_t inputIndex, size_t outputIndex = 0);
164 
165  /// For inputs and outputs in the graph set the variable names to be used
166  /// in generated code. Making sure variable names are valid and unique
167  /// to avoid name conflicts during shader generation.
168  void setVariableNames(GenContext& context);
169 
170  /// Populate the color transform map for the given shader port, if the provided combination of
171  /// source and target color spaces are supported for its data type.
172  void populateColorTransformMap(ColorManagementSystemPtr colorManagementSystem, ShaderPort* shaderPort,
173  const string& sourceColorSpace, const string& targetColorSpace, bool asInput);
174 
175  /// Populates the appropriate unit transform map if the provided input/parameter or output
176  /// has a unit attribute and is of the supported type
177  void populateUnitTransformMap(UnitSystemPtr unitSystem, ShaderPort* shaderPort, ValueElementPtr element, const string& targetUnitSpace, bool asInput);
178 
179  /// Break all connections on a node
180  void disconnect(ShaderNode* node) const;
181 
183  std::unordered_map<string, ShaderNodePtr> _nodeMap;
184  std::vector<ShaderNode*> _nodeOrder;
186 
187  // Temporary storage for inputs that require color transformations
188  std::unordered_map<ShaderInput*, ColorSpaceTransform> _inputColorTransformMap;
189  // Temporary storage for inputs that require unit transformations
190  std::unordered_map<ShaderInput*, UnitTransform> _inputUnitTransformMap;
191 
192  // Temporary storage for outputs that require color transformations
193  std::unordered_map<ShaderOutput*, ColorSpaceTransform> _outputColorTransformMap;
194  // Temporary storage for outputs that require unit transformations
195  std::unordered_map<ShaderOutput*, UnitTransform> _outputUnitTransformMap;
196 };
197 
198 /// @class ShaderGraphEdge
199 /// An edge returned during shader graph traversal.
201 {
202  public:
204  upstream(up),
205  downstream(down)
206  {
207  }
210 };
211 
212 /// @class ShaderGraphEdgeIterator
213 /// Iterator class for traversing edges between nodes in a shader graph.
215 {
216  public:
219 
220  bool operator==(const ShaderGraphEdgeIterator& rhs) const
221  {
222  return _upstream == rhs._upstream &&
223  _downstream == rhs._downstream &&
224  _stack == rhs._stack;
225  }
226  bool operator!=(const ShaderGraphEdgeIterator& rhs) const
227  {
228  return !(*this == rhs);
229  }
230 
231  /// Dereference this iterator, returning the current output in the traversal.
233  {
234  return ShaderGraphEdge(_upstream, _downstream);
235  }
236 
237  /// Iterate to the next edge in the traversal.
238  /// @throws ExceptionFoundCycle if a cycle is encountered.
239  ShaderGraphEdgeIterator& operator++();
240 
241  /// Return a reference to this iterator to begin traversal
243  {
244  return *this;
245  }
246 
247  /// Return the end iterator.
248  static const ShaderGraphEdgeIterator& end();
249 
250  private:
251  void extendPathUpstream(ShaderOutput* upstream, ShaderInput* downstream);
252  void returnPathDownstream(ShaderOutput* upstream);
253 
254  ShaderOutput* _upstream;
255  ShaderInput* _downstream;
256  using StackFrame = std::pair<ShaderOutput*, size_t>;
257  std::vector<StackFrame> _stack;
258  std::set<ShaderOutput*> _path;
259 };
260 
262 
263 #endif
std::unordered_map< ShaderInput *, UnitTransform > _inputUnitTransformMap
Definition: ShaderGraph.h:190
ShaderGraphEdge operator*() const
Dereference this iterator, returning the current output in the traversal.
Definition: ShaderGraph.h:232
ShaderGraphInputSocket * getInputSocket(size_t index)
Get socket by index.
Definition: ShaderGraph.h:80
friend class ShaderGraph
Definition: ShaderNode.h:511
vector< ShaderInput * > _inputOrder
Definition: ShaderNode.h:503
bool operator==(const ShaderGraphEdgeIterator &rhs) const
Definition: ShaderGraph.h:220
std::unordered_map< string, ShaderNodePtr > _nodeMap
Definition: ShaderGraph.h:183
#define MATERIALX_NAMESPACE_BEGIN
Definition: Generated.h:25
ShaderOutput * getOutput(size_t index=0)
Definition: ShaderNode.h:455
ShaderInput * getInput(size_t index)
Get inputs/outputs by index.
Definition: ShaderNode.h:454
shared_ptr< class UnitSystem > UnitSystemPtr
A shared pointer to a UnitSystem.
Definition: UnitSystem.h:26
vector< ShaderOutput * > _outputOrder
Definition: ShaderNode.h:506
ShaderGraphOutputSocket * getOutputSocket(const string &name)
Definition: ShaderGraph.h:87
shared_ptr< const Node > ConstNodePtr
A shared pointer to a const Node.
Definition: Node.h:26
size_t numOutputs() const
Definition: ShaderNode.h:451
#define MX_GENSHADER_API
Definition: Export.h:18
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:184
bool operator!=(const ShaderGraphEdgeIterator &rhs) const
Definition: ShaderGraph.h:226
ShaderGraphEdgeIterator & begin()
Return a reference to this iterator to begin traversal.
Definition: ShaderGraph.h:242
size_t numInputSockets() const
Get number of input sockets.
Definition: ShaderGraph.h:74
ShaderGraphEdge(ShaderOutput *up, ShaderInput *down)
Definition: ShaderGraph.h:203
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:209
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.
GLuint const GLchar * name
Definition: glcorearb.h:786
shared_ptr< class ShaderGraph > ShaderGraphPtr
A shared pointer to a shader graph.
Definition: ShaderGraph.h:39
GA_API const UT_StringHolder transform
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:193
ShaderOutput * upstream
Definition: ShaderGraph.h:208
bool isAGraph() const override
Return true if this node is a graph.
Definition: ShaderGraph.h:62
IdentifierMap _identifiers
Definition: ShaderGraph.h:185
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:195
shared_ptr< Element > ElementPtr
A shared pointer to an Element.
Definition: Element.h:31
shared_ptr< ValueElement > ValueElementPtr
A shared pointer to a ValueElement.
Definition: Element.h:41
#define MATERIALX_NAMESPACE_END
Definition: Generated.h:26
std::unordered_map< ShaderInput *, ColorSpaceTransform > _inputColorTransformMap
Definition: ShaderGraph.h:188
size_t numInputs() const
Get number of inputs/outputs.
Definition: ShaderNode.h:450
Definition: Syntax.h:39
ConstDocumentPtr _document
Definition: ShaderGraph.h:182
type
Definition: core.h:1059
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:115