Code refactor: reduce special node types, use generic constant folding.
[blender.git] / intern / cycles / render / svm.cpp
1 /*
2  * Copyright 2011-2013 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 #include "device.h"
18 #include "graph.h"
19 #include "light.h"
20 #include "mesh.h"
21 #include "nodes.h"
22 #include "scene.h"
23 #include "shader.h"
24 #include "svm.h"
25
26 #include "util_debug.h"
27 #include "util_logging.h"
28 #include "util_foreach.h"
29 #include "util_progress.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 /* Shader Manager */
34
35 SVMShaderManager::SVMShaderManager()
36 {
37 }
38
39 SVMShaderManager::~SVMShaderManager()
40 {
41 }
42
43 void SVMShaderManager::reset(Scene * /*scene*/)
44 {
45 }
46
47 void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
48 {
49         if(!need_update)
50                 return;
51
52         VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
53
54         /* test if we need to update */
55         device_free(device, dscene, scene);
56
57         /* determine which shaders are in use */
58         device_update_shaders_used(scene);
59
60         /* svm_nodes */
61         vector<int4> svm_nodes;
62         size_t i;
63
64         for(i = 0; i < scene->shaders.size(); i++) {
65                 svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
66                 svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
67         }
68         
69         for(i = 0; i < scene->shaders.size(); i++) {
70                 Shader *shader = scene->shaders[i];
71
72                 if(progress.get_cancel()) return;
73
74                 assert(shader->graph);
75
76                 if(shader->use_mis && shader->has_surface_emission)
77                         scene->light_manager->need_update = true;
78
79                 SVMCompiler::Summary summary;
80                 SVMCompiler compiler(scene->shader_manager, scene->image_manager);
81                 compiler.background = ((int)i == scene->default_background);
82                 compiler.compile(scene, shader, svm_nodes, i, &summary);
83
84                 VLOG(1) << "Compilation summary:\n"
85                         << "Shader name: " << shader->name << "\n"
86                         << summary.full_report();
87         }
88
89         dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size());
90         device->tex_alloc("__svm_nodes", dscene->svm_nodes);
91
92         for(i = 0; i < scene->shaders.size(); i++) {
93                 Shader *shader = scene->shaders[i];
94                 shader->need_update = false;
95         }
96
97         device_update_common(device, dscene, scene, progress);
98
99         need_update = false;
100 }
101
102 void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
103 {
104         device_free_common(device, dscene, scene);
105
106         device->tex_free(dscene->svm_nodes);
107         dscene->svm_nodes.clear();
108 }
109
110 /* Graph Compiler */
111
112 SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_)
113 {
114         shader_manager = shader_manager_;
115         image_manager = image_manager_;
116         max_stack_use = 0;
117         current_type = SHADER_TYPE_SURFACE;
118         current_shader = NULL;
119         current_graph = NULL;
120         background = false;
121         mix_weight_offset = SVM_STACK_INVALID;
122         compile_failed = false;
123 }
124
125 int SVMCompiler::stack_size(ShaderSocketType type)
126 {
127         int size = 0;
128         
129         switch(type) {
130                 case SHADER_SOCKET_FLOAT:
131                 case SHADER_SOCKET_INT:
132                         size = 1;
133                         break;
134                 case SHADER_SOCKET_COLOR:
135                 case SHADER_SOCKET_VECTOR:
136                 case SHADER_SOCKET_NORMAL:
137                 case SHADER_SOCKET_POINT:
138                         size = 3;
139                         break;
140                 case SHADER_SOCKET_CLOSURE:
141                         size = 0;
142                         break;
143                 default:
144                         assert(0);
145                         break;
146         }
147         
148         return size;
149 }
150
151 int SVMCompiler::stack_find_offset(ShaderSocketType type)
152 {
153         int size = stack_size(type);
154         int offset = -1;
155         
156         /* find free space in stack & mark as used */
157         for(int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
158                 if(active_stack.users[i]) num_unused = 0;
159                 else num_unused++;
160
161                 if(num_unused == size) {
162                         offset = i+1 - size;
163                         max_stack_use = max(i+1, max_stack_use);
164
165                         while(i >= offset)
166                                 active_stack.users[i--] = 1;
167
168                         return offset;
169                 }
170         }
171
172         if(!compile_failed) {
173                 compile_failed = true;
174                 fprintf(stderr, "Cycles: out of SVM stack space, shader \"%s\" too big.\n", current_shader->name.c_str());
175         }
176
177         return 0;
178 }
179
180 void SVMCompiler::stack_clear_offset(ShaderSocketType type, int offset)
181 {
182         int size = stack_size(type);
183
184         for(int i = 0; i < size; i++)
185                 active_stack.users[offset + i]--;
186 }
187
188 void SVMCompiler::stack_backup(StackBackup& backup, ShaderNodeSet& done)
189 {
190         backup.done = done;
191         backup.stack = active_stack;
192
193         foreach(ShaderNode *node, current_graph->nodes) {
194                 foreach(ShaderInput *input, node->inputs)
195                         backup.offsets.push_back(input->stack_offset);
196                 foreach(ShaderOutput *output, node->outputs)
197                         backup.offsets.push_back(output->stack_offset);
198         }
199 }
200
201 void SVMCompiler::stack_restore(StackBackup& backup, ShaderNodeSet& done)
202 {
203         int i = 0;
204
205         done = backup.done;
206         active_stack = backup.stack;
207
208         foreach(ShaderNode *node, current_graph->nodes) {
209                 foreach(ShaderInput *input, node->inputs)
210                         input->stack_offset = backup.offsets[i++];
211                 foreach(ShaderOutput *output, node->outputs)
212                         output->stack_offset = backup.offsets[i++];
213         }
214 }
215
216 void SVMCompiler::stack_assign(ShaderInput *input)
217 {
218         /* stack offset assign? */
219         if(input->stack_offset == SVM_STACK_INVALID) {
220                 if(input->link) {
221                         /* linked to output -> use output offset */
222                         input->stack_offset = input->link->stack_offset;
223                 }
224                 else {
225                         /* not linked to output -> add nodes to load default value */
226                         input->stack_offset = stack_find_offset(input->type);
227
228                         if(input->type == SHADER_SOCKET_FLOAT) {
229                                 add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset);
230                         }
231                         else if(input->type == SHADER_SOCKET_INT) {
232                                 add_node(NODE_VALUE_F, (int)input->value.x, input->stack_offset);
233                         }
234                         else if(input->type == SHADER_SOCKET_VECTOR ||
235                                 input->type == SHADER_SOCKET_NORMAL ||
236                                 input->type == SHADER_SOCKET_POINT ||
237                                 input->type == SHADER_SOCKET_COLOR)
238                         {
239
240                                 add_node(NODE_VALUE_V, input->stack_offset);
241                                 add_node(NODE_VALUE_V, input->value);
242                         }
243                         else /* should not get called for closure */
244                                 assert(0);
245                 }
246         }
247 }
248
249 void SVMCompiler::stack_assign(ShaderOutput *output)
250 {
251         /* if no stack offset assigned yet, find one */
252         if(output->stack_offset == SVM_STACK_INVALID)
253                 output->stack_offset = stack_find_offset(output->type);
254 }
255
256 void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
257 {
258         if(output->stack_offset == SVM_STACK_INVALID) {
259                 assert(input->link);
260                 assert(stack_size(output->type) == stack_size(input->link->type));
261
262                 output->stack_offset = input->link->stack_offset;
263
264                 int size = stack_size(output->type);
265
266                 for(int i = 0; i < size; i++)
267                         active_stack.users[output->stack_offset + i]++;
268         }
269 }
270
271 void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
272 {
273         /* optimization we should add:
274          * find and lower user counts for outputs for which all inputs are done.
275          * this is done before the node is compiled, under the assumption that the
276          * node will first load all inputs from the stack and then writes its
277          * outputs. this used to work, but was disabled because it gave trouble
278          * with inputs getting stack positions assigned */
279
280         foreach(ShaderInput *input, node->inputs) {
281                 ShaderOutput *output = input->link;
282
283                 if(output && output->stack_offset != SVM_STACK_INVALID) {
284                         bool all_done = true;
285
286                         /* optimization we should add: verify if in->parent is actually used */
287                         foreach(ShaderInput *in, output->links)
288                                 if(in->parent != node && done.find(in->parent) == done.end())
289                                         all_done = false;
290
291                         if(all_done) {
292                                 stack_clear_offset(output->type, output->stack_offset);
293                                 output->stack_offset = SVM_STACK_INVALID;
294
295                                 foreach(ShaderInput *in, output->links)
296                                         in->stack_offset = SVM_STACK_INVALID;
297                         }
298                 }
299         }
300 }
301
302 void SVMCompiler::stack_clear_temporary(ShaderNode *node)
303 {
304         foreach(ShaderInput *input, node->inputs) {
305                 if(!input->link && input->stack_offset != SVM_STACK_INVALID) {
306                         stack_clear_offset(input->type, input->stack_offset);
307                         input->stack_offset = SVM_STACK_INVALID;
308                 }
309         }
310 }
311
312 uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
313 {
314         assert(x <= 255);
315         assert(y <= 255);
316         assert(z <= 255);
317         assert(w <= 255);
318
319         return (x) | (y << 8) | (z << 16) | (w << 24);
320 }
321
322 void SVMCompiler::add_node(int a, int b, int c, int d)
323 {
324         svm_nodes.push_back(make_int4(a, b, c, d));
325 }
326
327 void SVMCompiler::add_node(NodeType type, int a, int b, int c)
328 {
329         svm_nodes.push_back(make_int4(type, a, b, c));
330 }
331
332 void SVMCompiler::add_node(NodeType type, const float3& f)
333 {
334         svm_nodes.push_back(make_int4(type,
335                 __float_as_int(f.x),
336                 __float_as_int(f.y),
337                 __float_as_int(f.z)));
338 }
339
340 void SVMCompiler::add_node(const float4& f)
341 {
342         svm_nodes.push_back(make_int4(
343                 __float_as_int(f.x),
344                 __float_as_int(f.y),
345                 __float_as_int(f.z),
346                 __float_as_int(f.w)));
347 }
348
349 void SVMCompiler::add_array(float4 *f, int num)
350 {
351         for(int i = 0; i < num; i++)
352                 add_node(f[i]);
353 }
354
355 uint SVMCompiler::attribute(ustring name)
356 {
357         return shader_manager->get_attribute_id(name);
358 }
359
360 uint SVMCompiler::attribute(AttributeStandard std)
361 {
362         return shader_manager->get_attribute_id(std);
363 }
364
365 bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
366 {
367         /* nasty exception .. */
368         if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
369                 return true;
370         
371         return false;
372 }
373
374 void SVMCompiler::find_dependencies(ShaderNodeSet& dependencies,
375                                     const ShaderNodeSet& done,
376                                     ShaderInput *input,
377                                     ShaderNode *skip_node)
378 {
379         ShaderNode *node = (input->link)? input->link->parent: NULL;
380
381         if(node != NULL &&
382            done.find(node) == done.end() &&
383            node != skip_node &&
384            dependencies.find(node) == dependencies.end())
385         {
386                 foreach(ShaderInput *in, node->inputs)
387                         if(!node_skip_input(node, in))
388                                 find_dependencies(dependencies, done, in, skip_node);
389
390                 dependencies.insert(node);
391         }
392 }
393
394 void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet& done)
395 {
396         node->compile(*this);
397         stack_clear_users(node, done);
398         stack_clear_temporary(node);
399
400         if(current_type == SHADER_TYPE_SURFACE) {
401                 if(node->has_spatial_varying())
402                         current_shader->has_surface_spatial_varying = true;
403         }
404         else if(current_type == SHADER_TYPE_VOLUME) {
405                 if(node->has_spatial_varying())
406                         current_shader->has_volume_spatial_varying = true;
407         }
408
409         if(node->has_object_dependency()) {
410                 current_shader->has_object_dependency = true;
411         }
412
413         if(node->has_integrator_dependency()) {
414                 current_shader->has_integrator_dependency = true;
415         }
416 }
417
418 void SVMCompiler::generate_svm_nodes(const ShaderNodeSet& nodes,
419                                      CompilerState *state)
420 {
421         ShaderNodeSet& done = state->nodes_done;
422         vector<bool>& done_flag = state->nodes_done_flag;
423
424         bool nodes_done;
425         do {
426                 nodes_done = true;
427
428                 foreach(ShaderNode *node, nodes) {
429                         if(!done_flag[node->id]) {
430                                 bool inputs_done = true;
431
432                                 foreach(ShaderInput *input, node->inputs)
433                                         if(!node_skip_input(node, input))
434                                                 if(input->link && !done_flag[input->link->parent->id])
435                                                         inputs_done = false;
436
437                                 if(inputs_done) {
438                                         generate_node(node, done);
439                                         done.insert(node);
440                                         done_flag[node->id] = true;
441                                 }
442                                 else
443                                         nodes_done = false;
444                         }
445                 }
446         } while(!nodes_done);
447 }
448
449 void SVMCompiler::generate_closure_node(ShaderNode *node,
450                                         CompilerState *state)
451 {
452         /* execute dependencies for closure */
453         foreach(ShaderInput *in, node->inputs) {
454                 if(!node_skip_input(node, in) && in->link) {
455                         ShaderNodeSet dependencies;
456                         find_dependencies(dependencies, state->nodes_done, in);
457                         generate_svm_nodes(dependencies, state);
458                 }
459         }
460
461         /* closure mix weight */
462         const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
463         ShaderInput *weight_in = node->input(weight_name);
464
465         if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) {
466                 stack_assign(weight_in);
467                 mix_weight_offset = weight_in->stack_offset;
468         }
469         else
470                 mix_weight_offset = SVM_STACK_INVALID;
471
472         /* compile closure itself */
473         generate_node(node, state->nodes_done);
474
475         mix_weight_offset = SVM_STACK_INVALID;
476
477         if(current_type == SHADER_TYPE_SURFACE) {
478                 if(node->has_surface_emission())
479                         current_shader->has_surface_emission = true;
480                 if(node->has_surface_transparent())
481                         current_shader->has_surface_transparent = true;
482                 if(node->has_surface_bssrdf()) {
483                         current_shader->has_surface_bssrdf = true;
484                         if(node->has_bssrdf_bump())
485                                 current_shader->has_bssrdf_bump = true;
486                 }
487         }
488 }
489
490 void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
491                                                  ShaderNode *node,
492                                                  CompilerState *state,
493                                                  const ShaderNodeSet& shared)
494 {
495         if(shared.find(node) != shared.end()) {
496                 generate_multi_closure(root_node, node, state);
497         }
498         else {
499                 foreach(ShaderInput *in, node->inputs) {
500                         if(in->type == SHADER_SOCKET_CLOSURE && in->link)
501                                 generated_shared_closure_nodes(root_node,
502                                                                in->link->parent,
503                                                                state,
504                                                                shared);
505                 }
506         }
507 }
508
509 void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
510                                          ShaderNode *node,
511                                          CompilerState *state)
512 {
513         /* only generate once */
514         if(state->closure_done.find(node) != state->closure_done.end())
515                 return;
516
517         state->closure_done.insert(node);
518
519         if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
520                 /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
521                 ShaderInput *cl1in = node->input("Closure1");
522                 ShaderInput *cl2in = node->input("Closure2");
523                 ShaderInput *facin = node->input("Fac");
524
525                 /* skip empty mix/add closure nodes */
526                 if(!cl1in->link && !cl2in->link)
527                         return;
528
529                 if(facin && facin->link) {
530                         /* mix closure: generate instructions to compute mix weight */
531                         ShaderNodeSet dependencies;
532                         find_dependencies(dependencies, state->nodes_done, facin);
533                         generate_svm_nodes(dependencies, state);
534
535                         stack_assign(facin);
536
537                         /* execute shared dependencies. this is needed to allow skipping
538                          * of zero weight closures and their dependencies later, so we
539                          * ensure that they only skip dependencies that are unique to them */
540                         ShaderNodeSet cl1deps, cl2deps, shareddeps;
541
542                         find_dependencies(cl1deps, state->nodes_done, cl1in);
543                         find_dependencies(cl2deps, state->nodes_done, cl2in);
544
545                         ShaderNodeIDComparator node_id_comp;
546                         set_intersection(cl1deps.begin(), cl1deps.end(),
547                                          cl2deps.begin(), cl2deps.end(),
548                                          std::inserter(shareddeps, shareddeps.begin()),
549                                          node_id_comp);
550
551                         /* it's possible some nodes are not shared between this mix node
552                          * inputs, but still needed to be always executed, this mainly
553                          * happens when a node of current subbranch is used by a parent
554                          * node or so */
555                         if(root_node != node) {
556                                 foreach(ShaderInput *in, root_node->inputs) {
557                                         ShaderNodeSet rootdeps;
558                                         find_dependencies(rootdeps, state->nodes_done, in, node);
559                                         set_intersection(rootdeps.begin(), rootdeps.end(),
560                                                          cl1deps.begin(), cl1deps.end(),
561                                                          std::inserter(shareddeps, shareddeps.begin()),
562                                                          node_id_comp);
563                                         set_intersection(rootdeps.begin(), rootdeps.end(),
564                                                          cl2deps.begin(), cl2deps.end(),
565                                                          std::inserter(shareddeps, shareddeps.begin()),
566                                                          node_id_comp);
567                                 }
568                         }
569
570                         if(!shareddeps.empty()) {
571                                 if(cl1in->link) {
572                                         generated_shared_closure_nodes(root_node,
573                                                                        cl1in->link->parent,
574                                                                        state,
575                                                                        shareddeps);
576                                 }
577                                 if(cl2in->link) {
578                                         generated_shared_closure_nodes(root_node,
579                                                                        cl2in->link->parent,
580                                                                        state,
581                                                                        shareddeps);
582                                 }
583
584                                 generate_svm_nodes(shareddeps, state);
585                         }
586
587                         /* generate instructions for input closure 1 */
588                         if(cl1in->link) {
589                                 /* add instruction to skip closure and its dependencies if mix weight is zero */
590                                 svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, facin->stack_offset, 0));
591                                 int node_jump_skip_index = svm_nodes.size() - 1;
592
593                                 generate_multi_closure(root_node, cl1in->link->parent, state);
594
595                                 /* fill in jump instruction location to be after closure */
596                                 svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
597                         }
598
599                         /* generate instructions for input closure 2 */
600                         if(cl2in->link) {
601                                 /* add instruction to skip closure and its dependencies if mix weight is zero */
602                                 svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
603                                 int node_jump_skip_index = svm_nodes.size() - 1;
604
605                                 generate_multi_closure(root_node, cl2in->link->parent, state);
606
607                                 /* fill in jump instruction location to be after closure */
608                                 svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
609                         }
610
611                         /* unassign */
612                         facin->stack_offset = SVM_STACK_INVALID;
613                 }
614                 else {
615                         /* execute closures and their dependencies, no runtime checks
616                          * to skip closures here because was already optimized due to
617                          * fixed weight or add closure that always needs both */
618                         if(cl1in->link)
619                                 generate_multi_closure(root_node, cl1in->link->parent, state);
620                         if(cl2in->link)
621                                 generate_multi_closure(root_node, cl2in->link->parent, state);
622                 }
623         }
624         else {
625                 generate_closure_node(node, state);
626         }
627
628         state->nodes_done.insert(node);
629         state->nodes_done_flag[node->id] = true;
630 }
631
632
633 void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
634 {
635         /* Converting a shader graph into svm_nodes that can be executed
636          * sequentially on the virtual machine is fairly simple. We can keep
637          * looping over nodes and each time all the inputs of a node are
638          * ready, we add svm_nodes for it that read the inputs from the
639          * stack and write outputs back to the stack.
640          *
641          * With the SVM, we always sample only a single closure. We can think
642          * of all closures nodes as a binary tree with mix closures as inner
643          * nodes and other closures as leafs. The SVM will traverse that tree,
644          * each time deciding to go left or right depending on the mix weights,
645          * until a closure is found.
646          *
647          * We only execute nodes that are needed for the mix weights and chosen
648          * closure.
649          */
650
651         current_type = type;
652         current_graph = graph;
653
654         /* get input in output node */
655         ShaderNode *node = graph->output();
656         ShaderInput *clin = NULL;
657         
658         switch(type) {
659                 case SHADER_TYPE_SURFACE:
660                         clin = node->input("Surface");
661                         break;
662                 case SHADER_TYPE_VOLUME:
663                         clin = node->input("Volume");
664                         break;
665                 case SHADER_TYPE_DISPLACEMENT:
666                         clin = node->input("Displacement");
667                         break;
668                 default:
669                         assert(0);
670                         break;
671         }
672
673         /* clear all compiler state */
674         memset(&active_stack, 0, sizeof(active_stack));
675         svm_nodes.clear();
676
677         foreach(ShaderNode *node_iter, graph->nodes) {
678                 foreach(ShaderInput *input, node_iter->inputs)
679                         input->stack_offset = SVM_STACK_INVALID;
680                 foreach(ShaderOutput *output, node_iter->outputs)
681                         output->stack_offset = SVM_STACK_INVALID;
682         }
683
684         if(shader->used) {
685                 if(clin->link) {
686                         bool generate = false;
687                         
688                         switch(type) {
689                                 case SHADER_TYPE_SURFACE: /* generate surface shader */         
690                                         generate = true;
691                                         shader->has_surface = true;
692                                         break;
693                                 case SHADER_TYPE_VOLUME: /* generate volume shader */
694                                         generate = true;
695                                         shader->has_volume = true;
696                                         break;
697                                 case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
698                                         generate = true;
699                                         shader->has_displacement = true;
700                                         break;
701                                 default:
702                                         break;
703                         }
704
705                         if(generate) {
706                                 CompilerState state(graph);
707                                 generate_multi_closure(clin->link->parent,
708                                                        clin->link->parent,
709                                                        &state);
710                         }
711                 }
712
713                 /* compile output node */
714                 node->compile(*this);
715         }
716
717         /* if compile failed, generate empty shader */
718         if(compile_failed) {
719                 svm_nodes.clear();
720                 compile_failed = false;
721         }
722
723         add_node(NODE_END, 0, 0, 0);
724 }
725
726 void SVMCompiler::compile(Scene *scene,
727                           Shader *shader,
728                           vector<int4>& global_svm_nodes,
729                           int index,
730                           Summary *summary)
731 {
732         /* copy graph for shader with bump mapping */
733         ShaderNode *node = shader->graph->output();
734         int start_num_svm_nodes = global_svm_nodes.size();
735
736         const double time_start = time_dt();
737
738         if(node->input("Surface")->link && node->input("Displacement")->link)
739                 if(!shader->graph_bump)
740                         shader->graph_bump = shader->graph->copy();
741
742         /* finalize */
743         {
744                 scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
745                 shader->graph->finalize(scene,
746                                         false,
747                                         false,
748                                         shader->has_integrator_dependency);
749         }
750
751         if(shader->graph_bump) {
752                 scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
753                 shader->graph_bump->finalize(scene,
754                                              true,
755                                              false,
756                                              shader->has_integrator_dependency);
757         }
758
759         current_shader = shader;
760
761         shader->has_surface = false;
762         shader->has_surface_emission = false;
763         shader->has_surface_transparent = false;
764         shader->has_surface_bssrdf = false;
765         shader->has_bssrdf_bump = false;
766         shader->has_volume = false;
767         shader->has_displacement = false;
768         shader->has_surface_spatial_varying = false;
769         shader->has_volume_spatial_varying = false;
770         shader->has_object_dependency = false;
771         shader->has_integrator_dependency = false;
772
773         /* generate surface shader */
774         {
775                 scoped_timer timer((summary != NULL)? &summary->time_generate_surface: NULL);
776                 compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
777                 global_svm_nodes[index*2 + 0].y = global_svm_nodes.size();
778                 global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
779                 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
780         }
781
782         if(shader->graph_bump) {
783                 scoped_timer timer((summary != NULL)? &summary->time_generate_bump: NULL);
784                 compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
785                 global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
786                 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
787         }
788
789         /* generate volume shader */
790         {
791                 scoped_timer timer((summary != NULL)? &summary->time_generate_volume: NULL);
792                 compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
793                 global_svm_nodes[index*2 + 0].z = global_svm_nodes.size();
794                 global_svm_nodes[index*2 + 1].z = global_svm_nodes.size();
795                 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
796         }
797
798         /* generate displacement shader */
799         {
800                 scoped_timer timer((summary != NULL)? &summary->time_generate_displacement: NULL);
801                 compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
802                 global_svm_nodes[index*2 + 0].w = global_svm_nodes.size();
803                 global_svm_nodes[index*2 + 1].w = global_svm_nodes.size();
804                 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
805         }
806
807         /* Fill in summary information. */
808         if(summary != NULL) {
809                 summary->time_total = time_dt() - time_start;
810                 summary->peak_stack_usage = max_stack_use;
811                 summary->num_svm_nodes = global_svm_nodes.size() - start_num_svm_nodes;
812         }
813 }
814
815 /* Compiler summary implementation. */
816
817 SVMCompiler::Summary::Summary()
818         : num_svm_nodes(0),
819           peak_stack_usage(0),
820           time_finalize(0.0),
821           time_finalize_bump(0.0),
822           time_generate_surface(0.0),
823           time_generate_bump(0.0),
824           time_generate_volume(0.0),
825           time_generate_displacement(0.0),
826           time_total(0.0)
827 {
828 }
829
830 string SVMCompiler::Summary::full_report() const
831 {
832         string report = "";
833         report += string_printf("Number of SVM nodes: %d\n", num_svm_nodes);
834         report += string_printf("Peak stack usage:    %d\n", peak_stack_usage);
835
836         report += string_printf("Time (in seconds):\n");
837         report += string_printf("  Finalize:          %f\n", time_finalize);
838         report += string_printf("  Bump finalize:     %f\n", time_finalize_bump);
839         report += string_printf("Finalize:            %f\n", time_finalize +
840                                                              time_finalize_bump);
841         report += string_printf("  Surface:           %f\n", time_generate_surface);
842         report += string_printf("  Bump:              %f\n", time_generate_bump);
843         report += string_printf("  Volume:            %f\n", time_generate_volume);
844         report += string_printf("  Displacement:      %f\n", time_generate_displacement);
845         report += string_printf("Generate:            %f\n", time_generate_surface +
846                                                              time_generate_bump +
847                                                              time_generate_volume +
848                                                              time_generate_displacement);
849         report += string_printf("Total:               %f\n", time_total);
850
851         return report;
852 }
853
854 /* Global state of the compiler. */
855
856 SVMCompiler::CompilerState::CompilerState(ShaderGraph *graph)
857 {
858         int max_id = 0;
859         foreach(ShaderNode *node, graph->nodes) {
860                 max_id = max(node->id, max_id);
861         }
862         nodes_done_flag.resize(max_id + 1, false);
863 }
864
865 CCL_NAMESPACE_END
866