cmake: adjustments required for lib-upgrade on windows.
[blender.git] / intern / cycles / render / osl.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/device.h"
18
19 #include "render/graph.h"
20 #include "render/light.h"
21 #include "render/osl.h"
22 #include "render/scene.h"
23 #include "render/shader.h"
24 #include "render/nodes.h"
25
26 #ifdef WITH_OSL
27
28 #include "kernel/osl/osl_globals.h"
29 #include "kernel/osl/osl_services.h"
30 #include "kernel/osl/osl_shader.h"
31 #include "OSL/llvm_util.h"
32
33 #include "util/util_foreach.h"
34 #include "util/util_logging.h"
35 #include "util/util_md5.h"
36 #include "util/util_path.h"
37 #include "util/util_progress.h"
38 #include "util/util_projection.h"
39
40 #endif
41
42 CCL_NAMESPACE_BEGIN
43
44 #ifdef WITH_OSL
45
46 /* Shared Texture and Shading System */
47
48 OSL::TextureSystem *OSLShaderManager::ts_shared = NULL;
49 int OSLShaderManager::ts_shared_users = 0;
50 thread_mutex OSLShaderManager::ts_shared_mutex;
51
52 OSL::ShadingSystem *OSLShaderManager::ss_shared = NULL;
53 OSLRenderServices *OSLShaderManager::services_shared = NULL;
54 int OSLShaderManager::ss_shared_users = 0;
55 thread_mutex OSLShaderManager::ss_shared_mutex;
56 thread_mutex OSLShaderManager::ss_mutex;
57
58 /* Shader Manager */
59
60 OSLShaderManager::OSLShaderManager()
61 {
62         texture_system_init();
63         shading_system_init();
64 }
65
66 OSLShaderManager::~OSLShaderManager()
67 {
68         shading_system_free();
69         texture_system_free();
70 #ifdef OSL_HAS_BLENDER_CLEANUP_FIX
71         /* There is a problem with llvm+osl: The order global destructors across
72          * different compilation units run cannot be guaranteed, on windows this means
73          * that the llvm destructors run before the osl destructors, causing a crash
74          * when the process exits. the OSL in svn has a special cleanup hack to
75          * sidestep this behavior */
76         OSL::pvt::LLVM_Util::Cleanup();
77 #endif
78 }
79
80 void OSLShaderManager::reset(Scene * /*scene*/)
81 {
82         shading_system_free();
83         shading_system_init();
84 }
85
86 void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
87 {
88         if(!need_update)
89                 return;
90
91         VLOG(1) << "Total " << scene->shaders.size() << " shaders.";
92
93         device_free(device, dscene, scene);
94
95         /* determine which shaders are in use */
96         device_update_shaders_used(scene);
97
98         /* create shaders */
99         OSLGlobals *og = (OSLGlobals*)device->osl_memory();
100
101         foreach(Shader *shader, scene->shaders) {
102                 assert(shader->graph);
103
104                 if(progress.get_cancel()) return;
105
106                 /* we can only compile one shader at the time as the OSL ShadingSytem
107                  * has a single state, but we put the lock here so different renders can
108                  * compile shaders alternating */
109                 thread_scoped_lock lock(ss_mutex);
110
111                 OSLCompiler compiler((void*)this, (void*)ss,
112                                      scene->image_manager,
113                                      scene->light_manager);
114                 compiler.background = (shader == scene->default_background);
115                 compiler.compile(scene, og, shader);
116
117                 if(shader->use_mis && shader->has_surface_emission)
118                         scene->light_manager->need_update = true;
119         }
120
121         /* setup shader engine */
122         og->ss = ss;
123         og->ts = ts;
124         og->services = services;
125
126         int background_id = scene->shader_manager->get_shader_id(scene->default_background);
127         og->background_state = og->surface_state[background_id & SHADER_MASK];
128         og->use = true;
129
130         foreach(Shader *shader, scene->shaders)
131                 shader->need_update = false;
132
133         need_update = false;
134
135         /* set texture system */
136         scene->image_manager->set_osl_texture_system((void*)ts);
137
138         device_update_common(device, dscene, scene, progress);
139
140         {
141                 /* Perform greedyjit optimization.
142                  *
143                  * This might waste time on optimizing gorups which are never actually
144                  * used, but this prevents OSL from allocating data on TLS at render
145                  * time.
146                  *
147                  * This is much better for us because this way we aren't required to
148                  * stop task scheduler threads to make sure all TLS is clean and don't
149                  * have issues with TLS data free accessing freed memory if task scheduler
150                  * is being freed after the Session is freed.
151                  */
152                 thread_scoped_lock lock(ss_shared_mutex);
153                 ss->optimize_all_groups();
154         }
155 }
156
157 void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene)
158 {
159         OSLGlobals *og = (OSLGlobals*)device->osl_memory();
160
161         device_free_common(device, dscene, scene);
162
163         /* clear shader engine */
164         og->use = false;
165         og->ss = NULL;
166         og->ts = NULL;
167
168         og->surface_state.clear();
169         og->volume_state.clear();
170         og->displacement_state.clear();
171         og->bump_state.clear();
172         og->background_state.reset();
173 }
174
175 void OSLShaderManager::texture_system_init()
176 {
177         /* create texture system, shared between different renders to reduce memory usage */
178         thread_scoped_lock lock(ts_shared_mutex);
179
180         if(ts_shared_users == 0) {
181                 ts_shared = TextureSystem::create(true);
182
183                 ts_shared->attribute("automip",  1);
184                 ts_shared->attribute("autotile", 64);
185                 ts_shared->attribute("gray_to_rgb", 1);
186
187                 /* effectively unlimited for now, until we support proper mipmap lookups */
188                 ts_shared->attribute("max_memory_MB", 16384);
189         }
190
191         ts = ts_shared;
192         ts_shared_users++;
193 }
194
195 void OSLShaderManager::texture_system_free()
196 {
197         /* shared texture system decrease users and destroy if no longer used */
198         thread_scoped_lock lock(ts_shared_mutex);
199         ts_shared_users--;
200
201         if(ts_shared_users == 0) {
202                 ts_shared->invalidate_all(true);
203                 OSL::TextureSystem::destroy(ts_shared);
204                 ts_shared = NULL;
205         }
206
207         ts = NULL;
208 }
209
210 void OSLShaderManager::shading_system_init()
211 {
212         /* create shading system, shared between different renders to reduce memory usage */
213         thread_scoped_lock lock(ss_shared_mutex);
214
215         if(ss_shared_users == 0) {
216                 services_shared = new OSLRenderServices();
217
218                 string shader_path = path_get("shader");
219 #ifdef _WIN32
220                 /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can
221                  * operate with file paths with any character. This requires to use wide
222                  * char functions, but OSL uses old fashioned ANSI functions which means:
223                  *
224                  * - We have to convert our paths to ANSI before passing to OSL
225                  * - OSL can't be used when there's a multi-byte character in the path
226                  *   to the shaders folder.
227                  */
228                 shader_path = string_to_ansi(shader_path);
229 #endif
230
231                 ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler);
232                 ss_shared->attribute("lockgeom", 1);
233                 ss_shared->attribute("commonspace", "world");
234                 ss_shared->attribute("searchpath:shader", shader_path);
235                 ss_shared->attribute("greedyjit", 1);
236
237                 VLOG(1) << "Using shader search path: " << shader_path;
238
239                 /* our own ray types */
240                 static const char *raytypes[] = {
241                         "camera",                       /* PATH_RAY_CAMERA */
242                         "reflection",           /* PATH_RAY_REFLECT */
243                         "refraction",           /* PATH_RAY_TRANSMIT */
244                         "diffuse",                      /* PATH_RAY_DIFFUSE */
245                         "glossy",                       /* PATH_RAY_GLOSSY */
246                         "singular",                     /* PATH_RAY_SINGULAR */
247                         "transparent",          /* PATH_RAY_TRANSPARENT */
248
249                         "shadow",                       /* PATH_RAY_SHADOW_OPAQUE_NON_CATCHER */
250                         "shadow",                       /* PATH_RAY_SHADOW_OPAQUE_CATCHER */
251                         "shadow",                       /* PATH_RAY_SHADOW_TRANSPARENT_NON_CATCHER */
252                         "shadow",                       /* PATH_RAY_SHADOW_TRANSPARENT_CATCHER */
253
254                         "__unused__",
255                         "volume_scatter",       /* PATH_RAY_VOLUME_SCATTER */
256                         "__unused__",
257
258                         "__unused__",
259                         "diffuse_ancestor",     /* PATH_RAY_DIFFUSE_ANCESTOR */
260                         "__unused__",
261                         "__unused__",
262                         "__unused__",
263                         "__unused__",
264                         "__unused__",
265                         "__unused__",
266                         "__unused__",
267                 };
268
269                 const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
270                 ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
271
272                 OSLShader::register_closures((OSLShadingSystem*)ss_shared);
273
274                 loaded_shaders.clear();
275         }
276
277         ss = ss_shared;
278         services = services_shared;
279         ss_shared_users++;
280 }
281
282 void OSLShaderManager::shading_system_free()
283 {
284         /* shared shading system decrease users and destroy if no longer used */
285         thread_scoped_lock lock(ss_shared_mutex);
286         ss_shared_users--;
287
288         if(ss_shared_users == 0) {
289                 delete ss_shared;
290                 ss_shared = NULL;
291
292                 delete services_shared;
293                 services_shared = NULL;
294         }
295
296         ss = NULL;
297         services = NULL;
298 }
299
300 bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
301 {
302         vector<string> options;
303         string stdosl_path;
304         string shader_path = path_get("shader");
305
306         /* specify output file name */
307         options.push_back("-o");
308         options.push_back(outputfile);
309
310         /* specify standard include path */
311         string include_path_arg = string("-I") + shader_path;
312         options.push_back(include_path_arg);
313
314         stdosl_path = path_get("shader/stdosl.h");
315
316         /* compile */
317         OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
318         bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path));
319         delete compiler;
320
321         return ok;
322 }
323
324 bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath)
325 {
326         string searchpath = path_user_get("shaders");
327         return query.open(filepath, searchpath);
328 }
329
330 static string shader_filepath_hash(const string& filepath, uint64_t modified_time)
331 {
332         /* compute a hash from filepath and modified time to detect changes */
333         MD5Hash md5;
334         md5.append((const uint8_t*)filepath.c_str(), filepath.size());
335         md5.append((const uint8_t*)&modified_time, sizeof(modified_time));
336
337         return md5.get_hex();
338 }
339
340 const char *OSLShaderManager::shader_test_loaded(const string& hash)
341 {
342         map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
343         return (it == loaded_shaders.end())? NULL: it->first.c_str();
344 }
345
346 OSLShaderInfo *OSLShaderManager::shader_loaded_info(const string& hash)
347 {
348         map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(hash);
349         return (it == loaded_shaders.end())? NULL: &it->second;
350 }
351
352 const char *OSLShaderManager::shader_load_filepath(string filepath)
353 {
354         size_t len = filepath.size();
355         string extension = filepath.substr(len - 4);
356         uint64_t modified_time = path_modified_time(filepath);
357
358         if(extension == ".osl") {
359                 /* .OSL File */
360                 string osopath = filepath.substr(0, len - 4) + ".oso";
361                 uint64_t oso_modified_time = path_modified_time(osopath);
362
363                 /* test if we have loaded the corresponding .OSO already */
364                 if(oso_modified_time != 0) {
365                         const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
366
367                         if(hash)
368                                 return hash;
369                 }
370
371                 /* autocompile .OSL to .OSO if needed */
372                 if(oso_modified_time == 0 || (oso_modified_time < modified_time)) {
373                         OSLShaderManager::osl_compile(filepath, osopath);
374                         modified_time = path_modified_time(osopath);
375                 }
376                 else
377                         modified_time = oso_modified_time;
378
379                 filepath = osopath;
380         }
381         else {
382                 if(extension == ".oso") {
383                         /* .OSO File, nothing to do */
384                 }
385                 else if(path_dirname(filepath) == "") {
386                         /* .OSO File in search path */
387                         filepath = path_join(path_user_get("shaders"), filepath + ".oso");
388                 }
389                 else {
390                         /* unknown file */
391                         return NULL;
392                 }
393
394                 /* test if we have loaded this .OSO already */
395                 const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
396
397                 if(hash)
398                         return hash;
399         }
400
401         /* read oso bytecode from file */
402         string bytecode_hash = shader_filepath_hash(filepath, modified_time);
403         string bytecode;
404
405         if(!path_read_text(filepath, bytecode)) {
406                 fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
407                 OSLShaderInfo info;
408                 loaded_shaders[bytecode_hash] = info; /* to avoid repeat tries */
409                 return NULL;
410         }
411
412         return shader_load_bytecode(bytecode_hash, bytecode);
413 }
414
415 const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode)
416 {
417         ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
418
419         OSLShaderInfo info;
420
421         if(!info.query.open_bytecode(bytecode)) {
422                 fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str());
423         }
424
425         /* this is a bit weak, but works */
426         info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos);
427         info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos);
428         info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos);
429
430         loaded_shaders[hash] = info;
431
432         return loaded_shaders.find(hash)->first.c_str();
433 }
434
435 OSLNode *OSLShaderManager::osl_node(const std::string& filepath,
436                                     const std::string& bytecode_hash,
437                                     const std::string& bytecode)
438 {
439         /* create query */
440         const char *hash;
441
442         if(!filepath.empty()) {
443                 hash = shader_load_filepath(filepath);
444         }
445         else {
446                 hash = shader_test_loaded(bytecode_hash);
447                 if(!hash)
448                         hash = shader_load_bytecode(bytecode_hash, bytecode);
449         }
450
451         if(!hash) {
452                 return NULL;
453         }
454
455         OSLShaderInfo *info = shader_loaded_info(hash);
456
457         /* count number of inputs */
458         size_t num_inputs = 0;
459
460         for(int i = 0; i < info->query.nparams(); i++) {
461                 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
462
463                 /* skip unsupported types */
464                 if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
465                         continue;
466
467                 if(!param->isoutput)
468                         num_inputs++;
469         }
470
471         /* create node */
472         OSLNode *node = OSLNode::create(num_inputs);
473
474         /* add new sockets from parameters */
475         set<void*> used_sockets;
476
477         for(int i = 0; i < info->query.nparams(); i++) {
478                 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
479
480                 /* skip unsupported types */
481                 if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
482                         continue;
483
484                 SocketType::Type socket_type;
485
486                 if(param->isclosure) {
487                         socket_type = SocketType::CLOSURE;
488                 }
489                 else if(param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
490                         if(param->type.vecsemantics == TypeDesc::COLOR)
491                                 socket_type = SocketType::COLOR;
492                         else if(param->type.vecsemantics == TypeDesc::POINT)
493                                 socket_type = SocketType::POINT;
494                         else if(param->type.vecsemantics == TypeDesc::VECTOR)
495                                 socket_type = SocketType::VECTOR;
496                         else if(param->type.vecsemantics == TypeDesc::NORMAL)
497                                 socket_type = SocketType::NORMAL;
498                         else
499                                 continue;
500
501                         if(!param->isoutput && param->validdefault) {
502                                 float3 *default_value = (float3*)node->input_default_value();
503                                 default_value->x = param->fdefault[0];
504                                 default_value->y = param->fdefault[1];
505                                 default_value->z = param->fdefault[2];
506                         }
507                 }
508                 else if(param->type.aggregate == TypeDesc::SCALAR) {
509                         if(param->type.basetype == TypeDesc::INT) {
510                                 socket_type = SocketType::INT;
511
512                                 if(!param->isoutput && param->validdefault) {
513                                         *(int*)node->input_default_value() = param->idefault[0];
514                                 }
515                         }
516                         else if(param->type.basetype == TypeDesc::FLOAT) {
517                                 socket_type = SocketType::FLOAT;
518
519                                 if(!param->isoutput && param->validdefault) {
520                                         *(float*)node->input_default_value() = param->fdefault[0];
521                                 }
522                         }
523                         else if(param->type.basetype == TypeDesc::STRING) {
524                                 socket_type = SocketType::STRING;
525
526                                 if(!param->isoutput && param->validdefault) {
527                                         *(ustring*)node->input_default_value() = param->sdefault[0];
528                                 }
529                         }
530                         else
531                                 continue;
532                 }
533                 else
534                         continue;
535
536                 if(param->isoutput) {
537                         node->add_output(param->name, socket_type);
538                 }
539                 else {
540                         node->add_input(param->name, socket_type);
541                 }
542         }
543
544         /* set bytcode hash or filepath */
545         if(!bytecode_hash.empty()) {
546                 node->bytecode_hash = bytecode_hash;
547         }
548         else {
549                 node->filepath = filepath;
550         }
551
552         /* Generate inputs and outputs */
553         node->create_inputs_outputs(node->type);
554
555         return node;
556 }
557
558 /* Graph Compiler */
559
560 OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_,
561                          ImageManager *image_manager_,
562                          LightManager *light_manager_)
563 {
564         manager = manager_;
565         shadingsys = shadingsys_;
566         image_manager = image_manager_;
567         light_manager = light_manager_;
568         current_type = SHADER_TYPE_SURFACE;
569         current_shader = NULL;
570         background = false;
571 }
572
573 string OSLCompiler::id(ShaderNode *node)
574 {
575         /* assign layer unique name based on pointer address + bump mode */
576         stringstream stream;
577         stream << "node_" << node->type->name << "_" << node;
578
579         return stream.str();
580 }
581
582 string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
583 {
584         string sname(input->name().string());
585         size_t i;
586
587         /* strip whitespace */
588         while((i = sname.find(" ")) != string::npos)
589                 sname.replace(i, 1, "");
590
591         /* if output exists with the same name, add "In" suffix */
592         foreach(ShaderOutput *output, node->outputs) {
593                 if(input->name() == output->name()) {
594                         sname += "In";
595                         break;
596                 }
597         }
598
599         return sname;
600 }
601
602 string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
603 {
604         string sname(output->name().string());
605         size_t i;
606
607         /* strip whitespace */
608         while((i = sname.find(" ")) != string::npos)
609                 sname.replace(i, 1, "");
610
611         /* if input exists with the same name, add "Out" suffix */
612         foreach(ShaderInput *input, node->inputs) {
613                 if(input->name() == output->name()) {
614                         sname += "Out";
615                         break;
616                 }
617         }
618
619         return sname;
620 }
621
622 bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
623 {
624         /* exception for output node, only one input is actually used
625          * depending on the current shader type */
626
627         if(input->flags() & SocketType::SVM_INTERNAL)
628                 return true;
629
630         if(node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
631                 if(input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
632                         return true;
633                 if(input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
634                         return true;
635                 if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
636                         return true;
637                 if(input->name() == "Normal" && current_type != SHADER_TYPE_BUMP)
638                         return true;
639         }
640         else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
641                 if(input->name() == "Height")
642                         return true;
643         }
644         else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
645                 return true;
646
647         return false;
648 }
649
650 void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
651 {
652         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
653
654         /* load filepath */
655         if(isfilepath) {
656                 name = ((OSLShaderManager*)manager)->shader_load_filepath(name);
657
658                 if(name == NULL)
659                         return;
660         }
661
662         /* pass in fixed parameter values */
663         foreach(ShaderInput *input, node->inputs) {
664                 if(!input->link) {
665                         /* checks to untangle graphs */
666                         if(node_skip_input(node, input))
667                                 continue;
668                         /* already has default value assigned */
669                         else if(input->flags() & SocketType::DEFAULT_LINK_MASK)
670                                 continue;
671
672                         string param_name = compatible_name(node, input);
673                         const SocketType& socket = input->socket_type;
674                         switch(input->type()) {
675                                 case SocketType::COLOR:
676                                         parameter_color(param_name.c_str(), node->get_float3(socket));
677                                         break;
678                                 case SocketType::POINT:
679                                         parameter_point(param_name.c_str(), node->get_float3(socket));
680                                         break;
681                                 case SocketType::VECTOR:
682                                         parameter_vector(param_name.c_str(), node->get_float3(socket));
683                                         break;
684                                 case SocketType::NORMAL:
685                                         parameter_normal(param_name.c_str(), node->get_float3(socket));
686                                         break;
687                                 case SocketType::FLOAT:
688                                         parameter(param_name.c_str(), node->get_float(socket));
689                                         break;
690                                 case SocketType::INT:
691                                         parameter(param_name.c_str(), node->get_int(socket));
692                                         break;
693                                 case SocketType::STRING:
694                                         parameter(param_name.c_str(), node->get_string(socket));
695                                         break;
696                                 case SocketType::CLOSURE:
697                                 case SocketType::UNDEFINED:
698                                 default:
699                                         break;
700                         }
701                 }
702         }
703
704         /* create shader of the appropriate type. OSL only distinguishes between "surface"
705          * and "displacement" atm */
706         if(current_type == SHADER_TYPE_SURFACE)
707                 ss->Shader("surface", name, id(node).c_str());
708         else if(current_type == SHADER_TYPE_VOLUME)
709                 ss->Shader("surface", name, id(node).c_str());
710         else if(current_type == SHADER_TYPE_DISPLACEMENT)
711                 ss->Shader("displacement", name, id(node).c_str());
712         else if(current_type == SHADER_TYPE_BUMP)
713                 ss->Shader("displacement", name, id(node).c_str());
714         else
715                 assert(0);
716
717         /* link inputs to other nodes */
718         foreach(ShaderInput *input, node->inputs) {
719                 if(input->link) {
720                         if(node_skip_input(node, input))
721                                 continue;
722
723                         /* connect shaders */
724                         string id_from = id(input->link->parent);
725                         string id_to = id(node);
726                         string param_from = compatible_name(input->link->parent, input->link);
727                         string param_to = compatible_name(node, input);
728
729                         ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
730                 }
731         }
732
733         /* test if we shader contains specific closures */
734         OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name);
735
736         if(current_type == SHADER_TYPE_SURFACE) {
737                 if(info) {
738                         if(info->has_surface_emission)
739                                 current_shader->has_surface_emission = true;
740                         if(info->has_surface_transparent)
741                                 current_shader->has_surface_transparent = true;
742                         if(info->has_surface_bssrdf) {
743                                 current_shader->has_surface_bssrdf = true;
744                                 current_shader->has_bssrdf_bump = true; /* can't detect yet */
745                         }
746                         current_shader->has_bump = true; /* can't detect yet */
747                 }
748
749                 if(node->has_spatial_varying()) {
750                         current_shader->has_surface_spatial_varying = true;
751                 }
752         }
753         else if(current_type == SHADER_TYPE_VOLUME) {
754                 if(node->has_spatial_varying())
755                         current_shader->has_volume_spatial_varying = true;
756         }
757
758         if(node->has_object_dependency()) {
759                 current_shader->has_object_dependency = true;
760         }
761
762         if(node->has_attribute_dependency()) {
763                 current_shader->has_attribute_dependency = true;
764         }
765
766         if(node->has_integrator_dependency()) {
767                 current_shader->has_integrator_dependency = true;
768         }
769 }
770
771 static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength)
772 {
773         return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
774                         (TypeDesc::AGGREGATE)typedesc.aggregate,
775                         (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
776                         arraylength);
777 }
778
779 void OSLCompiler::parameter(ShaderNode* node, const char *name)
780 {
781         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
782         ustring uname = ustring(name);
783         const SocketType& socket = *(node->type->find_input(uname));
784
785         switch(socket.type)
786         {
787                 case SocketType::BOOLEAN:
788                 {
789                         int value = node->get_bool(socket);
790                         ss->Parameter(name, TypeDesc::TypeInt, &value);
791                         break;
792                 }
793                 case SocketType::FLOAT:
794                 {
795                         float value = node->get_float(socket);
796                         ss->Parameter(uname, TypeDesc::TypeFloat, &value);
797                         break;
798                 }
799                 case SocketType::INT:
800                 {
801                         int value = node->get_int(socket);
802                         ss->Parameter(uname, TypeDesc::TypeInt, &value);
803                         break;
804                 }
805                 case SocketType::COLOR:
806                 {
807                         float3 value = node->get_float3(socket);
808                         ss->Parameter(uname, TypeDesc::TypeColor, &value);
809                         break;
810                 }
811                 case SocketType::VECTOR:
812                 {
813                         float3 value = node->get_float3(socket);
814                         ss->Parameter(uname, TypeDesc::TypeVector, &value);
815                         break;
816                 }
817                 case SocketType::POINT:
818                 {
819                         float3 value = node->get_float3(socket);
820                         ss->Parameter(uname, TypeDesc::TypePoint, &value);
821                         break;
822                 }
823                 case SocketType::NORMAL:
824                 {
825                         float3 value = node->get_float3(socket);
826                         ss->Parameter(uname, TypeDesc::TypeNormal, &value);
827                         break;
828                 }
829                 case SocketType::POINT2:
830                 {
831                         float2 value = node->get_float2(socket);
832                         ss->Parameter(uname, TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
833                         break;
834                 }
835                 case SocketType::STRING:
836                 {
837                         ustring value = node->get_string(socket);
838                         ss->Parameter(uname, TypeDesc::TypeString, &value);
839                         break;
840                 }
841                 case SocketType::ENUM:
842                 {
843                         ustring value = node->get_string(socket);
844                         ss->Parameter(uname, TypeDesc::TypeString, &value);
845                         break;
846                 }
847                 case SocketType::TRANSFORM:
848                 {
849                         Transform value = node->get_transform(socket);
850                         ProjectionTransform projection(value);
851                         projection = projection_transpose(projection);
852                         ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
853                         break;
854                 }
855                 case SocketType::BOOLEAN_ARRAY:
856                 {
857                         // OSL does not support booleans, so convert to int
858                         const array<bool>& value = node->get_bool_array(socket);
859                         array<int> intvalue(value.size());
860                         for(size_t i = 0; i < value.size(); i++)
861                                 intvalue[i] = value[i];
862                         ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), intvalue.data());
863                         break;
864                 }
865                 case SocketType::FLOAT_ARRAY:
866                 {
867                         const array<float>& value = node->get_float_array(socket);
868                         ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.size()), value.data());
869                         break;
870                 }
871                 case SocketType::INT_ARRAY:
872                 {
873                         const array<int>& value = node->get_int_array(socket);
874                         ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.size()), value.data());
875                         break;
876                 }
877                 case SocketType::COLOR_ARRAY:
878                 case SocketType::VECTOR_ARRAY:
879                 case SocketType::POINT_ARRAY:
880                 case SocketType::NORMAL_ARRAY:
881                 {
882                         TypeDesc typedesc;
883
884                         switch(socket.type)
885                         {
886                                 case SocketType::COLOR_ARRAY: typedesc = TypeDesc::TypeColor; break;
887                                 case SocketType::VECTOR_ARRAY: typedesc = TypeDesc::TypeVector; break;
888                                 case SocketType::POINT_ARRAY: typedesc = TypeDesc::TypePoint; break;
889                                 case SocketType::NORMAL_ARRAY: typedesc = TypeDesc::TypeNormal; break;
890                                 default: assert(0); break;
891                         }
892
893                         // convert to tightly packed array since float3 has padding
894                         const array<float3>& value = node->get_float3_array(socket);
895                         array<float> fvalue(value.size() * 3);
896                         for(size_t i = 0, j = 0; i < value.size(); i++) {
897                                 fvalue[j++] = value[i].x;
898                                 fvalue[j++] = value[i].y;
899                                 fvalue[j++] = value[i].z;
900                         }
901
902                         ss->Parameter(uname, array_typedesc(typedesc, value.size()), fvalue.data());
903                         break;
904                 }
905                 case SocketType::POINT2_ARRAY:
906                 {
907                         const array<float2>& value = node->get_float2_array(socket);
908                         ss->Parameter(uname, array_typedesc(TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.size()), value.data());
909                         break;
910                 }
911                 case SocketType::STRING_ARRAY:
912                 {
913                         const array<ustring>& value = node->get_string_array(socket);
914                         ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.size()), value.data());
915                         break;
916                 }
917                 case SocketType::TRANSFORM_ARRAY:
918                 {
919                         const array<Transform>& value = node->get_transform_array(socket);
920                         array<ProjectionTransform> fvalue(value.size());
921                         for(size_t i = 0; i < value.size(); i++) {
922                                 fvalue[i] = projection_transpose(ProjectionTransform(value[i]));
923                         }
924                         ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
925                         break;
926                 }
927                 case SocketType::CLOSURE:
928                 case SocketType::NODE:
929                 case SocketType::NODE_ARRAY:
930                 case SocketType::UNDEFINED:
931                 case SocketType::UINT:
932                 {
933                         assert(0);
934                         break;
935                 }
936         }
937 }
938
939 void OSLCompiler::parameter(const char *name, float f)
940 {
941         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
942         ss->Parameter(name, TypeDesc::TypeFloat, &f);
943 }
944
945 void OSLCompiler::parameter_color(const char *name, float3 f)
946 {
947         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
948         ss->Parameter(name, TypeDesc::TypeColor, &f);
949 }
950
951 void OSLCompiler::parameter_point(const char *name, float3 f)
952 {
953         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
954         ss->Parameter(name, TypeDesc::TypePoint, &f);
955 }
956
957 void OSLCompiler::parameter_normal(const char *name, float3 f)
958 {
959         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
960         ss->Parameter(name, TypeDesc::TypeNormal, &f);
961 }
962
963 void OSLCompiler::parameter_vector(const char *name, float3 f)
964 {
965         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
966         ss->Parameter(name, TypeDesc::TypeVector, &f);
967 }
968
969 void OSLCompiler::parameter(const char *name, int f)
970 {
971         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
972         ss->Parameter(name, TypeDesc::TypeInt, &f);
973 }
974
975 void OSLCompiler::parameter(const char *name, const char *s)
976 {
977         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
978         ss->Parameter(name, TypeDesc::TypeString, &s);
979 }
980
981 void OSLCompiler::parameter(const char *name, ustring s)
982 {
983         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
984         const char *str = s.c_str();
985         ss->Parameter(name, TypeDesc::TypeString, &str);
986 }
987
988 void OSLCompiler::parameter(const char *name, const Transform& tfm)
989 {
990         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
991         ProjectionTransform projection(tfm);
992         projection = projection_transpose(projection);
993         ss->Parameter(name, TypeDesc::TypeMatrix, (float*)&projection);
994 }
995
996 void OSLCompiler::parameter_array(const char *name, const float f[], int arraylen)
997 {
998         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
999         TypeDesc type = TypeDesc::TypeFloat;
1000         type.arraylen = arraylen;
1001         ss->Parameter(name, type, f);
1002 }
1003
1004 void OSLCompiler::parameter_color_array(const char *name, const array<float3>& f)
1005 {
1006         /* NB: cycles float3 type is actually 4 floats! need to use an explicit array */
1007         array<float[3]> table(f.size());
1008
1009         for(int i = 0; i < f.size(); ++i) {
1010                 table[i][0] = f[i].x;
1011                 table[i][1] = f[i].y;
1012                 table[i][2] = f[i].z;
1013         }
1014
1015         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
1016         TypeDesc type = TypeDesc::TypeColor;
1017         type.arraylen = table.size();
1018         ss->Parameter(name, type, table.data());
1019 }
1020
1021 void OSLCompiler::parameter_attribute(const char *name, ustring s)
1022 {
1023         if(Attribute::name_standard(s.c_str()))
1024                 parameter(name, (string("geom:") + s.c_str()).c_str());
1025         else
1026                 parameter(name, s.c_str());
1027 }
1028
1029 void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input)
1030 {
1031         ShaderNode *node = (input->link)? input->link->parent: NULL;
1032
1033         if(node != NULL && dependencies.find(node) == dependencies.end()) {
1034                 foreach(ShaderInput *in, node->inputs)
1035                         if(!node_skip_input(node, in))
1036                                 find_dependencies(dependencies, in);
1037
1038                 dependencies.insert(node);
1039         }
1040 }
1041
1042 void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes)
1043 {
1044         ShaderNodeSet done;
1045         bool nodes_done;
1046
1047         do {
1048                 nodes_done = true;
1049
1050                 foreach(ShaderNode *node, nodes) {
1051                         if(done.find(node) == done.end()) {
1052                                 bool inputs_done = true;
1053
1054                                 foreach(ShaderInput *input, node->inputs)
1055                                         if(!node_skip_input(node, input))
1056                                                 if(input->link && done.find(input->link->parent) == done.end())
1057                                                         inputs_done = false;
1058
1059                                 if(inputs_done) {
1060                                         node->compile(*this);
1061                                         done.insert(node);
1062
1063                                         if(current_type == SHADER_TYPE_SURFACE) {
1064                                                 if(node->has_surface_emission())
1065                                                         current_shader->has_surface_emission = true;
1066                                                 if(node->has_surface_transparent())
1067                                                         current_shader->has_surface_transparent = true;
1068                                                 if(node->has_spatial_varying())
1069                                                         current_shader->has_surface_spatial_varying = true;
1070                                                 if(node->has_surface_bssrdf()) {
1071                                                         current_shader->has_surface_bssrdf = true;
1072                                                         if(node->has_bssrdf_bump())
1073                                                                 current_shader->has_bssrdf_bump = true;
1074                                                 }
1075                                                 if(node->has_bump()) {
1076                                                         current_shader->has_bump = true;
1077                                                 }
1078                                         }
1079                                         else if(current_type == SHADER_TYPE_VOLUME) {
1080                                                 if(node->has_spatial_varying())
1081                                                         current_shader->has_volume_spatial_varying = true;
1082                                         }
1083                                 }
1084                                 else
1085                                         nodes_done = false;
1086                         }
1087                 }
1088         } while(!nodes_done);
1089 }
1090
1091 OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type)
1092 {
1093         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
1094
1095         current_type = type;
1096
1097         OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str());
1098
1099         ShaderNode *output = graph->output();
1100         ShaderNodeSet dependencies;
1101
1102         if(type == SHADER_TYPE_SURFACE) {
1103                 /* generate surface shader */
1104                 find_dependencies(dependencies, output->input("Surface"));
1105                 generate_nodes(dependencies);
1106                 output->compile(*this);
1107         }
1108         else if(type == SHADER_TYPE_BUMP) {
1109                 /* generate bump shader */
1110                 find_dependencies(dependencies, output->input("Normal"));
1111                 generate_nodes(dependencies);
1112                 output->compile(*this);
1113         }
1114         else if(type == SHADER_TYPE_VOLUME) {
1115                 /* generate volume shader */
1116                 find_dependencies(dependencies, output->input("Volume"));
1117                 generate_nodes(dependencies);
1118                 output->compile(*this);
1119         }
1120         else if(type == SHADER_TYPE_DISPLACEMENT) {
1121                 /* generate displacement shader */
1122                 find_dependencies(dependencies, output->input("Displacement"));
1123                 generate_nodes(dependencies);
1124                 output->compile(*this);
1125         }
1126         else
1127                 assert(0);
1128
1129         ss->ShaderGroupEnd();
1130
1131         return group;
1132 }
1133
1134 void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
1135 {
1136         if(shader->need_update) {
1137                 ShaderGraph *graph = shader->graph;
1138                 ShaderNode *output = (graph)? graph->output(): NULL;
1139
1140                 bool has_bump = (shader->displacement_method != DISPLACE_TRUE) &&
1141                                 output->input("Surface")->link && output->input("Displacement")->link;
1142
1143                 /* finalize */
1144                 shader->graph->finalize(scene,
1145                                         has_bump,
1146                                         shader->has_integrator_dependency,
1147                                         shader->displacement_method == DISPLACE_BOTH);
1148
1149                 current_shader = shader;
1150
1151                 shader->has_surface = false;
1152                 shader->has_surface_emission = false;
1153                 shader->has_surface_transparent = false;
1154                 shader->has_surface_bssrdf = false;
1155                 shader->has_bump = has_bump;
1156                 shader->has_bssrdf_bump = has_bump;
1157                 shader->has_volume = false;
1158                 shader->has_displacement = false;
1159                 shader->has_surface_spatial_varying = false;
1160                 shader->has_volume_spatial_varying = false;
1161                 shader->has_object_dependency = false;
1162                 shader->has_attribute_dependency = false;
1163                 shader->has_integrator_dependency = false;
1164
1165                 /* generate surface shader */
1166                 if(shader->used && graph && output->input("Surface")->link) {
1167                         shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
1168
1169                         if(has_bump)
1170                                 shader->osl_surface_bump_ref = compile_type(shader, shader->graph, SHADER_TYPE_BUMP);
1171                         else
1172                                 shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1173
1174                         shader->has_surface = true;
1175                 }
1176                 else {
1177                         shader->osl_surface_ref = OSL::ShaderGroupRef();
1178                         shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1179                 }
1180
1181                 /* generate volume shader */
1182                 if(shader->used && graph && output->input("Volume")->link) {
1183                         shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
1184                         shader->has_volume = true;
1185                 }
1186                 else
1187                         shader->osl_volume_ref = OSL::ShaderGroupRef();
1188
1189                 /* generate displacement shader */
1190                 if(shader->used && graph && output->input("Displacement")->link) {
1191                         shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
1192                         shader->has_displacement = true;
1193                 }
1194                 else
1195                         shader->osl_displacement_ref = OSL::ShaderGroupRef();
1196         }
1197
1198         /* push state to array for lookup */
1199         og->surface_state.push_back(shader->osl_surface_ref);
1200         og->volume_state.push_back(shader->osl_volume_ref);
1201         og->displacement_state.push_back(shader->osl_displacement_ref);
1202         og->bump_state.push_back(shader->osl_surface_bump_ref);
1203 }
1204
1205 #else
1206
1207 void OSLCompiler::add(ShaderNode * /*node*/, const char * /*name*/, bool /*isfilepath*/)
1208 {
1209 }
1210
1211 void OSLCompiler::parameter(ShaderNode * /*node*/, const char * /*name*/)
1212 {
1213 }
1214
1215 void OSLCompiler::parameter(const char * /*name*/, float /*f*/)
1216 {
1217 }
1218
1219 void OSLCompiler::parameter_color(const char * /*name*/, float3 /*f*/)
1220 {
1221 }
1222
1223 void OSLCompiler::parameter_vector(const char * /*name*/, float3 /*f*/)
1224 {
1225 }
1226
1227 void OSLCompiler::parameter_point(const char * /*name*/, float3 /*f*/)
1228 {
1229 }
1230
1231 void OSLCompiler::parameter_normal(const char * /*name*/, float3 /*f*/)
1232 {
1233 }
1234
1235 void OSLCompiler::parameter(const char * /*name*/, int /*f*/)
1236 {
1237 }
1238
1239 void OSLCompiler::parameter(const char * /*name*/, const char * /*s*/)
1240 {
1241 }
1242
1243 void OSLCompiler::parameter(const char * /*name*/, ustring /*s*/)
1244 {
1245 }
1246
1247 void OSLCompiler::parameter(const char * /*name*/, const Transform& /*tfm*/)
1248 {
1249 }
1250
1251 void OSLCompiler::parameter_array(const char * /*name*/, const float /*f*/[], int /*arraylen*/)
1252 {
1253 }
1254
1255 void OSLCompiler::parameter_color_array(const char * /*name*/, const array<float3>& /*f*/)
1256 {
1257 }
1258
1259 #endif /* WITH_OSL */
1260
1261 CCL_NAMESPACE_END