Fix #34601: cycles OSL crash when using preview render and viewport render at
[blender.git] / intern / cycles / render / osl.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "device.h"
20
21 #include "graph.h"
22 #include "light.h"
23 #include "osl.h"
24 #include "scene.h"
25 #include "shader.h"
26
27 #ifdef WITH_OSL
28
29 #include "osl_globals.h"
30 #include "osl_services.h"
31 #include "osl_shader.h"
32
33 #include "util_foreach.h"
34 #include "util_md5.h"
35 #include "util_path.h"
36 #include "util_progress.h"
37
38 #endif
39
40 CCL_NAMESPACE_BEGIN
41
42 #ifdef WITH_OSL
43
44 /* Shared Texture System */
45
46 OSL::TextureSystem *OSLShaderManager::ts_shared = NULL;
47 int OSLShaderManager::ts_shared_users = 0;
48 thread_mutex OSLShaderManager::ts_shared_mutex;
49
50 /* Shader Manager */
51
52 OSLShaderManager::OSLShaderManager()
53 {
54         services = new OSLRenderServices();
55
56         texture_system_init();
57         shading_system_init();
58 }
59
60 OSLShaderManager::~OSLShaderManager()
61 {
62         OSL::ShadingSystem::destroy(ss);
63
64         /* shared texture system decrease users and destroy if no longer used */
65         {
66                 thread_scoped_lock lock(ts_shared_mutex);
67                 ts_shared_users--;
68
69                 if(ts_shared_users == 0) {
70                         OSL::TextureSystem::destroy(ts_shared);
71                         ts_shared = NULL;
72                 }
73         }
74
75         delete services;
76 }
77
78 void OSLShaderManager::reset(Scene *scene)
79 {
80         OSL::ShadingSystem::destroy(ss);
81         delete services;
82
83         services = new OSLRenderServices();
84         shading_system_init();
85 }
86
87 void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
88 {
89         if(!need_update)
90                 return;
91
92         device_free(device, dscene, scene);
93
94         /* determine which shaders are in use */
95         device_update_shaders_used(scene);
96
97         /* create shaders */
98         OSLGlobals *og = (OSLGlobals*)device->osl_memory();
99
100         foreach(Shader *shader, scene->shaders) {
101                 assert(shader->graph);
102
103                 if(progress.get_cancel()) return;
104
105                 OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager);
106                 compiler.background = (shader == scene->shaders[scene->default_background]);
107                 compiler.compile(og, shader);
108
109                 if(shader->sample_as_light && shader->has_surface_emission)
110                         scene->light_manager->need_update = true;
111         }
112
113         /* setup shader engine */
114         og->ss = ss;
115         og->ts = ts;
116         og->services = services;
117
118         int background_id = scene->shader_manager->get_shader_id(scene->default_background);
119         og->background_state = og->surface_state[background_id & SHADER_MASK];
120         og->use = true;
121
122         foreach(Shader *shader, scene->shaders)
123                 shader->need_update = false;
124
125         need_update = false;
126         
127         /* set texture system */
128         scene->image_manager->set_osl_texture_system((void*)ts);
129
130         device_update_common(device, dscene, scene, progress);
131 }
132
133 void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
134 {
135         OSLGlobals *og = (OSLGlobals*)device->osl_memory();
136
137         device_free_common(device, dscene, scene);
138
139         /* clear shader engine */
140         og->use = false;
141         og->ss = NULL;
142         og->ts = NULL;
143
144         og->surface_state.clear();
145         og->volume_state.clear();
146         og->displacement_state.clear();
147         og->background_state.reset();
148 }
149
150 void OSLShaderManager::texture_system_init()
151 {
152         /* create texture system, shared between different renders to reduce memory usage */
153         thread_scoped_lock lock(ts_shared_mutex);
154
155         if(ts_shared_users == 0) {
156                 ts_shared = TextureSystem::create(true);
157
158                 ts_shared->attribute("automip",  1);
159                 ts_shared->attribute("autotile", 64);
160                 ts_shared->attribute("gray_to_rgb", 1);
161
162                 /* effectively unlimited for now, until we support proper mipmap lookups */
163                 ts_shared->attribute("max_memory_MB", 16384);
164         }
165
166         ts = ts_shared;
167         ts_shared_users++;
168 }
169
170 void OSLShaderManager::shading_system_init()
171 {
172         ss = OSL::ShadingSystem::create(services, ts, &errhandler);
173         ss->attribute("lockgeom", 1);
174         ss->attribute("commonspace", "world");
175         ss->attribute("optimize", 2);
176         //ss->attribute("debug", 1);
177         //ss->attribute("statistics:level", 1);
178         ss->attribute("searchpath:shader", path_get("shader"));
179
180         /* our own ray types */
181         static const char *raytypes[] = {
182                 "camera",               /* PATH_RAY_CAMERA */
183                 "reflection",   /* PATH_RAY_REFLECT */
184                 "refraction",   /* PATH_RAY_TRANSMIT */
185                 "diffuse",              /* PATH_RAY_DIFFUSE */
186                 "glossy",               /* PATH_RAY_GLOSSY */
187                 "singular",             /* PATH_RAY_SINGULAR */
188                 "transparent",  /* PATH_RAY_TRANSPARENT */
189                 "shadow",               /* PATH_RAY_SHADOW_OPAQUE */
190                 "shadow",               /* PATH_RAY_SHADOW_TRANSPARENT */
191         };
192
193         const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
194         ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
195
196         OSLShader::register_closures((OSLShadingSystem*)ss);
197
198         loaded_shaders.clear();
199 }
200
201 bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
202 {
203         vector<string> options;
204         string stdosl_path;
205
206         /* specify output file name */
207         options.push_back("-o");
208         options.push_back(outputfile);
209
210         /* specify standard include path */
211         options.push_back("-I" + path_get("shader"));
212         stdosl_path = path_get("shader/stdosl.h");
213
214         /* compile */
215         OSL::OSLCompiler *compiler = OSL::OSLCompiler::create();
216         bool ok = compiler->compile(inputfile, options, stdosl_path);
217         delete compiler;
218
219         return ok;
220 }
221
222 bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath)
223 {
224         string searchpath = path_user_get("shaders");
225         return query.open(filepath, searchpath);
226 }
227
228 static string shader_filepath_hash(const string& filepath, uint64_t modified_time)
229 {
230         /* compute a hash from filepath and modified time to detect changes */
231         MD5Hash md5;
232         md5.append((const uint8_t*)filepath.c_str(), filepath.size());
233         md5.append((const uint8_t*)&modified_time, sizeof(modified_time));
234
235         return md5.get_hex();
236 }
237
238 const char *OSLShaderManager::shader_test_loaded(const string& hash)
239 {
240         map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
241         return (it == loaded_shaders.end())? NULL: it->first.c_str();
242 }
243
244 OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string& hash)
245 {
246         map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
247         return (it == loaded_shaders.end())? NULL: &it->second;
248 }
249
250 const char *OSLShaderManager::shader_load_filepath(string filepath)
251 {
252         size_t len = filepath.size();
253         string extension = filepath.substr(len - 4);
254         uint64_t modified_time = path_modified_time(filepath);
255
256         if(extension == ".osl") {
257                 /* .OSL File */
258                 string osopath = filepath.substr(0, len - 4) + ".oso";
259                 uint64_t oso_modified_time = path_modified_time(osopath);
260
261                 /* test if we have loaded the corresponding .OSO already */
262                 if(oso_modified_time != 0) {
263                         const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
264
265                         if(hash)
266                                 return hash;
267                 }
268
269                 /* autocompile .OSL to .OSO if needed */
270                 if(oso_modified_time == 0 || (oso_modified_time < modified_time)) {
271                         OSLShaderManager::osl_compile(filepath, osopath);
272                         modified_time = path_modified_time(osopath);
273                 }
274                 else
275                         modified_time = oso_modified_time;
276
277                 filepath = osopath;
278         }
279         else {
280                 if(extension == ".oso") {
281                         /* .OSO File, nothing to do */
282                 }
283                 else if(path_dirname(filepath) == "") {
284                         /* .OSO File in search path */
285                         filepath = path_join(path_user_get("shaders"), filepath + ".oso");
286                 }
287                 else {
288                         /* unknown file */
289                         return NULL;
290                 }
291
292                 /* test if we have loaded this .OSO already */
293                 const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
294
295                 if(hash)
296                         return hash;
297         }
298
299         /* read oso bytecode from file */
300         string bytecode_hash = shader_filepath_hash(filepath, modified_time);
301         string bytecode;
302
303         if(!path_read_text(filepath, bytecode)) {
304                 fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
305                 OSLShaderInfo info;
306                 loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
307                 return NULL;
308         }
309
310         return shader_load_bytecode(bytecode_hash, bytecode);
311 }
312
313 /* don't try this at home .. this is a template trick to use either
314  * LoadMemoryShader or LoadMemoryCompiledShader which are the function
315  * names in our custom branch and the official repository. */
316
317 template<bool C, typename T = void> struct enable_if { typedef T type; };
318 template<typename T> struct enable_if<false, T> { };
319
320 template<typename T, typename Sign>
321 struct has_LoadMemoryCompiledShader {
322         typedef int yes;
323         typedef char no;
324         
325         template<typename U, U> struct type_check;
326         template<typename _1> static yes &chk(type_check<Sign, &_1::LoadMemoryCompiledShader>*);
327         template<typename   > static no  &chk(...);
328         static bool const value = sizeof(chk<T>(0)) == sizeof(yes);
329 };
330
331 template<typename T>
332 typename enable_if<has_LoadMemoryCompiledShader<T, 
333         bool(T::*)(const char*, const char*)>::value, bool>::type
334 load_memory_shader(T *ss, const char *name, const char *buffer)
335 {
336         return ss->LoadMemoryCompiledShader(name, buffer);
337 }
338
339 template<typename T>
340 typename enable_if<!has_LoadMemoryCompiledShader<T, 
341         bool(T::*)(const char*, const char*)>::value, bool>::type
342 load_memory_shader(T *ss, const char *name, const char *buffer)
343 {
344         return ss->LoadMemoryShader(name, buffer);
345 }
346
347 const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode)
348 {
349         load_memory_shader(ss, hash.c_str(), bytecode.c_str());
350
351         /* this is a bit weak, but works */
352         OSLShaderInfo info;
353         info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
354         info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
355         info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
356         loaded_shaders[hash] = info;
357
358         return loaded_shaders.find(hash)->first.c_str();
359 }
360
361 /* Graph Compiler */
362
363 OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_)
364 {
365         manager = manager_;
366         shadingsys = shadingsys_;
367         image_manager = image_manager_;
368         current_type = SHADER_TYPE_SURFACE;
369         current_shader = NULL;
370         background = false;
371 }
372
373 string OSLCompiler::id(ShaderNode *node)
374 {
375         /* assign layer unique name based on pointer address + bump mode */
376         stringstream stream;
377         stream << "node_" << node->name << "_" << node;
378
379         return stream.str();
380 }
381
382 string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
383 {
384         string sname(input->name);
385         size_t i;
386
387         /* strip whitespace */
388         while((i = sname.find(" ")) != string::npos)
389                 sname.replace(i, 1, "");
390         
391         /* if output exists with the same name, add "In" suffix */
392         foreach(ShaderOutput *output, node->outputs) {
393                 if (strcmp(input->name, output->name)==0) {
394                         sname += "In";
395                         break;
396                 }
397         }
398         
399         return sname;
400 }
401
402 string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
403 {
404         string sname(output->name);
405         size_t i;
406
407         /* strip whitespace */
408         while((i = sname.find(" ")) != string::npos)
409                 sname.replace(i, 1, "");
410         
411         /* if input exists with the same name, add "Out" suffix */
412         foreach(ShaderInput *input, node->inputs) {
413                 if (strcmp(input->name, output->name)==0) {
414                         sname += "Out";
415                         break;
416                 }
417         }
418         
419         return sname;
420 }
421
422 bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
423 {
424         /* exception for output node, only one input is actually used
425          * depending on the current shader type */
426         
427         if(!(input->usage & ShaderInput::USE_OSL))
428                 return true;
429
430         if(node->name == ustring("output")) {
431                 if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE)
432                         return true;
433                 if(strcmp(input->name, "Volume") == 0 && current_type != SHADER_TYPE_VOLUME)
434                         return true;
435                 if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT)
436                         return true;
437                 if(strcmp(input->name, "Normal") == 0)
438                         return true;
439         }
440         else if(node->name == ustring("bump")) {
441                 if(strcmp(input->name, "Height") == 0)
442                         return true;
443         }
444         else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->name == ustring("bump"))
445                 return true;
446
447         return false;
448 }
449
450 void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
451 {
452         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
453
454         /* load filepath */
455         if(isfilepath) {
456                 name = ((OSLShaderManager*)manager)->shader_load_filepath(name);
457
458                 if(name == NULL)
459                         return;
460         }
461
462         /* pass in fixed parameter values */
463         foreach(ShaderInput *input, node->inputs) {
464                 if(!input->link) {
465                         /* checks to untangle graphs */
466                         if(node_skip_input(node, input))
467                                 continue;
468                         /* already has default value assigned */
469                         else if(input->default_value != ShaderInput::NONE)
470                                 continue;
471
472                         string param_name = compatible_name(node, input);
473                         switch(input->type) {
474                                 case SHADER_SOCKET_COLOR:
475                                         parameter_color(param_name.c_str(), input->value);
476                                         break;
477                                 case SHADER_SOCKET_POINT:
478                                         parameter_point(param_name.c_str(), input->value);
479                                         break;
480                                 case SHADER_SOCKET_VECTOR:
481                                         parameter_vector(param_name.c_str(), input->value);
482                                         break;
483                                 case SHADER_SOCKET_NORMAL:
484                                         parameter_normal(param_name.c_str(), input->value);
485                                         break;
486                                 case SHADER_SOCKET_FLOAT:
487                                         parameter(param_name.c_str(), input->value.x);
488                                         break;
489                                 case SHADER_SOCKET_INT:
490                                         parameter(param_name.c_str(), (int)input->value.x);
491                                         break;
492                                 case SHADER_SOCKET_STRING:
493                                         parameter(param_name.c_str(), input->value_string);
494                                         break;
495                                 case SHADER_SOCKET_CLOSURE:
496                                 case SHADER_SOCKET_UNDEFINED:
497                                         break;
498                         }
499                 }
500         }
501
502         /* create shader of the appropriate type. we pass "surface" to all shaders,
503          * because "volume" and "displacement" don't work yet in OSL. the shaders
504          * work fine, but presumably these values would be used for more strict
505          * checking, so when that is fixed, we should update the code here too. */
506         if(current_type == SHADER_TYPE_SURFACE)
507                 ss->Shader("surface", name, id(node).c_str());
508         else if(current_type == SHADER_TYPE_VOLUME)
509                 ss->Shader("surface", name, id(node).c_str());
510         else if(current_type == SHADER_TYPE_DISPLACEMENT)
511                 ss->Shader("surface", name, id(node).c_str());
512         else
513                 assert(0);
514         
515         /* link inputs to other nodes */
516         foreach(ShaderInput *input, node->inputs) {
517                 if(input->link) {
518                         if(node_skip_input(node, input))
519                                 continue;
520
521                         /* connect shaders */
522                         string id_from = id(input->link->parent);
523                         string id_to = id(node);
524                         string param_from = compatible_name(input->link->parent, input->link);
525                         string param_to = compatible_name(node, input);
526
527                         ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
528                 }
529         }
530
531         /* test if we shader contains specific closures */
532         OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name);
533
534         if(info) {
535                 if(info->has_surface_emission)
536                         current_shader->has_surface_emission = true;
537                 if(info->has_surface_transparent)
538                         current_shader->has_surface_transparent = true;
539                 if(info->has_surface_bssrdf)
540                         current_shader->has_surface_bssrdf = true;
541         }
542 }
543
544 void OSLCompiler::parameter(const char *name, float f)
545 {
546         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
547         ss->Parameter(name, TypeDesc::TypeFloat, &f);
548 }
549
550 void OSLCompiler::parameter_color(const char *name, float3 f)
551 {
552         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
553         ss->Parameter(name, TypeDesc::TypeColor, &f);
554 }
555
556 void OSLCompiler::parameter_point(const char *name, float3 f)
557 {
558         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
559         ss->Parameter(name, TypeDesc::TypePoint, &f);
560 }
561
562 void OSLCompiler::parameter_normal(const char *name, float3 f)
563 {
564         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
565         ss->Parameter(name, TypeDesc::TypeNormal, &f);
566 }
567
568 void OSLCompiler::parameter_vector(const char *name, float3 f)
569 {
570         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
571         ss->Parameter(name, TypeDesc::TypeVector, &f);
572 }
573
574 void OSLCompiler::parameter(const char *name, int f)
575 {
576         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
577         ss->Parameter(name, TypeDesc::TypeInt, &f);
578 }
579
580 void OSLCompiler::parameter(const char *name, const char *s)
581 {
582         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
583         ss->Parameter(name, TypeDesc::TypeString, &s);
584 }
585
586 void OSLCompiler::parameter(const char *name, ustring s)
587 {
588         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
589         const char *str = s.c_str();
590         ss->Parameter(name, TypeDesc::TypeString, &str);
591 }
592
593 void OSLCompiler::parameter(const char *name, const Transform& tfm)
594 {
595         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
596         ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&tfm);
597 }
598
599 void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
600 {
601         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
602         TypeDesc type = TypeDesc::TypeFloat;
603         type.arraylen = arraylen;
604         ss->Parameter(name, type, f);
605 }
606
607 void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
608 {
609         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
610         TypeDesc type = TypeDesc::TypeColor;
611         type.arraylen = arraylen;
612         ss->Parameter(name, type, f);
613 }
614
615 void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
616 {
617         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
618         TypeDesc type = TypeDesc::TypeVector;
619         type.arraylen = arraylen;
620         ss->Parameter(name, type, f);
621 }
622
623 void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
624 {
625         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
626         TypeDesc type = TypeDesc::TypeNormal;
627         type.arraylen = arraylen;
628         ss->Parameter(name, type, f);
629 }
630
631 void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
632 {
633         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
634         TypeDesc type = TypeDesc::TypePoint;
635         type.arraylen = arraylen;
636         ss->Parameter(name, type, f);
637 }
638
639 void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
640 {
641         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
642         TypeDesc type = TypeDesc::TypeInt;
643         type.arraylen = arraylen;
644         ss->Parameter(name, type, f);
645 }
646
647 void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
648 {
649         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
650         TypeDesc type = TypeDesc::TypeString;
651         type.arraylen = arraylen;
652         ss->Parameter(name, type, s);
653 }
654
655 void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
656 {
657         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
658         TypeDesc type = TypeDesc::TypeMatrix;
659         type.arraylen = arraylen;
660         ss->Parameter(name, type, (const float *)tfm);
661 }
662
663 void OSLCompiler::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input)
664 {
665         ShaderNode *node = (input->link)? input->link->parent: NULL;
666
667         if(node) {
668                 foreach(ShaderInput *in, node->inputs)
669                         if(!node_skip_input(node, in))
670                                 find_dependencies(dependencies, in);
671
672                 dependencies.insert(node);
673         }
674 }
675
676 void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes)
677 {
678         set<ShaderNode*> done;
679         bool nodes_done;
680
681         do {
682                 nodes_done = true;
683
684                 foreach(ShaderNode *node, nodes) {
685                         if(done.find(node) == done.end()) {
686                                 bool inputs_done = true;
687
688                                 foreach(ShaderInput *input, node->inputs)
689                                         if(!node_skip_input(node, input))
690                                                 if(input->link && done.find(input->link->parent) == done.end())
691                                                         inputs_done = false;
692
693                                 if(inputs_done) {
694                                         node->compile(*this);
695                                         done.insert(node);
696
697                                         if(node->has_surface_emission())
698                                                 current_shader->has_surface_emission = true;
699                                         if(node->has_surface_transparent())
700                                                 current_shader->has_surface_transparent = true;
701                                         if(node->has_surface_bssrdf())
702                                                 current_shader->has_surface_bssrdf = true;
703                                 }
704                                 else
705                                         nodes_done = false;
706                         }
707                 }
708         } while(!nodes_done);
709 }
710
711 void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
712 {
713         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
714
715         current_type = type;
716
717         ss->ShaderGroupBegin();
718
719         ShaderNode *output = graph->output();
720         set<ShaderNode*> dependencies;
721
722         if(type == SHADER_TYPE_SURFACE) {
723                 /* generate surface shader */
724                 find_dependencies(dependencies, output->input("Surface"));
725                 generate_nodes(dependencies);
726                 output->compile(*this);
727         }
728         else if(type == SHADER_TYPE_VOLUME) {
729                 /* generate volume shader */
730                 find_dependencies(dependencies, output->input("Volume"));
731                 generate_nodes(dependencies);
732                 output->compile(*this);
733         }
734         else if(type == SHADER_TYPE_DISPLACEMENT) {
735                 /* generate displacement shader */
736                 find_dependencies(dependencies, output->input("Displacement"));
737                 generate_nodes(dependencies);
738                 output->compile(*this);
739         }
740         else
741                 assert(0);
742
743         ss->ShaderGroupEnd();
744 }
745
746 void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
747 {
748         if(shader->need_update) {
749                 OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
750                 ShaderGraph *graph = shader->graph;
751                 ShaderNode *output = (graph)? graph->output(): NULL;
752
753                 /* copy graph for shader with bump mapping */
754                 if(output->input("Surface")->link && output->input("Displacement")->link)
755                         if(!shader->graph_bump)
756                                 shader->graph_bump = shader->graph->copy();
757
758                 /* finalize */
759                 shader->graph->finalize(false, true);
760                 if(shader->graph_bump)
761                         shader->graph_bump->finalize(true, true);
762
763                 current_shader = shader;
764
765                 shader->has_surface = false;
766                 shader->has_surface_emission = false;
767                 shader->has_surface_transparent = false;
768                 shader->has_surface_bssrdf = false;
769                 shader->has_volume = false;
770                 shader->has_displacement = false;
771
772                 /* generate surface shader */
773                 if(shader->used && graph && output->input("Surface")->link) {
774                         compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
775                         shader->osl_surface_ref = ss->state();
776
777                         if(shader->graph_bump) {
778                                 ss->clear_state();
779                                 compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
780                         }
781
782                         shader->osl_surface_bump_ref = ss->state();
783                         ss->clear_state();
784
785                         shader->has_surface = true;
786                 }
787                 else {
788                         shader->osl_surface_ref = OSL::ShadingAttribStateRef();
789                         shader->osl_surface_bump_ref = OSL::ShadingAttribStateRef();
790                 }
791
792                 /* generate volume shader */
793                 if(shader->used && graph && output->input("Volume")->link) {
794                         compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
795                         shader->has_volume = true;
796
797                         shader->osl_volume_ref = ss->state();
798                         ss->clear_state();
799                 }
800                 else
801                         shader->osl_volume_ref = OSL::ShadingAttribStateRef();
802
803                 /* generate displacement shader */
804                 if(shader->used && graph && output->input("Displacement")->link) {
805                         compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
806                         shader->has_displacement = true;
807                         shader->osl_displacement_ref = ss->state();
808                         ss->clear_state();
809                 }
810                 else
811                         shader->osl_displacement_ref = OSL::ShadingAttribStateRef();
812         }
813
814         /* push state to array for lookup */
815         og->surface_state.push_back(shader->osl_surface_ref);
816         og->surface_state.push_back(shader->osl_surface_bump_ref);
817
818         og->volume_state.push_back(shader->osl_volume_ref);
819         og->volume_state.push_back(shader->osl_volume_ref);
820
821         og->displacement_state.push_back(shader->osl_displacement_ref);
822         og->displacement_state.push_back(shader->osl_displacement_ref);
823 }
824
825 #else
826
827 void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
828 {
829 }
830
831 void OSLCompiler::parameter(const char *name, float f)
832 {
833 }
834
835 void OSLCompiler::parameter_color(const char *name, float3 f)
836 {
837 }
838
839 void OSLCompiler::parameter_vector(const char *name, float3 f)
840 {
841 }
842
843 void OSLCompiler::parameter_point(const char *name, float3 f)
844 {
845 }
846
847 void OSLCompiler::parameter_normal(const char *name, float3 f)
848 {
849 }
850
851 void OSLCompiler::parameter(const char *name, int f)
852 {
853 }
854
855 void OSLCompiler::parameter(const char *name, const char *s)
856 {
857 }
858
859 void OSLCompiler::parameter(const char *name, ustring s)
860 {
861 }
862
863 void OSLCompiler::parameter(const char *name, const Transform& tfm)
864 {
865 }
866
867 void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
868 {
869 }
870
871 void OSLCompiler::parameter_color_array(const char *name, const float f[][3], int arraylen)
872 {
873 }
874
875 void OSLCompiler::parameter_vector_array(const char *name, const float f[][3], int arraylen)
876 {
877 }
878
879 void OSLCompiler::parameter_normal_array(const char *name, const float f[][3], int arraylen)
880 {
881 }
882
883 void OSLCompiler::parameter_point_array(const char *name, const float f[][3], int arraylen)
884 {
885 }
886
887 void OSLCompiler::parameter_array(const char *name, const int f[], int arraylen)
888 {
889 }
890
891 void OSLCompiler::parameter_array(const char *name, const char * const s[], int arraylen)
892 {
893 }
894
895 void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int arraylen)
896 {
897 }
898
899 #endif /* WITH_OSL */
900
901 CCL_NAMESPACE_END
902