38 OSL::TextureSystem *OSLShaderManager::ts_shared =
NULL;
39 int OSLShaderManager::ts_shared_users = 0;
44 int OSLShaderManager::ss_shared_users = 0;
47 int OSLCompiler::texture_shared_unique_id = 0;
51 OSLShaderManager::OSLShaderManager()
53 texture_system_init();
54 shading_system_init();
57 OSLShaderManager::~OSLShaderManager()
59 shading_system_free();
60 texture_system_free();
63 void OSLShaderManager::free_memory()
65 # ifdef OSL_HAS_BLENDER_CLEANUP_FIX
71 OSL::pvt::LLVM_Util::Cleanup();
77 shading_system_free();
78 shading_system_init();
81 void OSLShaderManager::device_update_specific(
Device *device,
91 scene->update_stats->osl.times.add_entry({
"device_update", time});
97 device_free(device, dscene,
scene);
107 assert(shader->
graph);
118 compiler.background = (shader == background_shader);
119 compiler.compile(og, shader);
128 og->services = services;
131 og->background_state = og->surface_state[background_id &
SHADER_MASK];
137 update_flags = UPDATE_NONE;
143 device_update_common(device, dscene,
scene, progress);
158 ss->optimize_all_groups();
166 device_free_common(device, dscene,
scene);
173 og->surface_state.clear();
174 og->volume_state.clear();
175 og->displacement_state.clear();
176 og->bump_state.clear();
177 og->background_state.reset();
180 void OSLShaderManager::texture_system_init()
185 if (ts_shared_users == 0) {
188 ts_shared->attribute(
"automip", 1);
189 ts_shared->attribute(
"autotile", 64);
190 ts_shared->attribute(
"gray_to_rgb", 1);
193 ts_shared->attribute(
"max_memory_MB", 16384);
200 void OSLShaderManager::texture_system_free()
206 if (ts_shared_users == 0) {
207 ts_shared->invalidate_all(
true);
208 OSL::TextureSystem::destroy(ts_shared);
215 void OSLShaderManager::shading_system_init()
220 if (ss_shared_users == 0) {
222 services_shared = util_aligned_new<OSLRenderServices>(ts_shared);
224 string shader_path =
path_get(
"shader");
234 shader_path = string_to_ansi(shader_path);
238 ss_shared->attribute(
"lockgeom", 1);
239 ss_shared->attribute(
"commonspace",
"world");
240 ss_shared->attribute(
"searchpath:shader", shader_path);
241 ss_shared->attribute(
"greedyjit", 1);
243 VLOG_INFO <<
"Using shader search path: " << shader_path;
246 static const char *raytypes[] = {
286 const int nraytypes =
sizeof(raytypes) /
sizeof(raytypes[0]);
287 ss_shared->attribute(
"raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
289 OSLShader::register_closures((OSLShadingSystem *)ss_shared);
291 loaded_shaders.clear();
295 services = services_shared;
299 void OSLShaderManager::shading_system_free()
305 if (ss_shared_users == 0) {
310 services_shared =
NULL;
317 bool OSLShaderManager::osl_compile(
const string &inputfile,
const string &outputfile)
321 string shader_path =
path_get(
"shader");
328 string include_path_arg =
string(
"-I") + shader_path;
329 options.push_back(include_path_arg);
331 stdosl_path =
path_join(shader_path,
"stdcycles.h");
339 OSL::OSLCompiler *compiler =
new OSL::OSLCompiler(&OSL::ErrorHandler::default_handler());
340 bool ok = compiler->compile(string_view(inputfile),
options, string_view(stdosl_path));
346 bool OSLShaderManager::osl_query(OSL::OSLQuery &
query,
const string &filepath)
349 return query.open(filepath, searchpath);
352 static string shader_filepath_hash(
const string &filepath,
uint64_t modified_time)
356 md5.
append((
const uint8_t *)filepath.c_str(), filepath.size());
357 md5.
append((
const uint8_t *)&modified_time,
sizeof(modified_time));
362 const char *OSLShaderManager::shader_test_loaded(
const string &
hash)
364 map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(
hash);
365 return (it == loaded_shaders.end()) ?
NULL : it->first.c_str();
368 OSLShaderInfo *OSLShaderManager::shader_loaded_info(
const string &
hash)
370 map<string, OSLShaderInfo>::iterator it = loaded_shaders.find(
hash);
371 return (it == loaded_shaders.end()) ?
NULL : &it->second;
374 const char *OSLShaderManager::shader_load_filepath(
string filepath)
376 size_t len = filepath.size();
377 string extension = filepath.substr(
len - 4);
380 if (extension ==
".osl") {
382 string osopath = filepath.substr(0,
len - 4) +
".oso";
386 if (oso_modified_time != 0) {
387 const char *
hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
394 if (oso_modified_time == 0 || (oso_modified_time < modified_time)) {
395 OSLShaderManager::osl_compile(filepath, osopath);
399 modified_time = oso_modified_time;
404 if (extension ==
".oso") {
417 const char *
hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
424 string bytecode_hash = shader_filepath_hash(filepath, modified_time);
428 fprintf(stderr,
"Cycles shader graph: failed to read file %s\n", filepath.c_str());
430 loaded_shaders[bytecode_hash] = info;
434 return shader_load_bytecode(bytecode_hash, bytecode);
437 const char *OSLShaderManager::shader_load_bytecode(
const string &
hash,
const string &bytecode)
439 ss->LoadMemoryCompiledShader(
hash.c_str(), bytecode.c_str());
443 if (!info.query.open_bytecode(bytecode)) {
444 fprintf(stderr,
"OSL query error: %s\n", info.query.geterror().c_str());
448 info.has_surface_emission = (bytecode.find(
"\"emission\"") != string::npos);
449 info.has_surface_transparent = (bytecode.find(
"\"transparent\"") != string::npos);
450 info.has_surface_bssrdf = (bytecode.find(
"\"bssrdf\"") != string::npos);
452 loaded_shaders[
hash] = info;
454 return loaded_shaders.find(
hash)->first.c_str();
461 const std::string &filepath,
462 const std::string &bytecode_hash,
463 const std::string &bytecode)
470 OSLShaderManager *osl_manager =
static_cast<OSLShaderManager *
>(manager);
473 if (!filepath.empty()) {
474 hash = osl_manager->shader_load_filepath(filepath);
477 hash = osl_manager->shader_test_loaded(bytecode_hash);
479 hash = osl_manager->shader_load_bytecode(bytecode_hash, bytecode);
486 OSLShaderInfo *info = osl_manager->shader_loaded_info(
hash);
489 size_t num_inputs = 0;
491 for (
int i = 0; i < info->query.nparams(); i++) {
492 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
495 if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
498 if (!param->isoutput)
506 set<void *> used_sockets;
508 for (
int i = 0; i < info->query.nparams(); i++) {
509 const OSL::OSLQuery::Parameter *param = info->query.getparam(i);
512 if (param->varlenarray || param->isstruct || param->type.arraylen > 1)
517 if (param->isclosure) {
520 else if (param->type.vecsemantics != TypeDesc::NOSEMANTICS) {
521 if (param->type.vecsemantics == TypeDesc::COLOR)
525 else if (param->type.vecsemantics == TypeDesc::VECTOR)
532 if (!param->isoutput && param->validdefault) {
534 default_value->
x = param->fdefault[0];
535 default_value->
y = param->fdefault[1];
536 default_value->
z = param->fdefault[2];
539 else if (param->type.aggregate == TypeDesc::SCALAR) {
540 if (param->type.basetype == TypeDesc::INT) {
543 if (!param->isoutput && param->validdefault) {
544 *(
int *)
node->input_default_value() = param->idefault[0];
550 if (!param->isoutput && param->validdefault) {
551 *(
float *)
node->input_default_value() = param->fdefault[0];
554 else if (param->type.basetype == TypeDesc::STRING) {
557 if (!param->isoutput && param->validdefault) {
558 *(ustring *)
node->input_default_value() = param->sdefault[0];
567 if (param->isoutput) {
568 node->add_output(param->name, socket_type);
571 node->add_input(param->name, socket_type);
576 if (!bytecode_hash.empty()) {
577 node->bytecode_hash = bytecode_hash;
580 node->filepath = filepath;
584 node->create_inputs_outputs(
node->type);
591 OSLCompiler::OSLCompiler(OSLShaderManager *manager,
595 :
scene(
scene), manager(manager), services(services), ss(ss)
598 current_shader =
NULL;
606 stream <<
"node_" <<
node->type->name <<
"_" <<
node;
613 string sname(
input->name().string());
617 while ((i = sname.find(
" ")) != string::npos)
618 sname.replace(i, 1,
"");
633 string sname(
output->name().string());
637 while ((i = sname.find(
" ")) != string::npos)
638 sname.replace(i, 1,
"");
670 if (
input->name() ==
"Height")
684 name = manager->shader_load_filepath(name);
697 string param_name = compatible_name(
node,
input);
699 switch (
input->type()) {
732 ss->Shader(
"surface", name,
id(
node).c_str());
734 ss->Shader(
"surface", name,
id(
node).c_str());
736 ss->Shader(
"displacement", name,
id(
node).c_str());
738 ss->Shader(
"displacement", name,
id(
node).c_str());
749 string id_from =
id(
input->link->parent);
751 string param_from = compatible_name(
input->link->parent,
input->link);
752 string param_to = compatible_name(
node,
input);
754 ss->ConnectShaders(id_from.c_str(), param_from.c_str(), id_to.c_str(), param_to.c_str());
759 OSLShaderInfo *info = manager->shader_loaded_info(name);
763 if (info->has_surface_emission)
765 if (info->has_surface_transparent)
767 if (info->has_surface_bssrdf) {
775 if (
node->has_spatial_varying()) {
780 if (
node->has_spatial_varying())
782 if (
node->has_attribute_dependency())
786 if (
node->has_integrator_dependency()) {
791 static TypeDesc array_typedesc(TypeDesc typedesc,
int arraylength)
793 return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
794 (TypeDesc::AGGREGATE)typedesc.aggregate,
795 (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
801 ustring uname = ustring(name);
804 switch (socket.
type) {
806 int value =
node->get_bool(socket);
807 ss->Parameter(name, TypeDesc::TypeInt, &value);
811 float value =
node->get_float(socket);
812 ss->Parameter(uname, TypeDesc::TypeFloat, &value);
816 int value =
node->get_int(socket);
817 ss->Parameter(uname, TypeDesc::TypeInt, &value);
822 ss->Parameter(uname, TypeDesc::TypeColor, &value);
827 ss->Parameter(uname, TypeDesc::TypeVector, &value);
832 ss->Parameter(uname, TypeDesc::TypePoint, &value);
837 ss->Parameter(uname, TypeDesc::TypeNormal, &value);
846 ustring value =
node->get_string(socket);
847 ss->Parameter(uname, TypeDesc::TypeString, &value);
851 ustring value =
node->get_string(socket);
852 ss->Parameter(uname, TypeDesc::TypeString, &value);
859 ss->Parameter(uname, TypeDesc::TypeMatrix, &projection);
866 for (
size_t i = 0; i < value.
size(); i++)
867 intvalue[i] = value[i];
868 ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.
size()), intvalue.data());
873 ss->Parameter(uname, array_typedesc(TypeDesc::TypeFloat, value.
size()), value.
data());
878 ss->Parameter(uname, array_typedesc(TypeDesc::TypeInt, value.
size()), value.
data());
887 switch (socket.
type) {
889 typedesc = TypeDesc::TypeColor;
892 typedesc = TypeDesc::TypeVector;
895 typedesc = TypeDesc::TypePoint;
898 typedesc = TypeDesc::TypeNormal;
908 for (
size_t i = 0, j = 0; i < value.
size(); i++) {
909 fvalue[j++] = value[i].x;
910 fvalue[j++] = value[i].y;
911 fvalue[j++] = value[i].z;
914 ss->Parameter(uname, array_typedesc(typedesc, value.
size()), fvalue.data());
927 ss->Parameter(uname, array_typedesc(TypeDesc::TypeString, value.
size()), value.
data());
933 for (
size_t i = 0; i < value.
size(); i++) {
936 ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, fvalue.size()), fvalue.data());
952 ss->Parameter(name, TypeDesc::TypeFloat, &f);
957 ss->Parameter(name, TypeDesc::TypeColor, &f);
962 ss->Parameter(name, TypeDesc::TypePoint, &f);
967 ss->Parameter(name, TypeDesc::TypeNormal, &f);
972 ss->Parameter(name, TypeDesc::TypeVector, &f);
977 ss->Parameter(name, TypeDesc::TypeInt, &f);
982 ss->Parameter(name, TypeDesc::TypeString, &s);
987 const char *
str = s.c_str();
988 ss->Parameter(name, TypeDesc::TypeString, &
str);
995 ss->Parameter(name, TypeDesc::TypeMatrix, (
float *)&projection);
1000 TypeDesc
type = TypeDesc::TypeFloat;
1001 type.arraylen = arraylen;
1002 ss->Parameter(name,
type, f);
1010 for (
int i = 0; i < f.
size(); ++i) {
1011 table[i][0] = f[i].x;
1012 table[i][1] = f[i].y;
1013 table[i][2] = f[i].z;
1016 TypeDesc
type = TypeDesc::TypeColor;
1017 type.arraylen = table.size();
1018 ss->Parameter(name,
type, table.data());
1024 parameter(name, (
string(
"geom:") + s.c_str()).c_str());
1033 if (
node !=
NULL && dependencies.find(
node) == dependencies.end()) {
1035 if (!node_skip_input(
node, in))
1036 find_dependencies(dependencies, in);
1038 dependencies.insert(
node);
1042 void OSLCompiler::generate_nodes(
const ShaderNodeSet &nodes)
1051 if (done.find(
node) == done.end()) {
1052 bool inputs_done =
true;
1056 if (
input->link && done.find(
input->link->parent) == done.end())
1057 inputs_done =
false;
1060 node->compile(*
this);
1064 if (
node->has_surface_emission())
1066 if (
node->has_surface_transparent())
1070 if (
node->has_spatial_varying())
1072 if (
node->has_surface_bssrdf()) {
1074 if (
node->has_bssrdf_bump())
1077 if (
node->has_bump()) {
1082 if (
node->has_spatial_varying())
1090 }
while (!nodes_done);
1095 current_type =
type;
1097 OSL::ShaderGroupRef group = ss->ShaderGroupBegin(shader->
name.c_str());
1104 find_dependencies(dependencies,
output->input(
"Surface"));
1105 generate_nodes(dependencies);
1110 find_dependencies(dependencies,
output->input(
"Normal"));
1111 generate_nodes(dependencies);
1116 find_dependencies(dependencies,
output->input(
"Volume"));
1117 generate_nodes(dependencies);
1122 find_dependencies(dependencies,
output->input(
"Displacement"));
1123 generate_nodes(dependencies);
1129 ss->ShaderGroupEnd();
1140 bool has_bump = (shader->get_displacement_method() !=
DISPLACE_TRUE) &&
1141 output->input(
"Surface")->link &&
output->input(
"Displacement")->link;
1149 current_shader = shader;
1171 shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1176 shader->osl_surface_ref = OSL::ShaderGroupRef();
1177 shader->osl_surface_bump_ref = OSL::ShaderGroupRef();
1186 shader->osl_volume_ref = OSL::ShaderGroupRef();
1194 shader->osl_displacement_ref = OSL::ShaderGroupRef();
1198 og->surface_state.push_back(shader->osl_surface_ref);
1199 og->volume_state.push_back(shader->osl_volume_ref);
1200 og->displacement_state.push_back(shader->osl_displacement_ref);
1201 og->bump_state.push_back(shader->osl_surface_bump_ref);
1210 services->textures.insert(filename, handle);
1220 ustring filename(
string_printf(
"@svm%d", texture_shared_unique_id++).c_str());
1221 services->textures.insert(filename,
1229 ustring filename(
string_printf(
"@svm%d", texture_shared_unique_id++).c_str());
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum query
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value NORMAL
static AttributeStandard name_standard(const char *name)
Shader * get_shader(const Scene *scene)
static ColorSpaceProcessor * get_processor(ustring colorspace)
virtual void * get_cpu_osl_memory()
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(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)
static OSLNode * create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from=NULL)
void finalize(Scene *scene, bool do_bump=false, bool do_simplify=false, bool bump_in_object_space=false)
int get_shader_id(Shader *shader, bool smooth=false)
bool has_surface_spatial_varying
bool has_volume_attribute_dependency
NODE_DECLARE ShaderGraph * graph
bool has_integrator_dependency
bool has_surface_emission
bool has_surface_raytrace
bool has_surface_transparent
bool has_volume_spatial_varying
#define CCL_NAMESPACE_END
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
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
ccl_gpu_kernel_postfix ccl_global float int int int int float bool reset
clear internal cached data and reset random seed
@ SHADER_TYPE_DISPLACEMENT
@ KERNEL_FEATURE_NODE_RAYTRACE
static const VertexNature POINT
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value)
Allocate a new IDProperty of type IDP_INT, set its name and value.
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
set< ShaderNode *, ShaderNodeIDComparator > ShaderNodeSet
unsigned __int64 uint64_t
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
int reference_count() 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