d0bd34915df7f1b332d1b7e94a8c37823d5995b6
[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         VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
50
51         if(!need_update)
52                 return;
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 compiler(scene->shader_manager, scene->image_manager);
80                 compiler.background = ((int)i == scene->default_background);
81                 compiler.compile(shader, svm_nodes, i);
82         }
83
84         dscene->svm_nodes.copy((uint4*)&svm_nodes[0], svm_nodes.size());
85         device->tex_alloc("__svm_nodes", dscene->svm_nodes);
86
87         for(i = 0; i < scene->shaders.size(); i++) {
88                 Shader *shader = scene->shaders[i];
89                 shader->need_update = false;
90         }
91
92         device_update_common(device, dscene, scene, progress);
93
94         need_update = false;
95 }
96
97 void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
98 {
99         device_free_common(device, dscene, scene);
100
101         device->tex_free(dscene->svm_nodes);
102         dscene->svm_nodes.clear();
103 }
104
105 /* Graph Compiler */
106
107 SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_)
108 {
109         shader_manager = shader_manager_;
110         image_manager = image_manager_;
111         max_stack_use = 0;
112         current_type = SHADER_TYPE_SURFACE;
113         current_shader = NULL;
114         current_graph = NULL;
115         background = false;
116         mix_weight_offset = SVM_STACK_INVALID;
117         compile_failed = false;
118 }
119
120 int SVMCompiler::stack_size(ShaderSocketType type)
121 {
122         int size = 0;
123         
124         switch (type) {
125                 case SHADER_SOCKET_FLOAT:
126                 case SHADER_SOCKET_INT:
127                         size = 1;
128                         break;
129                 case SHADER_SOCKET_COLOR:
130                 case SHADER_SOCKET_VECTOR:
131                 case SHADER_SOCKET_NORMAL:
132                 case SHADER_SOCKET_POINT:
133                         size = 3;
134                         break;
135                 case SHADER_SOCKET_CLOSURE:
136                         size = 0;
137                         break;
138                 default:
139                         assert(0);
140                         break;
141         }
142         
143         return size;
144 }
145
146 int SVMCompiler::stack_find_offset(ShaderSocketType type)
147 {
148         int size = stack_size(type);
149         int offset = -1;
150         
151         /* find free space in stack & mark as used */
152         for(int i = 0, num_unused = 0; i < SVM_STACK_SIZE; i++) {
153                 if(active_stack.users[i]) num_unused = 0;
154                 else num_unused++;
155
156                 if(num_unused == size) {
157                         offset = i+1 - size;
158                         max_stack_use = max(i+1, max_stack_use);
159
160                         while(i >= offset)
161                                 active_stack.users[i--] = 1;
162
163                         return offset;
164                 }
165         }
166
167         if(!compile_failed) {
168                 compile_failed = true;
169                 fprintf(stderr, "Cycles: out of SVM stack space, shader \"%s\" too big.\n", current_shader->name.c_str());
170         }
171
172         return 0;
173 }
174
175 void SVMCompiler::stack_clear_offset(ShaderSocketType type, int offset)
176 {
177         int size = stack_size(type);
178
179         for(int i = 0; i < size; i++)
180                 active_stack.users[offset + i]--;
181 }
182
183 void SVMCompiler::stack_backup(StackBackup& backup, set<ShaderNode*>& done)
184 {
185         backup.done = done;
186         backup.stack = active_stack;
187
188         foreach(ShaderNode *node, current_graph->nodes) {
189                 foreach(ShaderInput *input, node->inputs)
190                         backup.offsets.push_back(input->stack_offset);
191                 foreach(ShaderOutput *output, node->outputs)
192                         backup.offsets.push_back(output->stack_offset);
193         }
194 }
195
196 void SVMCompiler::stack_restore(StackBackup& backup, set<ShaderNode*>& done)
197 {
198         int i = 0;
199
200         done = backup.done;
201         active_stack = backup.stack;
202
203         foreach(ShaderNode *node, current_graph->nodes) {
204                 foreach(ShaderInput *input, node->inputs)
205                         input->stack_offset = backup.offsets[i++];
206                 foreach(ShaderOutput *output, node->outputs)
207                         output->stack_offset = backup.offsets[i++];
208         }
209 }
210
211 void SVMCompiler::stack_assign(ShaderInput *input)
212 {
213         /* stack offset assign? */
214         if(input->stack_offset == SVM_STACK_INVALID) {
215                 if(input->link) {
216                         /* linked to output -> use output offset */
217                         input->stack_offset = input->link->stack_offset;
218                 }
219                 else {
220                         /* not linked to output -> add nodes to load default value */
221                         input->stack_offset = stack_find_offset(input->type);
222
223                         if(input->type == SHADER_SOCKET_FLOAT) {
224                                 add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset);
225                         }
226                         else if(input->type == SHADER_SOCKET_INT) {
227                                 add_node(NODE_VALUE_F, (int)input->value.x, input->stack_offset);
228                         }
229                         else if(input->type == SHADER_SOCKET_VECTOR ||
230                                 input->type == SHADER_SOCKET_NORMAL ||
231                                 input->type == SHADER_SOCKET_POINT ||
232                                 input->type == SHADER_SOCKET_COLOR)
233                         {
234
235                                 add_node(NODE_VALUE_V, input->stack_offset);
236                                 add_node(NODE_VALUE_V, input->value);
237                         }
238                         else /* should not get called for closure */
239                                 assert(0);
240                 }
241         }
242 }
243
244 void SVMCompiler::stack_assign(ShaderOutput *output)
245 {
246         /* if no stack offset assigned yet, find one */
247         if(output->stack_offset == SVM_STACK_INVALID)
248                 output->stack_offset = stack_find_offset(output->type);
249 }
250
251 void SVMCompiler::stack_link(ShaderInput *input, ShaderOutput *output)
252 {
253         if(output->stack_offset == SVM_STACK_INVALID) {
254                 assert(input->link);
255                 assert(stack_size(output->type) == stack_size(input->link->type));
256
257                 output->stack_offset = input->link->stack_offset;
258
259                 int size = stack_size(output->type);
260
261                 for(int i = 0; i < size; i++)
262                         active_stack.users[output->stack_offset + i]++;
263         }
264 }
265
266 void SVMCompiler::stack_clear_users(ShaderNode *node, set<ShaderNode*>& done)
267 {
268         /* optimization we should add:
269          * find and lower user counts for outputs for which all inputs are done.
270          * this is done before the node is compiled, under the assumption that the
271          * node will first load all inputs from the stack and then writes its
272          * outputs. this used to work, but was disabled because it gave trouble
273          * with inputs getting stack positions assigned */
274
275         foreach(ShaderInput *input, node->inputs) {
276                 ShaderOutput *output = input->link;
277
278                 if(output && output->stack_offset != SVM_STACK_INVALID) {
279                         bool all_done = true;
280
281                         /* optimization we should add: verify if in->parent is actually used */
282                         foreach(ShaderInput *in, output->links)
283                                 if(in->parent != node && done.find(in->parent) == done.end())
284                                         all_done = false;
285
286                         if(all_done) {
287                                 stack_clear_offset(output->type, output->stack_offset);
288                                 output->stack_offset = SVM_STACK_INVALID;
289
290                                 foreach(ShaderInput *in, output->links)
291                                         in->stack_offset = SVM_STACK_INVALID;
292                         }
293                 }
294         }
295 }
296
297 void SVMCompiler::stack_clear_temporary(ShaderNode *node)
298 {
299         foreach(ShaderInput *input, node->inputs) {
300                 if(!input->link && input->stack_offset != SVM_STACK_INVALID) {
301                         stack_clear_offset(input->type, input->stack_offset);
302                         input->stack_offset = SVM_STACK_INVALID;
303                 }
304         }
305 }
306
307 uint SVMCompiler::encode_uchar4(uint x, uint y, uint z, uint w)
308 {
309         assert(x <= 255);
310         assert(y <= 255);
311         assert(z <= 255);
312         assert(w <= 255);
313
314         return (x) | (y << 8) | (z << 16) | (w << 24);
315 }
316
317 void SVMCompiler::add_node(int a, int b, int c, int d)
318 {
319         svm_nodes.push_back(make_int4(a, b, c, d));
320 }
321
322 void SVMCompiler::add_node(NodeType type, int a, int b, int c)
323 {
324         svm_nodes.push_back(make_int4(type, a, b, c));
325 }
326
327 void SVMCompiler::add_node(NodeType type, const float3& f)
328 {
329         svm_nodes.push_back(make_int4(type,
330                 __float_as_int(f.x),
331                 __float_as_int(f.y),
332                 __float_as_int(f.z)));
333 }
334
335 void SVMCompiler::add_node(const float4& f)
336 {
337         svm_nodes.push_back(make_int4(
338                 __float_as_int(f.x),
339                 __float_as_int(f.y),
340                 __float_as_int(f.z),
341                 __float_as_int(f.w)));
342 }
343
344 void SVMCompiler::add_array(float4 *f, int num)
345 {
346         for(int i = 0; i < num; i++)
347                 add_node(f[i]);
348 }
349
350 uint SVMCompiler::attribute(ustring name)
351 {
352         return shader_manager->get_attribute_id(name);
353 }
354
355 uint SVMCompiler::attribute(AttributeStandard std)
356 {
357         return shader_manager->get_attribute_id(std);
358 }
359
360 bool SVMCompiler::node_skip_input(ShaderNode * /*node*/, ShaderInput *input)
361 {
362         /* nasty exception .. */
363         if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump"))
364                 return true;
365         
366         return false;
367 }
368
369 void SVMCompiler::find_dependencies(set<ShaderNode*>& dependencies,
370                                     const set<ShaderNode*>& done,
371                                     ShaderInput *input,
372                                     ShaderNode *skip_node)
373 {
374         ShaderNode *node = (input->link)? input->link->parent: NULL;
375
376         if(node && done.find(node) == done.end() && node != skip_node) {
377                 foreach(ShaderInput *in, node->inputs)
378                         if(!node_skip_input(node, in))
379                                 find_dependencies(dependencies, done, in, skip_node);
380
381                 dependencies.insert(node);
382         }
383 }
384
385 void SVMCompiler::generate_node(ShaderNode *node, set<ShaderNode*>& done)
386 {
387         node->compile(*this);
388         stack_clear_users(node, done);
389         stack_clear_temporary(node);
390
391         if(current_type == SHADER_TYPE_VOLUME) {
392                 if(node->has_spatial_varying())
393                         current_shader->has_heterogeneous_volume = true;
394         }
395
396         if(node->has_object_dependency()) {
397                 current_shader->has_object_dependency = true;
398         }
399 }
400
401 void SVMCompiler::generate_svm_nodes(const set<ShaderNode*>& nodes, set<ShaderNode*>& done)
402 {
403         bool nodes_done;
404
405         do {
406                 nodes_done = true;
407
408                 foreach(ShaderNode *node, nodes) {
409                         if(done.find(node) == done.end()) {
410                                 bool inputs_done = true;
411
412                                 foreach(ShaderInput *input, node->inputs)
413                                         if(!node_skip_input(node, input))
414                                                 if(input->link && done.find(input->link->parent) == done.end())
415                                                         inputs_done = false;
416
417                                 if(inputs_done) {
418                                         generate_node(node, done);
419                                         done.insert(node);
420                                 }
421                                 else
422                                         nodes_done = false;
423                         }
424                 }
425         } while(!nodes_done);
426 }
427
428 void SVMCompiler::generate_closure_node(ShaderNode *node, set<ShaderNode*>& done)
429 {
430         /* execute dependencies for closure */
431         foreach(ShaderInput *in, node->inputs) {
432                 if(!node_skip_input(node, in) && in->link) {
433                         set<ShaderNode*> dependencies;
434                         find_dependencies(dependencies, done, in);
435                         generate_svm_nodes(dependencies, done);
436                 }
437         }
438
439         /* closure mix weight */
440         const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
441         ShaderInput *weight_in = node->input(weight_name);
442
443         if(weight_in && (weight_in->link || weight_in->value.x != 1.0f)) {
444                 stack_assign(weight_in);
445                 mix_weight_offset = weight_in->stack_offset;
446         }
447         else
448                 mix_weight_offset = SVM_STACK_INVALID;
449
450         /* compile closure itself */
451         generate_node(node, done);
452
453         mix_weight_offset = SVM_STACK_INVALID;
454
455         if(current_type == SHADER_TYPE_SURFACE) {
456                 if(node->has_surface_emission())
457                         current_shader->has_surface_emission = true;
458                 if(node->has_surface_transparent())
459                         current_shader->has_surface_transparent = true;
460                 if(node->has_surface_bssrdf()) {
461                         current_shader->has_surface_bssrdf = true;
462                         if(node->has_bssrdf_bump())
463                                 current_shader->has_bssrdf_bump = true;
464                 }
465         }
466 }
467
468 void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
469                                                  ShaderNode *node,
470                                                  set<ShaderNode*>& done,
471                                                  set<ShaderNode*>& closure_done,
472                                                  const set<ShaderNode*>& shared)
473 {
474         if(shared.find(node) != shared.end()) {
475                 generate_multi_closure(root_node, node, done, closure_done);
476         }
477         else {
478                 foreach(ShaderInput *in, node->inputs) {
479                         if(in->type == SHADER_SOCKET_CLOSURE && in->link)
480                                 generated_shared_closure_nodes(root_node, in->link->parent,
481                                                                done, closure_done, shared);
482                 }
483         }
484 }
485
486 void SVMCompiler::generate_multi_closure(ShaderNode *root_node,
487                                          ShaderNode *node,
488                                          set<ShaderNode*>& done,
489                                          set<ShaderNode*>& closure_done)
490 {
491         /* only generate once */
492         if(closure_done.find(node) != closure_done.end())
493                 return;
494
495         closure_done.insert(node);
496
497         if(node->name == ustring("mix_closure") || node->name == ustring("add_closure")) {
498                 /* weighting is already taken care of in ShaderGraph::transform_multi_closure */
499                 ShaderInput *cl1in = node->input("Closure1");
500                 ShaderInput *cl2in = node->input("Closure2");
501                 ShaderInput *facin = node->input("Fac");
502
503                 /* skip empty mix/add closure nodes */
504                 if(!cl1in->link && !cl2in->link)
505                         return;
506
507                 if(facin && facin->link) {
508                         /* mix closure: generate instructions to compute mix weight */
509                         set<ShaderNode*> dependencies;
510                         find_dependencies(dependencies, done, facin);
511                         generate_svm_nodes(dependencies, done);
512
513                         stack_assign(facin);
514
515                         /* execute shared dependencies. this is needed to allow skipping
516                          * of zero weight closures and their dependencies later, so we
517                          * ensure that they only skip dependencies that are unique to them */
518                         set<ShaderNode*> cl1deps, cl2deps, shareddeps;
519
520                         find_dependencies(cl1deps, done, cl1in);
521                         find_dependencies(cl2deps, done, cl2in);
522
523                         set_intersection(cl1deps.begin(), cl1deps.end(),
524                                          cl2deps.begin(), cl2deps.end(),
525                                          std::inserter(shareddeps, shareddeps.begin()));
526
527                         /* it's possible some nodes are not shared between this mix node
528                          * inputs, but still needed to be always executed, this mainly
529                          * happens when a node of current subbranch is used by a parent
530                          * node or so */
531                         if(root_node != node) {
532                                 foreach(ShaderInput *in, root_node->inputs) {
533                                         set<ShaderNode*> rootdeps;
534                                         find_dependencies(rootdeps, done, in, node);
535                                         set_intersection(rootdeps.begin(), rootdeps.end(),
536                                                          cl1deps.begin(), cl1deps.end(),
537                                                          std::inserter(shareddeps, shareddeps.begin()));
538                                         set_intersection(rootdeps.begin(), rootdeps.end(),
539                                                          cl2deps.begin(), cl2deps.end(),
540                                                          std::inserter(shareddeps, shareddeps.begin()));
541                                 }
542                         }
543
544                         if(!shareddeps.empty()) {
545                                 if(cl1in->link) {
546                                         generated_shared_closure_nodes(root_node, cl1in->link->parent,
547                                                                        done, closure_done, shareddeps);
548                                 }
549                                 if(cl2in->link) {
550                                         generated_shared_closure_nodes(root_node, cl2in->link->parent,
551                                                                        done, closure_done, shareddeps);
552                                 }
553
554                                 generate_svm_nodes(shareddeps, done);
555                         }
556
557                         /* generate instructions for input closure 1 */
558                         if(cl1in->link) {
559                                 /* add instruction to skip closure and its dependencies if mix weight is zero */
560                                 svm_nodes.push_back(make_int4(NODE_JUMP_IF_ONE, 0, facin->stack_offset, 0));
561                                 int node_jump_skip_index = svm_nodes.size() - 1;
562
563                                 generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
564
565                                 /* fill in jump instruction location to be after closure */
566                                 svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
567                         }
568
569                         /* generate instructions for input closure 2 */
570                         if(cl2in->link) {
571                                 /* add instruction to skip closure and its dependencies if mix weight is zero */
572                                 svm_nodes.push_back(make_int4(NODE_JUMP_IF_ZERO, 0, facin->stack_offset, 0));
573                                 int node_jump_skip_index = svm_nodes.size() - 1;
574
575                                 generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
576
577                                 /* fill in jump instruction location to be after closure */
578                                 svm_nodes[node_jump_skip_index].y = svm_nodes.size() - node_jump_skip_index - 1;
579                         }
580
581                         /* unassign */
582                         facin->stack_offset = SVM_STACK_INVALID;
583                 }
584                 else {
585                         /* execute closures and their dependencies, no runtime checks
586                          * to skip closures here because was already optimized due to
587                          * fixed weight or add closure that always needs both */
588                         if(cl1in->link)
589                                 generate_multi_closure(root_node, cl1in->link->parent, done, closure_done);
590                         if(cl2in->link)
591                                 generate_multi_closure(root_node, cl2in->link->parent, done, closure_done);
592                 }
593         }
594         else {
595                 generate_closure_node(node, done);
596         }
597
598         done.insert(node);
599 }
600
601
602 void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
603 {
604         /* Converting a shader graph into svm_nodes that can be executed
605          * sequentially on the virtual machine is fairly simple. We can keep
606          * looping over nodes and each time all the inputs of a node are
607          * ready, we add svm_nodes for it that read the inputs from the
608          * stack and write outputs back to the stack.
609          *
610          * With the SVM, we always sample only a single closure. We can think
611          * of all closures nodes as a binary tree with mix closures as inner
612          * nodes and other closures as leafs. The SVM will traverse that tree,
613          * each time deciding to go left or right depending on the mix weights,
614          * until a closure is found.
615          *
616          * We only execute nodes that are needed for the mix weights and chosen
617          * closure.
618          */
619
620         current_type = type;
621         current_graph = graph;
622
623         /* get input in output node */
624         ShaderNode *node = graph->output();
625         ShaderInput *clin = NULL;
626         
627         switch (type) {
628                 case SHADER_TYPE_SURFACE:
629                         clin = node->input("Surface");
630                         break;
631                 case SHADER_TYPE_VOLUME:
632                         clin = node->input("Volume");
633                         break;
634                 case SHADER_TYPE_DISPLACEMENT:
635                         clin = node->input("Displacement");
636                         break;
637                 default:
638                         assert(0);
639                         break;
640         }
641
642         /* clear all compiler state */
643         memset(&active_stack, 0, sizeof(active_stack));
644         svm_nodes.clear();
645
646         foreach(ShaderNode *node_iter, graph->nodes) {
647                 foreach(ShaderInput *input, node_iter->inputs)
648                         input->stack_offset = SVM_STACK_INVALID;
649                 foreach(ShaderOutput *output, node_iter->outputs)
650                         output->stack_offset = SVM_STACK_INVALID;
651         }
652
653         if(shader->used) {
654                 if(clin->link) {
655                         bool generate = false;
656                         
657                         switch (type) {
658                                 case SHADER_TYPE_SURFACE: /* generate surface shader */         
659                                         generate = true;
660                                         shader->has_surface = true;
661                                         break;
662                                 case SHADER_TYPE_VOLUME: /* generate volume shader */
663                                         generate = true;
664                                         shader->has_volume = true;
665                                         break;
666                                 case SHADER_TYPE_DISPLACEMENT: /* generate displacement shader */
667                                         generate = true;
668                                         shader->has_displacement = true;
669                                         break;
670                                 default:
671                                         break;
672                         }
673
674                         if(generate) {
675                                 set<ShaderNode*> done, closure_done;
676                                 generate_multi_closure(clin->link->parent, clin->link->parent,
677                                                        done, closure_done);
678                         }
679                 }
680
681                 /* compile output node */
682                 node->compile(*this);
683         }
684
685         /* if compile failed, generate empty shader */
686         if(compile_failed) {
687                 svm_nodes.clear();
688                 compile_failed = false;
689         }
690
691         add_node(NODE_END, 0, 0, 0);
692 }
693
694 void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int index)
695 {
696         /* copy graph for shader with bump mapping */
697         ShaderNode *node = shader->graph->output();
698
699         if(node->input("Surface")->link && node->input("Displacement")->link)
700                 if(!shader->graph_bump)
701                         shader->graph_bump = shader->graph->copy();
702
703         /* finalize */
704         shader->graph->finalize(false, false);
705         if(shader->graph_bump)
706                 shader->graph_bump->finalize(true, false);
707
708         current_shader = shader;
709
710         shader->has_surface = false;
711         shader->has_surface_emission = false;
712         shader->has_surface_transparent = false;
713         shader->has_surface_bssrdf = false;
714         shader->has_bssrdf_bump = false;
715         shader->has_volume = false;
716         shader->has_displacement = false;
717         shader->has_heterogeneous_volume = false;
718         shader->has_object_dependency = false;
719
720         /* generate surface shader */
721         compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
722         global_svm_nodes[index*2 + 0].y = global_svm_nodes.size();
723         global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
724         global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
725
726         if(shader->graph_bump) {
727                 compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
728                 global_svm_nodes[index*2 + 1].y = global_svm_nodes.size();
729                 global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
730         }
731
732         /* generate volume shader */
733         compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
734         global_svm_nodes[index*2 + 0].z = global_svm_nodes.size();
735         global_svm_nodes[index*2 + 1].z = global_svm_nodes.size();
736         global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
737
738         /* generate displacement shader */
739         compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
740         global_svm_nodes[index*2 + 0].w = global_svm_nodes.size();
741         global_svm_nodes[index*2 + 1].w = global_svm_nodes.size();
742         global_svm_nodes.insert(global_svm_nodes.end(), svm_nodes.begin(), svm_nodes.end());
743 }
744
745 CCL_NAMESPACE_END
746