1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __GRAPH_H__
18 #define __GRAPH_H__
19 
20 #include "graph/node.h"
21 #include "graph/node_type.h"
22 
23 #include "kernel/kernel_types.h"
24 
25 #include "util/util_list.h"
26 #include "util/util_map.h"
27 #include "util/util_param.h"
28 #include "util/util_set.h"
29 #include "util/util_types.h"
30 #include "util/util_vector.h"
31 
32 CCL_NAMESPACE_BEGIN
33 
34 class AttributeRequestSet;
35 class Scene;
36 class Shader;
37 class ShaderInput;
38 class ShaderOutput;
39 class ShaderNode;
40 class ShaderGraph;
41 class SVMCompiler;
42 class OSLCompiler;
43 class OutputNode;
44 class ConstantFolder;
45 class MD5Hash;
46 
47 /* Bump
48  *
49  * For bump mapping, a node may be evaluated multiple times, using different
50  * samples to reconstruct the normal, this indicates the sample position */
51 
52 enum ShaderBump { SHADER_BUMP_NONE, SHADER_BUMP_CENTER, SHADER_BUMP_DX, SHADER_BUMP_DY };
53 
54 /* Identifiers for some special node types.
55  *
56  * The graph needs to identify these in the clean function.
57  * Cannot use dynamic_cast, as this is disabled for OSL. */
58 
59 enum ShaderNodeSpecialType {
60   SHADER_SPECIAL_TYPE_NONE,
61   SHADER_SPECIAL_TYPE_PROXY,
62   SHADER_SPECIAL_TYPE_AUTOCONVERT,
63   SHADER_SPECIAL_TYPE_GEOMETRY,
64   SHADER_SPECIAL_TYPE_OSL,
65   SHADER_SPECIAL_TYPE_IMAGE_SLOT,
66   SHADER_SPECIAL_TYPE_CLOSURE,
67   SHADER_SPECIAL_TYPE_COMBINE_CLOSURE,
68   SHADER_SPECIAL_TYPE_OUTPUT,
69   SHADER_SPECIAL_TYPE_BUMP,
70   SHADER_SPECIAL_TYPE_OUTPUT_AOV,
71 };
72 
73 /* Input
74  *
75  * Input socket for a shader node. May be linked to an output or not. If not
76  * linked, it will either get a fixed default value, or e.g. a texture
77  * coordinate. */
78 
79 class ShaderInput {
80  public:
ShaderInput(const SocketType & socket_type_,ShaderNode * parent_)81   ShaderInput(const SocketType &socket_type_, ShaderNode *parent_)
82       : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
83   {
84   }
85 
name()86   ustring name()
87   {
88     return socket_type.ui_name;
89   }
flags()90   int flags()
91   {
92     return socket_type.flags;
93   }
type()94   SocketType::Type type()
95   {
96     return socket_type.type;
97   }
98 
set(float f)99   void set(float f)
100   {
101     ((Node *)parent)->set(socket_type, f);
102   }
set(float3 f)103   void set(float3 f)
104   {
105     ((Node *)parent)->set(socket_type, f);
106   }
107 
108   void disconnect();
109 
110   const SocketType &socket_type;
111   ShaderNode *parent;
112   ShaderOutput *link;
113   int stack_offset; /* for SVM compiler */
114 };
115 
116 /* Output
117  *
118  * Output socket for a shader node. */
119 
120 class ShaderOutput {
121  public:
ShaderOutput(const SocketType & socket_type_,ShaderNode * parent_)122   ShaderOutput(const SocketType &socket_type_, ShaderNode *parent_)
123       : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
124   {
125   }
126 
name()127   ustring name()
128   {
129     return socket_type.ui_name;
130   }
type()131   SocketType::Type type()
132   {
133     return socket_type.type;
134   }
135 
136   void disconnect();
137 
138   const SocketType &socket_type;
139   ShaderNode *parent;
140   vector<ShaderInput *> links;
141   int stack_offset; /* for SVM compiler */
142 };
143 
144 /* Node
145  *
146  * Shader node in graph, with input and output sockets. This is the virtual
147  * base class for all node types. */
148 
149 class ShaderNode : public Node {
150  public:
151   explicit ShaderNode(const NodeType *type);
152   virtual ~ShaderNode();
153 
154   void create_inputs_outputs(const NodeType *type);
155   void remove_input(ShaderInput *input);
156 
157   ShaderInput *input(const char *name);
158   ShaderOutput *output(const char *name);
159   ShaderInput *input(ustring name);
160   ShaderOutput *output(ustring name);
161 
162   virtual ShaderNode *clone(ShaderGraph *graph) const = 0;
163   virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
164   virtual void compile(SVMCompiler &compiler) = 0;
165   virtual void compile(OSLCompiler &compiler) = 0;
166 
167   /* Expand node into additional nodes. */
expand(ShaderGraph *)168   virtual void expand(ShaderGraph * /* graph */)
169   {
170   }
171 
172   /* ** Node optimization ** */
173   /* Check whether the node can be replaced with single constant. */
constant_fold(const ConstantFolder &)174   virtual void constant_fold(const ConstantFolder & /*folder*/)
175   {
176   }
177 
178   /* Simplify settings used by artists to the ones which are simpler to
179    * evaluate in the kernel but keep the final result unchanged.
180    */
simplify_settings(Scene *)181   virtual void simplify_settings(Scene * /*scene*/){};
182 
has_surface_emission()183   virtual bool has_surface_emission()
184   {
185     return false;
186   }
has_surface_transparent()187   virtual bool has_surface_transparent()
188   {
189     return false;
190   }
has_surface_bssrdf()191   virtual bool has_surface_bssrdf()
192   {
193     return false;
194   }
has_bump()195   virtual bool has_bump()
196   {
197     return false;
198   }
has_bssrdf_bump()199   virtual bool has_bssrdf_bump()
200   {
201     return false;
202   }
has_spatial_varying()203   virtual bool has_spatial_varying()
204   {
205     return false;
206   }
has_attribute_dependency()207   virtual bool has_attribute_dependency()
208   {
209     return false;
210   }
has_integrator_dependency()211   virtual bool has_integrator_dependency()
212   {
213     return false;
214   }
has_volume_support()215   virtual bool has_volume_support()
216   {
217     return false;
218   }
has_raytrace()219   virtual bool has_raytrace()
220   {
221     return false;
222   }
223   vector<ShaderInput *> inputs;
224   vector<ShaderOutput *> outputs;
225 
226   int id;          /* index in graph node array */
227   ShaderBump bump; /* for bump mapping utility */
228 
229   ShaderNodeSpecialType special_type; /* special node type */
230 
231   /* ** Selective nodes compilation ** */
232 
233   /* TODO(sergey): More explicitly mention in the function names
234    * that those functions are for selective compilation only?
235    */
236 
237   /* Nodes are split into several groups, group of level 0 contains
238    * nodes which are most commonly used, further levels are extension
239    * of previous one and includes less commonly used nodes.
240    */
get_group()241   virtual int get_group()
242   {
243     return NODE_GROUP_LEVEL_0;
244   }
245 
246   /* Node feature are used to disable huge nodes inside the group,
247    * so it's possible to disable huge nodes inside of the required
248    * nodes group.
249    */
get_feature()250   virtual int get_feature()
251   {
252     return bump == SHADER_BUMP_NONE ? 0 : NODE_FEATURE_BUMP;
253   }
254 
255   /* Get closure ID to which the node compiles into. */
get_closure_type()256   virtual ClosureType get_closure_type()
257   {
258     return CLOSURE_NONE_ID;
259   }
260 
261   /* Check whether settings of the node equals to another one.
262    *
263    * This is mainly used to check whether two nodes can be merged
264    * together. Meaning, runtime stuff like node id and unbound slots
265    * will be ignored for comparison.
266    *
267    * NOTE: If some node can't be de-duplicated for whatever reason it
268    * is to be handled in the subclass.
269    */
270   virtual bool equals(const ShaderNode &other);
271 };
272 
273 /* Node definition utility macros */
274 
275 #define SHADER_NODE_CLASS(type) \
276   NODE_DECLARE \
277   type(); \
278   virtual ShaderNode *clone(ShaderGraph *graph) const \
279   { \
280     return graph->create_node<type>(*this); \
281   } \
282   virtual void compile(SVMCompiler &compiler); \
283   virtual void compile(OSLCompiler &compiler);
284 
285 #define SHADER_NODE_NO_CLONE_CLASS(type) \
286   NODE_DECLARE \
287   type(); \
288   virtual void compile(SVMCompiler &compiler); \
289   virtual void compile(OSLCompiler &compiler);
290 
291 #define SHADER_NODE_BASE_CLASS(type) \
292   virtual ShaderNode *clone(ShaderGraph *graph) const \
293   { \
294     return graph->create_node<type>(*this); \
295   } \
296   virtual void compile(SVMCompiler &compiler); \
297   virtual void compile(OSLCompiler &compiler);
298 
299 class ShaderNodeIDComparator {
300  public:
operator()301   bool operator()(const ShaderNode *n1, const ShaderNode *n2) const
302   {
303     return n1->id < n2->id;
304   }
305 };
306 
307 typedef set<ShaderNode *, ShaderNodeIDComparator> ShaderNodeSet;
308 typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap;
309 
310 /* Graph
311  *
312  * Shader graph of nodes. Also does graph manipulations for default inputs,
313  * bump mapping from displacement, and possibly other things in the future. */
314 
315 class ShaderGraph : public NodeOwner {
316  public:
317   list<ShaderNode *> nodes;
318   size_t num_node_ids;
319   bool finalized;
320   bool simplified;
321   string displacement_hash;
322 
323   ShaderGraph();
324   ~ShaderGraph();
325 
326   ShaderNode *add(ShaderNode *node);
327   OutputNode *output();
328 
329   void connect(ShaderOutput *from, ShaderInput *to);
330   void disconnect(ShaderOutput *from);
331   void disconnect(ShaderInput *to);
332   void relink(ShaderInput *from, ShaderInput *to);
333   void relink(ShaderOutput *from, ShaderOutput *to);
334   void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
335 
336   void remove_proxy_nodes();
337   void compute_displacement_hash();
338   void simplify(Scene *scene);
339   void finalize(Scene *scene,
340                 bool do_bump = false,
341                 bool do_simplify = false,
342                 bool bump_in_object_space = false);
343 
344   int get_num_closures();
345 
346   void dump_graph(const char *filename);
347 
348   /* This function is used to create a node of a specified type instead of
349    * calling 'new', and sets the graph as the owner of the node.
350    */
create_node(Args &&...args)351   template<typename T, typename... Args> T *create_node(Args &&... args)
352   {
353     T *node = new T(args...);
354     node->set_owner(this);
355     return node;
356   }
357 
358   /* This function is used to delete a node created and owned by the graph.
359    */
delete_node(T * node)360   template<typename T> void delete_node(T *node)
361   {
362     assert(node->get_owner() == this);
363     delete node;
364   }
365 
366  protected:
367   typedef pair<ShaderNode *const, ShaderNode *> NodePair;
368 
369   void find_dependencies(ShaderNodeSet &dependencies, ShaderInput *input);
370   void clear_nodes();
371   void copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap);
372 
373   void break_cycles(ShaderNode *node, vector<bool> &visited, vector<bool> &on_stack);
374   void bump_from_displacement(bool use_object_space);
375   void refine_bump_nodes();
376   void expand();
377   void default_inputs(bool do_osl);
378   void transform_multi_closure(ShaderNode *node, ShaderOutput *weight_out, bool volume);
379 
380   /* Graph simplification routines. */
381   void clean(Scene *scene);
382   void constant_fold(Scene *scene);
383   void simplify_settings(Scene *scene);
384   void deduplicate_nodes();
385   void verify_volume_output();
386 };
387 
388 CCL_NAMESPACE_END
389 
390 #endif /* __GRAPH_H__ */
391