38# if OIIO_VERSION_MAJOR >= 3
39std::shared_ptr<OSL::TextureSystem> OSLShaderManager::ts_shared;
41OSL::TextureSystem *OSLShaderManager::ts_shared =
NULL;
43int OSLShaderManager::ts_shared_users = 0;
46OSL::ErrorHandler OSLShaderManager::errhandler;
47map<int, OSL::ShadingSystem *> OSLShaderManager::ss_shared;
48int OSLShaderManager::ss_shared_users = 0;
52int OSLCompiler::texture_shared_unique_id = 0;
56OSLShaderManager::OSLShaderManager(
Device *device) : device_(device)
58 texture_system_init();
59 shading_system_init();
62OSLShaderManager::~OSLShaderManager()
64 shading_system_free();
65 texture_system_free();
68void OSLShaderManager::free_memory()
70# ifdef OSL_HAS_BLENDER_CLEANUP_FIX
76 OSL::pvt::LLVM_Util::Cleanup();
80void OSLShaderManager::reset(
Scene * )
82 shading_system_free();
83 shading_system_init();
86uint64_t OSLShaderManager::get_attribute_id(ustring name)
95 return stdname.hash();
98void OSLShaderManager::device_update_specific(
Device *device,
114 device_free(device, dscene, scene);
118# if OIIO_VERSION_MAJOR >= 3
129 assert(shader->
graph);
140 [
this, scene, shader, background = (shader == background_shader)](
Device *sub_device) {
142 OSL::ShadingSystem *ss = ss_shared[sub_device->
info.
type];
145 compiler.background = background;
146 compiler.compile(og, shader);
158 OSL::ShadingSystem *ss = ss_shared[sub_device->
info.
type];
161# if OIIO_VERSION_MAJOR >= 3
162 og->ts = ts_shared.get();
168 og->background_state = og->surface_state[background_id &
SHADER_MASK];
175 update_flags = UPDATE_NONE;
178 for (
const auto &[device_type, ss] : ss_shared) {
186 device_update_common(device, dscene, scene, progress);
209 for (
const auto &[device_type, ss] : ss_shared) {
210 ss->optimize_all_groups();
224 device_free_common(device, dscene, scene);
234 og->surface_state.clear();
235 og->volume_state.clear();
236 og->displacement_state.clear();
237 og->bump_state.clear();
238 og->background_state.reset();
243 for (
const auto &[device_type, ss] : ss_shared) {
246 for (
auto it = services->
textures.begin(); it != services->
textures.end(); ++it) {
247 if (it->second->handle.get_manager() == scene->
image_manager) {
249 services->
textures.erase(it->first,
false);
258void OSLShaderManager::texture_system_init()
263 if (ts_shared_users++ == 0) {
264 ts_shared = TextureSystem::create(
true);
266 ts_shared->attribute(
"automip", 1);
267 ts_shared->attribute(
"autotile", 64);
268 ts_shared->attribute(
"gray_to_rgb", 1);
271 ts_shared->attribute(
"max_memory_MB", 16384);
275void OSLShaderManager::texture_system_free()
280 if (--ts_shared_users == 0) {
281 ts_shared->invalidate_all(
true);
282# if OIIO_VERSION_MAJOR >= 3
283 OSL::TextureSystem::destroy(ts_shared);
286 OSL::TextureSystem::destroy(ts_shared);
292void OSLShaderManager::shading_system_init()
297 device_->foreach_device([](
Device *sub_device) {
300 if (ss_shared_users++ == 0 || ss_shared.find(device_type) == ss_shared.end()) {
302# if OIIO_VERSION_MAJOR >= 3
309 string shader_path =
path_get(
"shader");
319 shader_path = string_to_ansi(shader_path);
322# if OIIO_VERSION_MAJOR >= 3
323 OSL::ShadingSystem *ss =
new OSL::ShadingSystem(
324 services, ts_shared.get(), &errhandler);
326 OSL::ShadingSystem *ss =
new OSL::ShadingSystem(services, ts_shared, &errhandler);
328 ss->attribute(
"lockgeom", 1);
329 ss->attribute(
"commonspace",
"world");
330 ss->attribute(
"searchpath:shader", shader_path);
331 ss->attribute(
"greedyjit", 1);
333 VLOG_INFO <<
"Using shader search path: " << shader_path;
336 static const char *raytypes[] = {
376 const int nraytypes =
sizeof(raytypes) /
sizeof(raytypes[0]);
377 ss->attribute(
"raytypes",
TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
381 ss_shared[device_type] = ss;
385 loaded_shaders.clear();
388void OSLShaderManager::shading_system_free()
393 device_->foreach_device([](
Device * ) {
394 if (--ss_shared_users == 0) {
395 for (
const auto &[device_type, ss] : ss_shared) {
408bool OSLShaderManager::osl_compile(
const string &inputfile,
const string &outputfile)
412 string shader_path =
path_get(
"shader");
419 string include_path_arg = string(
"-I") + shader_path;
420 options.push_back(include_path_arg);
422 stdosl_path =
path_join(shader_path,
"stdcycles.h");
430 OSL::OSLCompiler *compiler =
new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
431 bool ok = compiler->compile(string_view(inputfile),
options, string_view(stdosl_path));
437bool OSLShaderManager::osl_query(OSL::OSLQuery &query,
const string &filepath)
440 return query.open(filepath, searchpath);
443static string shader_filepath_hash(
const string &filepath,
uint64_t modified_time)
447 md5.
append((
const uint8_t *)filepath.c_str(), filepath.size());
448 md5.
append((
const uint8_t *)&modified_time,
sizeof(modified_time));
453const char *OSLShaderManager::shader_test_loaded(
const string &
hash)
455 map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(
hash);
456 return (it == loaded_shaders.end()) ?
NULL : it->first.c_str();
459OSLShaderInfo *OSLShaderManager::shader_loaded_info(
const string &
hash)
461 map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(
hash);
462 return (it == loaded_shaders.end()) ?
NULL : &it->second;
465const char *OSLShaderManager::shader_load_filepath(
string filepath)
467 size_t len = filepath.size();
468 string extension = filepath.substr(
len - 4);
471 if (extension ==
".osl") {
473 string osopath = filepath.substr(0,
len - 4) +
".oso";
477 if (oso_modified_time != 0) {
478 const char *
hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
485 if (oso_modified_time == 0 || (oso_modified_time < modified_time)) {
486 OSLShaderManager::osl_compile(filepath, osopath);
490 modified_time = oso_modified_time;
495 if (extension ==
".oso") {
508 const char *
hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
515 string bytecode_hash = shader_filepath_hash(filepath, modified_time);
519 fprintf(stderr,
"Cycles shader graph: failed to read file %s\n", filepath.c_str());
521 loaded_shaders[bytecode_hash] = info;
525 return shader_load_bytecode(bytecode_hash, bytecode);
528const char *OSLShaderManager::shader_load_bytecode(
const string &
hash,
const string &bytecode)
530 for (
const auto &[device_type, ss] : ss_shared) {
531 ss->LoadMemoryCompiledShader(
hash.c_str(), bytecode.c_str());
536 if (!info.query.open_bytecode(bytecode)) {
537 fprintf(stderr,
"OSL query error: %s\n", info.query.geterror().c_str());
541 info.has_surface_emission = (bytecode.find(
"\"emission\"") != string::npos);
542 info.has_surface_transparent = (bytecode.find(
"\"transparent\"") != string::npos);
543 info.has_surface_bssrdf = (bytecode.find(
"\"bssrdf\"") != string::npos);
545 loaded_shaders[
hash] = info;
547 return loaded_shaders.find(
hash)->first.c_str();
554 const std::string &filepath,
555 const std::string &bytecode_hash,
556 const std::string &bytecode)
563 OSLShaderManager *osl_manager =
static_cast<OSLShaderManager *
>(manager);
566 if (!filepath.empty()) {
567 hash = osl_manager->shader_load_filepath(filepath);
570 hash = osl_manager->shader_test_loaded(bytecode_hash);
572 hash = osl_manager->shader_load_bytecode(bytecode_hash, bytecode);
579 OSLShaderInfo *info = osl_manager->shader_loaded_info(
hash);
582 size_t num_inputs = 0;
584 for (
int i = 0; i < info->query.nparams(); i++) {
585 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
588 if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
591 if (!param->isoutput)
599 set<void *> used_sockets;
601 for (
int i = 0; i < info->query.nparams(); i++) {
602 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
605 if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
611 if (param->isclosure) {
614 else if (param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
615 if (param->type.vecsemantics == TypeDesc::COLOR)
617 else if (param->type.vecsemantics == TypeDesc::POINT)
619 else if (param->type.vecsemantics == TypeDesc::VECTOR)
621 else if (param->type.vecsemantics == TypeDesc::NORMAL)
626 if (!param->isoutput && param->validdefault) {
628 default_value->
x = param->fdefault[0];
629 default_value->
y = param->fdefault[1];
630 default_value->
z = param->fdefault[2];
633 else if (param->type.aggregate == TypeDesc::SCALAR) {
634 if (param->type.basetype == TypeDesc::INT) {
637 if (!param->isoutput && param->validdefault) {
641 else if (param->type.basetype == TypeDesc::FLOAT) {
644 if (!param->isoutput && param->validdefault) {
648 else if (param->type.basetype == TypeDesc::STRING) {
651 if (!param->isoutput && param->validdefault) {
661 if (param->isoutput) {
667 int socket_flags = 0;
668 if (!param->validdefault) {
671 for (
const OSL::OSLQuery::Parameter &metadata : param->metadata) {
672 if (metadata.type == TypeDesc::STRING) {
673 if (metadata.name ==
"widget" && metadata.sdefault[0] ==
"null") {
679 node->
add_input(param->name, socket_type, socket_flags);
684 if (!bytecode_hash.empty()) {
698void OSLShaderManager::osl_image_slots(
Device *device,
700 set<int> &image_slots)
702 set<OSLRenderServices *> services_shared;
705 services_shared.insert(og->services);
709 for (
auto it = services->
textures.begin(); it != services->
textures.end(); ++it) {
710 if (it->second->handle.get_manager() == image_manager) {
711 const int slot = it->second->handle.svm_slot();
712 image_slots.insert(slot);
720OSLCompiler::OSLCompiler(OSLShaderManager *manager, OSL::ShadingSystem *ss,
Scene *scene)
727 current_shader =
NULL;
734 std::stringstream stream;
738 stream.imbue(std::locale(
"C"));
740 stream <<
"node_" << node->
type->
name <<
"_" << node;
747 string sname(input->
name().string());
751 while ((i = sname.find(
" ")) != string::npos)
752 sname.replace(i, 1,
"");
767 string sname(
output->name().string());
771 while ((i = sname.find(
" ")) != string::npos)
772 sname.replace(i, 1,
"");
775 foreach (ShaderInput *input, node->
inputs) {
804 if (input->
name() ==
"Height")
818 name = manager->shader_load_filepath(name);
825 foreach (ShaderInput *input, node->
inputs) {
828 if (node_skip_input(node, input)) {
835 string param_name = compatible_name(node, input);
837 switch (input->
type()) {
870 ss->Shader(
"surface", name,
id(node).c_str());
872 ss->Shader(
"surface", name,
id(node).c_str());
874 ss->Shader(
"displacement", name,
id(node).c_str());
876 ss->Shader(
"displacement", name,
id(node).c_str());
881 foreach (ShaderInput *input, node->
inputs) {
883 if (node_skip_input(node, input))
888 string id_to = id(node);
889 string param_from = compatible_name(input->
link->
parent, input->
link);
890 string param_to = compatible_name(node, input);
892 ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
897 OSLShaderInfo *info = manager->shader_loaded_info(name);
903 OSLNode *oslnode =
static_cast<OSLNode *
>(node);
906 if (info->has_surface_transparent)
907 current_shader->has_surface_transparent =
true;
908 if (info->has_surface_bssrdf) {
909 current_shader->has_surface_bssrdf =
true;
910 current_shader->has_bssrdf_bump =
true;
912 current_shader->has_bump =
true;
913 current_shader->has_surface_raytrace =
true;
917 current_shader->has_surface_spatial_varying =
true;
922 current_shader->has_volume_spatial_varying =
true;
924 current_shader->has_volume_attribute_dependency =
true;
930 return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
931 (TypeDesc::AGGREGATE)typedesc.aggregate,
932 (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
938 ustring uname = ustring(name);
941 switch (socket.
type) {
944 ss->Parameter(name, TypeInt, &value);
949 ss->Parameter(uname, TypeFloat, &value);
953 int value = node->
get_int(socket);
954 ss->Parameter(uname, TypeInt, &value);
959 ss->Parameter(uname, TypeColor, &value);
964 ss->Parameter(uname, TypeVector, &value);
969 ss->Parameter(uname, TypePoint, &value);
974 ss->Parameter(uname, TypeNormal, &value);
979 ss->Parameter(uname,
TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), &value);
984 ss->Parameter(uname, TypeString, &value);
989 ss->Parameter(uname, TypeString, &value);
996 ss->Parameter(uname, TypeMatrix, &projection);
1002 array<int> intvalue(value.
size());
1003 for (
size_t i = 0; i < value.
size(); i++)
1004 intvalue[i] = value[i];
1005 ss->Parameter(uname, array_typedesc(TypeInt, value.
size()), intvalue.data());
1010 ss->Parameter(uname, array_typedesc(TypeFloat, value.
size()), value.
data());
1015 ss->Parameter(uname, array_typedesc(TypeInt, value.
size()), value.
data());
1024 switch (socket.
type) {
1026 typedesc = TypeColor;
1029 typedesc = TypeVector;
1032 typedesc = TypePoint;
1035 typedesc = TypeNormal;
1044 array<float> fvalue(value.
size() * 3);
1045 for (
size_t i = 0, j = 0; i < value.
size(); i++) {
1046 fvalue[j++] = value[i].x;
1047 fvalue[j++] = value[i].y;
1048 fvalue[j++] = value[i].z;
1051 ss->Parameter(uname, array_typedesc(typedesc, value.
size()), fvalue.data());
1058 array_typedesc(
TypeDesc(TypeDesc::FLOAT, TypeDesc::VEC2, TypeDesc::POINT), value.
size()),
1064 ss->Parameter(uname, array_typedesc(TypeString, value.
size()), value.
data());
1069 array<ProjectionTransform> fvalue(value.
size());
1070 for (
size_t i = 0; i < value.
size(); i++) {
1073 ss->Parameter(uname, array_typedesc(TypeMatrix, fvalue.size()), fvalue.data());
1091 ss->Parameter(name, TypeFloat, &f);
1096 ss->Parameter(name, TypeColor, &f);
1101 ss->Parameter(name, TypePoint, &f);
1106 ss->Parameter(name, TypeNormal, &f);
1111 ss->Parameter(name, TypeVector, &f);
1116 ss->Parameter(name, TypeInt, &f);
1121 ss->Parameter(name, TypeString, &s);
1126 const char *
str = s.c_str();
1127 ss->Parameter(name, TypeString, &
str);
1134 ss->Parameter(name, TypeMatrix, (
float *)&projection);
1140 type.arraylen = arraylen;
1141 ss->Parameter(name, type, f);
1147 array<float[3]> table(f.
size());
1149 for (
int i = 0; i < f.
size(); ++i) {
1150 table[i][0] = f[i].x;
1151 table[i][1] = f[i].y;
1152 table[i][2] = f[i].z;
1156 type.arraylen = table.size();
1157 ss->Parameter(name, type, table.data());
1163 parameter(name, (
string(
"geom:") + s.c_str()).c_str());
1172 if (node !=
NULL && dependencies.find(node) == dependencies.end()) {
1173 foreach (ShaderInput *
in, node->
inputs)
1174 if (!node_skip_input(node, in))
1175 find_dependencies(dependencies, in);
1177 dependencies.insert(node);
1189 foreach (ShaderNode *node, nodes) {
1190 if (done.find(node) == done.end()) {
1191 bool inputs_done =
true;
1193 foreach (ShaderInput *input, node->
inputs)
1194 if (!node_skip_input(node, input))
1196 inputs_done =
false;
1204 current_shader->has_surface_transparent =
true;
1206 current_shader->has_surface_raytrace =
true;
1208 current_shader->has_surface_spatial_varying =
true;
1210 current_shader->has_surface_bssrdf =
true;
1212 current_shader->has_bssrdf_bump =
true;
1215 current_shader->has_bump =
true;
1220 current_shader->has_volume_spatial_varying =
true;
1227 }
while (!nodes_done);
1232 current_type = type;
1235 std::stringstream name;
1236 name.imbue(std::locale(
"C"));
1237 name <<
"shader_" << shader->
name.hash();
1239 OSL::ShaderGroupRef group = ss->ShaderGroupBegin(name.str());
1246 find_dependencies(dependencies,
output->input(
"Surface"));
1247 generate_nodes(dependencies);
1252 find_dependencies(dependencies,
output->input(
"Normal"));
1253 generate_nodes(dependencies);
1258 find_dependencies(dependencies,
output->input(
"Volume"));
1259 generate_nodes(dependencies);
1264 find_dependencies(dependencies,
output->input(
"Displacement"));
1265 generate_nodes(dependencies);
1271 ss->ShaderGroupEnd();
1279 ShaderGraph *graph = shader->
graph;
1282 bool has_bump = (shader->get_displacement_method() !=
DISPLACE_TRUE) &&
1288 current_shader = shader;
1309 shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1314 shader->osl_surface_ref = OSL::ShaderGroupRef();
1315 shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1324 shader->osl_volume_ref = OSL::ShaderGroupRef();
1332 shader->osl_displacement_ref = OSL::ShaderGroupRef();
1339 og->surface_state.push_back(shader->osl_surface_ref);
1340 og->volume_state.push_back(shader->osl_volume_ref);
1341 og->displacement_state.push_back(shader->osl_displacement_ref);
1342 og->bump_state.push_back(shader->osl_surface_bump_ref);
1361 ustring filename(
string_printf(
"@svm%d", texture_shared_unique_id++).c_str());
1370 ustring filename(
string_printf(
"@svm%d", texture_shared_unique_id++).c_str());
VecBase< float, 3 > float3
static AttributeStandard name_standard(const char *name)
static const char * standard_name(AttributeStandard std)
Shader * get_shader(const Scene *scene)
static ColorSpaceProcessor * get_processor(ustring colorspace)
virtual const string & error_message()
virtual bool load_osl_kernels()
virtual void * get_cpu_osl_memory()
virtual void foreach_device(const function< void(Device *)> &callback)
vector< int4 > get_svm_slots() const
void set_osl_texture_system(void *texture_system)
void tag_update(Scene *scene, uint32_t flag)
void append(const uint8_t *data, int size)
void add_entry(const NamedTimeEntry &entry)
void add(ShaderNode *node, const char *name, bool isfilepath=false)
void parameter_vector(const char *name, float3 f)
void parameter_array(const char *name, const float f[], int arraylen)
void parameter_texture_ies(const char *name, int svm_slot)
void parameter_texture(const char *name, ustring filename, ustring colorspace)
void parameter(ShaderNode *node, const char *name)
void parameter_normal(const char *name, float3 f)
void parameter_color_array(const char *name, const array< float3 > &f)
void compile(OSLGlobals *og, Shader *shader)
void parameter_point(const char *name, float3 f)
void parameter_color(const char *name, float3 f)
void parameter_attribute(const char *name, ustring s)
void add_input(ustring name, SocketType::Type type, const int flags=0)
static OSLNode * create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from=NULL)
void add_output(ustring name, SocketType::Type type)
char * input_default_value()
static ImageManager * image_manager
OSLTextureHandleMap textures
static void register_closures(OSL::ShadingSystem *ss)
void set_error(const string &error_message_)
void finalize(Scene *scene, bool do_bump=false, bool bump_in_object_space=false)
int get_shader_id(Shader *shader, bool smooth=false)
ShaderInput * input(const char *name)
virtual bool has_surface_transparent()
vector< ShaderOutput * > outputs
ShaderNodeSpecialType special_type
virtual bool has_bssrdf_bump()
virtual bool has_spatial_varying()
vector< ShaderInput * > inputs
virtual int get_feature()
virtual bool has_attribute_dependency()
void create_inputs_outputs(const NodeType *type)
virtual bool has_surface_bssrdf()
virtual void compile(SVMCompiler &compiler)=0
bool has_surface_spatial_varying
bool has_volume_attribute_dependency
NODE_DECLARE ShaderGraph * graph
EmissionSampling emission_sampling
bool has_surface_raytrace
bool has_surface_transparent
bool has_volume_spatial_varying
VecBase< float, 2 > float2
T * util_aligned_new(Args... args)
void util_aligned_delete(T *t)
CCL_NAMESPACE_BEGIN struct ProjectionTransform ProjectionTransform
ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform &a)
CCL_NAMESPACE_BEGIN struct Options options
#define CCL_NAMESPACE_END
@ SHADER_TYPE_DISPLACEMENT
#define KERNEL_FEATURE_NODE_RAYTRACE
CCL_NAMESPACE_BEGIN typedef OSL::ustringhash OSLUStringHash
string path_user_get(const string &sub)
string path_dirname(const string &path)
string path_get(const string &sub)
uint64_t path_modified_time(const string &path)
string path_join(const string &dir, const string &file)
bool path_read_text(const string &path, string &text)
@ SHADER_SPECIAL_TYPE_BUMP
@ SHADER_SPECIAL_TYPE_OUTPUT
@ SHADER_SPECIAL_TYPE_OSL
set< ShaderNode *, ShaderNodeIDComparator > ShaderNodeSet
unsigned __int64 uint64_t
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
const SocketType * find_input(ustring name) const
const array< float3 > & get_float3_array(const SocketType &input) const
const array< float > & get_float_array(const SocketType &input) const
const array< int > & get_int_array(const SocketType &input) const
float get_float(const SocketType &input) const
Transform get_transform(const SocketType &input) const
float3 get_float3(const SocketType &input) const
const array< bool > & get_bool_array(const SocketType &input) const
bool get_bool(const SocketType &input) const
int reference_count() const
float2 get_float2(const SocketType &input) const
const array< ustring > & get_string_array(const SocketType &input) const
const array< float2 > & get_float2_array(const SocketType &input) const
ustring get_string(const SocketType &input) const
int get_int(const SocketType &input) const
const array< Transform > & get_transform_array(const SocketType &input) const
ColorSpaceProcessor * processor
vector< Shader * > shaders
ImageManager * image_manager
ShaderManager * shader_manager
LightManager * light_manager
SceneUpdateStats * update_stats
std::unique_lock< std::mutex > thread_scoped_lock
CCL_NAMESPACE_BEGIN typedef std::mutex thread_mutex