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