diff options
Diffstat (limited to 'intern/cycles/render/osl.cpp')
-rw-r--r-- | intern/cycles/render/osl.cpp | 115 |
1 files changed, 78 insertions, 37 deletions
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index a02f91ad2cf..e1c5416b024 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -100,7 +100,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager); compiler.background = (shader == scene->shaders[scene->default_background]); - compiler.compile(og, shader); + compiler.compile(scene, og, shader); if(shader->use_mis && shader->has_surface_emission) scene->light_manager->need_update = true; @@ -125,11 +125,21 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene device_update_common(device, dscene, scene, progress); - /* greedyjit test { + /* Perform greedyjit optimization. + * + * This might waste time on optimizing gorups which are never actually + * used, but this prevents OSL from allocating data on TLS at render + * time. + * + * This is much better for us because this way we aren't required to + * stop task scheduler threads to make sure all TLS is clean and don't + * have issues with TLS data free accessing freed memory if task scheduler + * is being freed after the Session is freed. + */ thread_scoped_lock lock(ss_shared_mutex); ss->optimize_all_groups(); - }*/ + } } void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) @@ -176,6 +186,7 @@ void OSLShaderManager::texture_system_free() ts_shared_users--; if(ts_shared_users == 0) { + ts_shared->invalidate_all(true); OSL::TextureSystem::destroy(ts_shared); ts_shared = NULL; } @@ -191,13 +202,26 @@ void OSLShaderManager::shading_system_init() if(ss_shared_users == 0) { services_shared = new OSLRenderServices(); + string shader_path = path_get("shader"); +#ifdef _WIN32 + /* Annoying thing, Cycles stores paths in UTF-8 codepage, so it can + * operate with file paths with any character. This requires to use wide + * char functions, but OSL uses old fashioned ANSI functions which means: + * + * - We have to convert our paths to ANSI before passing to OSL + * - OSL can't be used when there's a multi-byte character in the path + * to the shaders folder. + */ + shader_path = string_to_ansi(shader_path); +#endif + ss_shared = new OSL::ShadingSystem(services_shared, ts_shared, &errhandler); ss_shared->attribute("lockgeom", 1); ss_shared->attribute("commonspace", "world"); - ss_shared->attribute("searchpath:shader", path_get("shader")); - //ss_shared->attribute("greedyjit", 1); + ss_shared->attribute("searchpath:shader", shader_path); + ss_shared->attribute("greedyjit", 1); - VLOG(1) << "Using shader search path: " << path_get("shader"); + VLOG(1) << "Using shader search path: " << shader_path; /* our own ray types */ static const char *raytypes[] = { @@ -253,11 +277,7 @@ void OSLShaderManager::shading_system_free() bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile) { -#if OSL_LIBRARY_VERSION_CODE < 10602 - vector<string_view> options; -#else vector<string> options; -#endif string stdosl_path; string shader_path = path_get("shader"); @@ -272,7 +292,7 @@ bool OSLShaderManager::osl_compile(const string& inputfile, const string& output stdosl_path = path_get("shader/stdosl.h"); /* compile */ - OSL::OSLCompiler *compiler = new OSL::OSLCompiler(); + OSL::OSLCompiler *compiler = new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler()); bool ok = compiler->compile(string_view(inputfile), options, string_view(stdosl_path)); delete compiler; @@ -555,24 +575,34 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) /* test if we shader contains specific closures */ OSLShaderInfo *info = ((OSLShaderManager*)manager)->shader_loaded_info(name); - if(info && current_type == SHADER_TYPE_SURFACE) { - if(info->has_surface_emission) - current_shader->has_surface_emission = true; - if(info->has_surface_transparent) - current_shader->has_surface_transparent = true; - if(info->has_surface_bssrdf) { - current_shader->has_surface_bssrdf = true; - current_shader->has_bssrdf_bump = true; /* can't detect yet */ + if(current_type == SHADER_TYPE_SURFACE) { + if(info) { + if(info->has_surface_emission) + current_shader->has_surface_emission = true; + if(info->has_surface_transparent) + current_shader->has_surface_transparent = true; + if(info->has_surface_bssrdf) { + current_shader->has_surface_bssrdf = true; + current_shader->has_bssrdf_bump = true; /* can't detect yet */ + } + } + + if(node->has_spatial_varying()) { + current_shader->has_surface_spatial_varying = true; } } else if(current_type == SHADER_TYPE_VOLUME) { if(node->has_spatial_varying()) - current_shader->has_heterogeneous_volume = true; + current_shader->has_volume_spatial_varying = true; } if(node->has_object_dependency()) { current_shader->has_object_dependency = true; } + + if(node->has_integrator_dependency()) { + current_shader->has_integrator_dependency = true; + } } void OSLCompiler::parameter(const char *name, float f) @@ -694,11 +724,11 @@ void OSLCompiler::parameter_array(const char *name, const Transform tfm[], int a ss->Parameter(name, type, (const float *)tfm); } -void OSLCompiler::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input) +void OSLCompiler::find_dependencies(ShaderNodeSet& dependencies, ShaderInput *input) { ShaderNode *node = (input->link)? input->link->parent: NULL; - if(node) { + if(node != NULL && dependencies.find(node) == dependencies.end()) { foreach(ShaderInput *in, node->inputs) if(!node_skip_input(node, in)) find_dependencies(dependencies, in); @@ -707,9 +737,9 @@ void OSLCompiler::find_dependencies(set<ShaderNode*>& dependencies, ShaderInput } } -void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) +void OSLCompiler::generate_nodes(const ShaderNodeSet& nodes) { - set<ShaderNode*> done; + ShaderNodeSet done; bool nodes_done; do { @@ -733,6 +763,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_spatial_varying()) + current_shader->has_surface_spatial_varying = true; if(node->has_surface_bssrdf()) { current_shader->has_surface_bssrdf = true; if(node->has_bssrdf_bump()) @@ -741,7 +773,7 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) } else if(current_type == SHADER_TYPE_VOLUME) { if(node->has_spatial_varying()) - current_shader->has_heterogeneous_volume = true; + current_shader->has_volume_spatial_varying = true; } } else @@ -751,16 +783,16 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) } while(!nodes_done); } -OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type) +OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType type) { OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys; current_type = type; - OSL::ShadingAttribStateRef group = ss->ShaderGroupBegin(shader->name.c_str()); + OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->name.c_str()); ShaderNode *output = graph->output(); - set<ShaderNode*> dependencies; + ShaderNodeSet dependencies; if(type == SHADER_TYPE_SURFACE) { /* generate surface shader */ @@ -788,7 +820,7 @@ OSL::ShadingAttribStateRef OSLCompiler::compile_type(Shader *shader, ShaderGraph return group; } -void OSLCompiler::compile(OSLGlobals *og, Shader *shader) +void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader) { if(shader->need_update) { ShaderGraph *graph = shader->graph; @@ -800,9 +832,16 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->graph_bump = shader->graph->copy(); /* finalize */ - shader->graph->finalize(false, true); - if(shader->graph_bump) - shader->graph_bump->finalize(true, true); + shader->graph->finalize(scene, + false, + true, + shader->has_integrator_dependency); + if(shader->graph_bump) { + shader->graph_bump->finalize(scene, + true, + true, + shader->has_integrator_dependency); + } current_shader = shader; @@ -813,8 +852,10 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_bssrdf_bump = false; shader->has_volume = false; shader->has_displacement = false; - shader->has_heterogeneous_volume = false; + shader->has_surface_spatial_varying = false; + shader->has_volume_spatial_varying = false; shader->has_object_dependency = false; + shader->has_integrator_dependency = false; /* generate surface shader */ if(shader->used && graph && output->input("Surface")->link) { @@ -828,8 +869,8 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_surface = true; } else { - shader->osl_surface_ref = OSL::ShadingAttribStateRef(); - shader->osl_surface_bump_ref = OSL::ShadingAttribStateRef(); + shader->osl_surface_ref = OSL::ShaderGroupRef(); + shader->osl_surface_bump_ref = OSL::ShaderGroupRef(); } /* generate volume shader */ @@ -838,7 +879,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_volume = true; } else - shader->osl_volume_ref = OSL::ShadingAttribStateRef(); + shader->osl_volume_ref = OSL::ShaderGroupRef(); /* generate displacement shader */ if(shader->used && graph && output->input("Displacement")->link) { @@ -846,7 +887,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_displacement = true; } else - shader->osl_displacement_ref = OSL::ShadingAttribStateRef(); + shader->osl_displacement_ref = OSL::ShaderGroupRef(); } /* push state to array for lookup */ |