diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2016-05-29 16:10:34 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2016-06-08 22:45:40 +0300 |
commit | 56f89666eefe064f00cef2af270f0d014eb673f7 (patch) | |
tree | ce8ab56fb2e062094824941ed2d56bb98ab1a631 /intern/cycles/render | |
parent | 10d3acacf6bc630141796137beb506cd2478eccd (diff) |
Code refactor: centralize OSL node creation in shader manager.
Diffstat (limited to 'intern/cycles/render')
-rw-r--r-- | intern/cycles/render/nodes.cpp | 19 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 11 | ||||
-rw-r--r-- | intern/cycles/render/osl.cpp | 129 | ||||
-rw-r--r-- | intern/cycles/render/osl.h | 7 |
4 files changed, 157 insertions, 9 deletions
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index ea68a671029..a73204bc190 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -4516,20 +4516,29 @@ void SetNormalNode::compile(OSLCompiler& compiler) compiler.add(this, "node_set_normal"); } -/* OSLScriptNode */ +/* OSLNode */ -OSLScriptNode::OSLScriptNode() -: ShaderNode("osl_script") +OSLNode::OSLNode() +: ShaderNode("osl_shader") { special_type = SHADER_SPECIAL_TYPE_SCRIPT; } -void OSLScriptNode::compile(SVMCompiler& /*compiler*/) +OSLNode::~OSLNode() +{ +} + +OSLNode* OSLNode::create(size_t) +{ + return new OSLNode(); +} + +void OSLNode::compile(SVMCompiler&) { /* doesn't work for SVM, obviously ... */ } -void OSLScriptNode::compile(OSLCompiler& compiler) +void OSLNode::compile(OSLCompiler& compiler) { if(!filepath.empty()) compiler.add(this, filepath.c_str(), true); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 43dc1dd26fe..9ece9b86eac 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -966,17 +966,22 @@ public: SHADER_NODE_CLASS(SetNormalNode) }; -class OSLScriptNode : public ShaderNode { +class OSLNode : public ShaderNode { public: - SHADER_NODE_CLASS(OSLScriptNode) + static OSLNode *create(size_t num_inputs); + ~OSLNode(); + + SHADER_NODE_BASE_CLASS(OSLNode) /* ideally we could beter detect this, but we can't query this now */ bool has_spatial_varying() { return true; } + virtual bool equals(const ShaderNode * /*other*/) { return false; } string filepath; string bytecode_hash; - virtual bool equals(const ShaderNode * /*other*/) { return false; } +private: + OSLNode(); }; class NormalMapNode : public ShaderNode { diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index c1112ce44f6..1cfe3fb38e2 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -394,16 +394,143 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str { ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str()); - /* this is a bit weak, but works */ OSLShaderInfo info; + + if(!info.query.open_bytecode(bytecode)) { + fprintf(stderr, "OSL query error: %s\n", info.query.geterror().c_str()); + } + + /* this is a bit weak, but works */ info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos); info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos); info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos); + loaded_shaders[hash] = info; return loaded_shaders.find(hash)->first.c_str(); } +OSLNode *OSLShaderManager::osl_node(const std::string& filepath, + const std::string& bytecode_hash, + const std::string& bytecode) +{ + /* create query */ + const char *hash; + + if(!filepath.empty()) { + hash = shader_load_filepath(filepath); + } + else { + hash = shader_test_loaded(bytecode_hash); + if(!hash) + hash = shader_load_bytecode(bytecode_hash, bytecode); + } + + if(!hash) { + return NULL; + } + + OSLShaderInfo *info = shader_loaded_info(hash); + + /* count number of inputs */ + size_t num_inputs = 0; + + for(int i = 0; i < info->query.nparams(); i++) { + const OSL::OSLQuery::Parameter *param = info->query.getparam(i); + + /* skip unsupported types */ + if(param->varlenarray || param->isstruct || param->type.arraylen > 1) + continue; + + if(!param->isoutput) + num_inputs++; + } + + /* create node */ + OSLNode *node = OSLNode::create(num_inputs); + + /* add new sockets from parameters */ + set<void*> used_sockets; + + for(int i = 0; i < info->query.nparams(); i++) { + const OSL::OSLQuery::Parameter *param = info->query.getparam(i); + + /* skip unsupported types */ + if(param->varlenarray || param->isstruct || param->type.arraylen > 1) + continue; + + SocketType::Type socket_type; + + if(param->isclosure) { + socket_type = SocketType::CLOSURE; + } + else if(param->type.vecsemantics != TypeDesc::NOSEMANTICS) { + if(param->type.vecsemantics == TypeDesc::COLOR) + socket_type = SocketType::COLOR; + else if(param->type.vecsemantics == TypeDesc::POINT) + socket_type = SocketType::POINT; + else if(param->type.vecsemantics == TypeDesc::VECTOR) + socket_type = SocketType::VECTOR; + else if(param->type.vecsemantics == TypeDesc::NORMAL) + socket_type = SocketType::NORMAL; + else + continue; + + if(!param->isoutput && param->validdefault) { + node->add_input(param->name.c_str(), socket_type, make_float3(param->fdefault[0], param->fdefault[1], param->fdefault[2])); + continue; + } + } + else if(param->type.aggregate == TypeDesc::SCALAR) { + if(param->type.basetype == TypeDesc::INT) { + socket_type = SocketType::INT; + + if(!param->isoutput && param->validdefault) { + node->add_input(param->name.c_str(), socket_type, (float)param->idefault[0]); + continue; + } + } + else if(param->type.basetype == TypeDesc::FLOAT) { + socket_type = SocketType::FLOAT; + + if(!param->isoutput && param->validdefault) { + node->add_input(param->name.c_str(), socket_type, param->fdefault[0]); + continue; + } + } + else if(param->type.basetype == TypeDesc::STRING) { + socket_type = SocketType::STRING; + + if(!param->isoutput && param->validdefault) { + node->add_input(param->name.c_str(), socket_type); + continue; + } + } + else + continue; + } + else + continue; + + if(param->isoutput) { + node->add_output(param->name.c_str(), socket_type); + } + else { + node->add_input(param->name.c_str(), socket_type); + } + } + + /* set bytcode hash or filepath */ + if(!bytecode_hash.empty()) { + node->bytecode_hash = bytecode_hash; + } + else { + node->filepath = filepath; + } + + return node; +} + /* Graph Compiler */ OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_) diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 110897ff300..13b9d6307f9 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -22,6 +22,7 @@ #include "util_thread.h" #include "graph.h" +#include "nodes.h" #include "shader.h" #ifdef WITH_OSL @@ -54,6 +55,7 @@ struct OSLShaderInfo { has_surface_bssrdf(false) {} + OSL::OSLQuery query; bool has_surface_emission; bool has_surface_transparent; bool has_surface_bssrdf; @@ -83,6 +85,11 @@ public: const char *shader_load_filepath(string filepath); OSLShaderInfo *shader_loaded_info(const string& hash); + /* create OSL node using OSLQuery */ + OSLNode *osl_node(const std::string& filepath, + const std::string& bytecode_hash = "", + const std::string& bytecode = ""); + protected: void texture_system_init(); void texture_system_free(); |