ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / render / shader.cpp
index 3c94f2d..ac3303c 100644 (file)
@@ -48,16 +48,15 @@ bool ShaderManager::beckmann_table_ready = false;
 /* 2D slope distribution (alpha = 1.0) */
 static float beckmann_table_P22(const float slope_x, const float slope_y)
 {
-       return expf(-(slope_x*slope_x + slope_y*slope_y));
+  return expf(-(slope_x * slope_x + slope_y * slope_y));
 }
 
 /* maximal slope amplitude (range that contains 99.99% of the distribution) */
 static float beckmann_table_slope_max()
 {
-       return 6.0;
+  return 6.0;
 }
 
-
 /* MSVC 2015 needs this ugly hack to prevent a codegen bug on x86
  * see T50176 for details
  */
@@ -74,327 +73,331 @@ static float beckmann_table_slope_max()
  */
 static void beckmann_table_rows(float *table, int row_from, int row_to)
 {
-       /* allocate temporary data */
-       const int DATA_TMP_SIZE = 512;
-       vector<double> slope_x(DATA_TMP_SIZE);
-       vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
-
-       /* loop over incident directions */
-       for(int index_theta = row_from; index_theta < row_to; index_theta++) {
-               /* incident vector */
-               const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
-               const float sin_theta = safe_sqrtf(1.0f - cos_theta*cos_theta);
-
-               /* for a given incident vector
-                * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
-               slope_x[0] = (double)-beckmann_table_slope_max();
-               CDF_P22_omega_i[0] = 0;
-
-               for(MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
-                       /* slope_x */
-                       slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * index_slope_x/(DATA_TMP_SIZE - 1.0f));
-
-                       /* dot product with incident vector */
-                       float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x]*sin_theta + cos_theta);
-                       /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
-                       float P22_omega_i = 0.0f;
-
-                       for(int j = 0; j < 100; ++j) {
-                               float slope_y = -beckmann_table_slope_max() + 2.0f * beckmann_table_slope_max() * j * (1.0f/99.0f);
-                               P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
-                       }
-
-                       /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
-                       CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
-               }
-
-               /* renormalize CDF_P22_omega_i */
-               for(int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
-                       CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
-
-               /* loop over random number U1 */
-               int index_slope_x = 0;
-
-               for(int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
-                       const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
-
-                       /* inverse CDF_P22_omega_i, solve Eq.(11) */
-                       while(CDF_P22_omega_i[index_slope_x] <= U)
-                               ++index_slope_x;
-
-                       const double interp =
-                               (CDF_P22_omega_i[index_slope_x] - U) /
-                               (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
-
-                       /* store value */
-                       table[index_U + index_theta*BECKMANN_TABLE_SIZE] = (float)(
-                               interp * slope_x[index_slope_x - 1] +
-                                   (1.0 - interp) * slope_x[index_slope_x]);
-               }
-       }
+  /* allocate temporary data */
+  const int DATA_TMP_SIZE = 512;
+  vector<double> slope_x(DATA_TMP_SIZE);
+  vector<double> CDF_P22_omega_i(DATA_TMP_SIZE);
+
+  /* loop over incident directions */
+  for (int index_theta = row_from; index_theta < row_to; index_theta++) {
+    /* incident vector */
+    const float cos_theta = index_theta / (BECKMANN_TABLE_SIZE - 1.0f);
+    const float sin_theta = safe_sqrtf(1.0f - cos_theta * cos_theta);
+
+    /* for a given incident vector
+     * integrate P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+    slope_x[0] = (double)-beckmann_table_slope_max();
+    CDF_P22_omega_i[0] = 0;
+
+    for (MSVC_VOLATILE int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x) {
+      /* slope_x */
+      slope_x[index_slope_x] = (double)(-beckmann_table_slope_max() +
+                                        2.0f * beckmann_table_slope_max() * index_slope_x /
+                                            (DATA_TMP_SIZE - 1.0f));
+
+      /* dot product with incident vector */
+      float dot_product = fmaxf(0.0f, -(float)slope_x[index_slope_x] * sin_theta + cos_theta);
+      /* marginalize P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+      float P22_omega_i = 0.0f;
+
+      for (int j = 0; j < 100; ++j) {
+        float slope_y = -beckmann_table_slope_max() +
+                        2.0f * beckmann_table_slope_max() * j * (1.0f / 99.0f);
+        P22_omega_i += dot_product * beckmann_table_P22((float)slope_x[index_slope_x], slope_y);
+      }
+
+      /* CDF of P22_{omega_i}(x_slope, 1, 1), Eq. (10) */
+      CDF_P22_omega_i[index_slope_x] = CDF_P22_omega_i[index_slope_x - 1] + (double)P22_omega_i;
+    }
+
+    /* renormalize CDF_P22_omega_i */
+    for (int index_slope_x = 1; index_slope_x < DATA_TMP_SIZE; ++index_slope_x)
+      CDF_P22_omega_i[index_slope_x] /= CDF_P22_omega_i[DATA_TMP_SIZE - 1];
+
+    /* loop over random number U1 */
+    int index_slope_x = 0;
+
+    for (int index_U = 0; index_U < BECKMANN_TABLE_SIZE; ++index_U) {
+      const double U = 0.0000001 + 0.9999998 * index_U / (double)(BECKMANN_TABLE_SIZE - 1);
+
+      /* inverse CDF_P22_omega_i, solve Eq.(11) */
+      while (CDF_P22_omega_i[index_slope_x] <= U)
+        ++index_slope_x;
+
+      const double interp = (CDF_P22_omega_i[index_slope_x] - U) /
+                            (CDF_P22_omega_i[index_slope_x] - CDF_P22_omega_i[index_slope_x - 1]);
+
+      /* store value */
+      table[index_U + index_theta * BECKMANN_TABLE_SIZE] =
+          (float)(interp * slope_x[index_slope_x - 1] + (1.0 - interp) * slope_x[index_slope_x]);
+    }
+  }
 }
 
 #undef MSVC_VOLATILE
 
-static void beckmann_table_build(vector<float>table)
+static void beckmann_table_build(vector<float> &table)
 {
-       table.resize(BECKMANN_TABLE_SIZE*BECKMANN_TABLE_SIZE);
+  table.resize(BECKMANN_TABLE_SIZE * BECKMANN_TABLE_SIZE);
 
-       /* multithreaded build */
-       TaskPool pool;
+  /* multithreaded build */
+  TaskPool pool;
 
-       for(int i = 0; i < BECKMANN_TABLE_SIZE; i+=8)
-               pool.push(function_bind(&beckmann_table_rows, &table[0], i, i+8));
+  for (int i = 0; i < BECKMANN_TABLE_SIZE; i += 8)
+    pool.push(function_bind(&beckmann_table_rows, &table[0], i, i + 8));
 
-       pool.wait_work();
+  pool.wait_work();
 }
 
 /* Shader */
 
 NODE_DEFINE(Shader)
 {
-       NodeType* type = NodeType::add("shader", create);
-
-       SOCKET_BOOLEAN(use_mis, "Use MIS", true);
-       SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
-       SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
-
-       static NodeEnum volume_sampling_method_enum;
-       volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
-       volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
-       volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
-       SOCKET_ENUM(volume_sampling_method, "Volume Sampling Method", volume_sampling_method_enum, VOLUME_SAMPLING_DISTANCE);
-
-       static NodeEnum volume_interpolation_method_enum;
-       volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
-       volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
-       SOCKET_ENUM(volume_interpolation_method, "Volume Interpolation Method", volume_interpolation_method_enum, VOLUME_INTERPOLATION_LINEAR);
-
-       static NodeEnum displacement_method_enum;
-       displacement_method_enum.insert("bump", DISPLACE_BUMP);
-       displacement_method_enum.insert("true", DISPLACE_TRUE);
-       displacement_method_enum.insert("both", DISPLACE_BOTH);
-       SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
-
-       return type;
+  NodeType *type = NodeType::add("shader", create);
+
+  SOCKET_BOOLEAN(use_mis, "Use MIS", true);
+  SOCKET_BOOLEAN(use_transparent_shadow, "Use Transparent Shadow", true);
+  SOCKET_BOOLEAN(heterogeneous_volume, "Heterogeneous Volume", true);
+
+  static NodeEnum volume_sampling_method_enum;
+  volume_sampling_method_enum.insert("distance", VOLUME_SAMPLING_DISTANCE);
+  volume_sampling_method_enum.insert("equiangular", VOLUME_SAMPLING_EQUIANGULAR);
+  volume_sampling_method_enum.insert("multiple_importance", VOLUME_SAMPLING_MULTIPLE_IMPORTANCE);
+  SOCKET_ENUM(volume_sampling_method,
+              "Volume Sampling Method",
+              volume_sampling_method_enum,
+              VOLUME_SAMPLING_DISTANCE);
+
+  static NodeEnum volume_interpolation_method_enum;
+  volume_interpolation_method_enum.insert("linear", VOLUME_INTERPOLATION_LINEAR);
+  volume_interpolation_method_enum.insert("cubic", VOLUME_INTERPOLATION_CUBIC);
+  SOCKET_ENUM(volume_interpolation_method,
+              "Volume Interpolation Method",
+              volume_interpolation_method_enum,
+              VOLUME_INTERPOLATION_LINEAR);
+
+  static NodeEnum displacement_method_enum;
+  displacement_method_enum.insert("bump", DISPLACE_BUMP);
+  displacement_method_enum.insert("true", DISPLACE_TRUE);
+  displacement_method_enum.insert("both", DISPLACE_BOTH);
+  SOCKET_ENUM(displacement_method, "Displacement Method", displacement_method_enum, DISPLACE_BUMP);
+
+  return type;
 }
 
-Shader::Shader()
-: Node(node_type)
+Shader::Shader() : Node(node_type)
 {
-       pass_id = 0;
-
-       graph = NULL;
-
-       has_surface = false;
-       has_surface_transparent = false;
-       has_surface_emission = false;
-       has_surface_bssrdf = false;
-       has_volume = false;
-       has_displacement = false;
-       has_bump = false;
-       has_bssrdf_bump = false;
-       has_surface_spatial_varying = false;
-       has_volume_spatial_varying = false;
-       has_object_dependency = false;
-       has_attribute_dependency = false;
-       has_integrator_dependency = false;
-       has_volume_connected = false;
-
-       displacement_method = DISPLACE_BUMP;
-
-       id = -1;
-       used = false;
-
-       need_update = true;
-       need_update_mesh = true;
-       need_sync_object = false;
+  pass_id = 0;
+
+  graph = NULL;
+
+  has_surface = false;
+  has_surface_transparent = false;
+  has_surface_emission = false;
+  has_surface_bssrdf = false;
+  has_volume = false;
+  has_displacement = false;
+  has_bump = false;
+  has_bssrdf_bump = false;
+  has_surface_spatial_varying = false;
+  has_volume_spatial_varying = false;
+  has_object_dependency = false;
+  has_attribute_dependency = false;
+  has_integrator_dependency = false;
+  has_volume_connected = false;
+
+  displacement_method = DISPLACE_BUMP;
+
+  id = -1;
+  used = false;
+
+  need_update = true;
+  need_update_mesh = true;
+  need_sync_object = false;
 }
 
 Shader::~Shader()
 {
-       delete graph;
+  delete graph;
 }
 
 bool Shader::is_constant_emission(float3 *emission)
 {
-       ShaderInput *surf = graph->output()->input("Surface");
+  ShaderInput *surf = graph->output()->input("Surface");
 
-       if(surf->link == NULL) {
-               return false;
-       }
+  if (surf->link == NULL) {
+    return false;
+  }
 
-       if(surf->link->parent->type == EmissionNode::node_type) {
-               EmissionNode *node = (EmissionNode*) surf->link->parent;
+  if (surf->link->parent->type == EmissionNode::node_type) {
+    EmissionNode *node = (EmissionNode *)surf->link->parent;
 
-               assert(node->input("Color"));
-               assert(node->input("Strength"));
+    assert(node->input("Color"));
+    assert(node->input("Strength"));
 
-               if(node->input("Color")->link || node->input("Strength")->link) {
-                       return false;
-               }
+    if (node->input("Color")->link || node->input("Strength")->link) {
+      return false;
+    }
 
-               *emission = node->color*node->strength;
-       }
-       else if(surf->link->parent->type == BackgroundNode::node_type) {
-               BackgroundNode *node = (BackgroundNode*) surf->link->parent;
+    *emission = node->color * node->strength;
+  }
+  else if (surf->link->parent->type == BackgroundNode::node_type) {
+    BackgroundNode *node = (BackgroundNode *)surf->link->parent;
 
-               assert(node->input("Color"));
-               assert(node->input("Strength"));
+    assert(node->input("Color"));
+    assert(node->input("Strength"));
 
-               if(node->input("Color")->link || node->input("Strength")->link) {
-                       return false;
-               }
+    if (node->input("Color")->link || node->input("Strength")->link) {
+      return false;
+    }
 
-               *emission = node->color*node->strength;
-       }
-       else {
-               return false;
-       }
+    *emission = node->color * node->strength;
+  }
+  else {
+    return false;
+  }
 
-       return true;
+  return true;
 }
 
 void Shader::set_graph(ShaderGraph *graph_)
 {
-       /* do this here already so that we can detect if mesh or object attributes
-        * are needed, since the node attribute callbacks check if their sockets
-        * are connected but proxy nodes should not count */
-       if(graph_) {
-               graph_->remove_proxy_nodes();
-
-               if(displacement_method != DISPLACE_BUMP) {
-                       graph_->compute_displacement_hash();
-               }
-       }
-
-       /* update geometry if displacement changed */
-       if(displacement_method != DISPLACE_BUMP) {
-               const char *old_hash = (graph)? graph->displacement_hash.c_str() : "";
-               const char *new_hash = (graph_)? graph_->displacement_hash.c_str() : "";
-
-               if(strcmp(old_hash, new_hash) != 0) {
-                       need_update_mesh = true;
-               }
-       }
-
-       /* assign graph */
-       delete graph;
-       graph = graph_;
-
-       /* Store info here before graph optimization to make sure that
-        * nodes that get optimized away still count. */
-       has_volume_connected = (graph->output()->input("Volume")->link != NULL);
+  /* do this here already so that we can detect if mesh or object attributes
+   * are needed, since the node attribute callbacks check if their sockets
+   * are connected but proxy nodes should not count */
+  if (graph_) {
+    graph_->remove_proxy_nodes();
+
+    if (displacement_method != DISPLACE_BUMP) {
+      graph_->compute_displacement_hash();
+    }
+  }
+
+  /* update geometry if displacement changed */
+  if (displacement_method != DISPLACE_BUMP) {
+    const char *old_hash = (graph) ? graph->displacement_hash.c_str() : "";
+    const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : "";
+
+    if (strcmp(old_hash, new_hash) != 0) {
+      need_update_mesh = true;
+    }
+  }
+
+  /* assign graph */
+  delete graph;
+  graph = graph_;
+
+  /* Store info here before graph optimization to make sure that
+   * nodes that get optimized away still count. */
+  has_volume_connected = (graph->output()->input("Volume")->link != NULL);
 }
 
 void Shader::tag_update(Scene *scene)
 {
-       /* update tag */
-       need_update = true;
-       scene->shader_manager->need_update = true;
-
-       /* if the shader previously was emissive, update light distribution,
-        * if the new shader is emissive, a light manager update tag will be
-        * done in the shader manager device update. */
-       if(use_mis && has_surface_emission)
-               scene->light_manager->need_update = true;
-
-       /* Special handle of background MIS light for now: for some reason it
-        * has use_mis set to false. We are quite close to release now, so
-        * better to be safe.
-        */
-       if(this == scene->default_background &&
-          scene->light_manager->has_background_light(scene))
-       {
-               scene->light_manager->need_update = true;
-       }
-
-       /* quick detection of which kind of shaders we have to avoid loading
-        * e.g. surface attributes when there is only a volume shader. this could
-        * be more fine grained but it's better than nothing */
-       OutputNode *output = graph->output();
-       bool prev_has_volume = has_volume;
-       has_surface = has_surface || output->input("Surface")->link;
-       has_volume = has_volume || output->input("Volume")->link;
-       has_displacement = has_displacement || output->input("Displacement")->link;
-
-       /* get requested attributes. this could be optimized by pruning unused
-        * nodes here already, but that's the job of the shader manager currently,
-        * and may not be so great for interactive rendering where you temporarily
-        * disconnect a node */
-
-       AttributeRequestSet prev_attributes = attributes;
-
-       attributes.clear();
-       foreach(ShaderNode *node, graph->nodes)
-               node->attributes(this, &attributes);
-
-       if(has_displacement && displacement_method == DISPLACE_BOTH) {
-               attributes.add(ATTR_STD_POSITION_UNDISPLACED);
-       }
-
-       /* compare if the attributes changed, mesh manager will check
-        * need_update_mesh, update the relevant meshes and clear it. */
-       if(attributes.modified(prev_attributes)) {
-               need_update_mesh = true;
-               scene->mesh_manager->need_update = true;
-       }
-
-       if(has_volume != prev_has_volume) {
-               scene->mesh_manager->need_flags_update = true;
-               scene->object_manager->need_flags_update = true;
-       }
+  /* update tag */
+  need_update = true;
+  scene->shader_manager->need_update = true;
+
+  /* if the shader previously was emissive, update light distribution,
+   * if the new shader is emissive, a light manager update tag will be
+   * done in the shader manager device update. */
+  if (use_mis && has_surface_emission)
+    scene->light_manager->need_update = true;
+
+  /* Special handle of background MIS light for now: for some reason it
+   * has use_mis set to false. We are quite close to release now, so
+   * better to be safe.
+   */
+  if (this == scene->default_background && scene->light_manager->has_background_light(scene)) {
+    scene->light_manager->need_update = true;
+  }
+
+  /* quick detection of which kind of shaders we have to avoid loading
+   * e.g. surface attributes when there is only a volume shader. this could
+   * be more fine grained but it's better than nothing */
+  OutputNode *output = graph->output();
+  bool prev_has_volume = has_volume;
+  has_surface = has_surface || output->input("Surface")->link;
+  has_volume = has_volume || output->input("Volume")->link;
+  has_displacement = has_displacement || output->input("Displacement")->link;
+
+  /* get requested attributes. this could be optimized by pruning unused
+   * nodes here already, but that's the job of the shader manager currently,
+   * and may not be so great for interactive rendering where you temporarily
+   * disconnect a node */
+
+  AttributeRequestSet prev_attributes = attributes;
+
+  attributes.clear();
+  foreach (ShaderNode *node, graph->nodes)
+    node->attributes(this, &attributes);
+
+  if (has_displacement && displacement_method == DISPLACE_BOTH) {
+    attributes.add(ATTR_STD_POSITION_UNDISPLACED);
+  }
+
+  /* compare if the attributes changed, mesh manager will check
+   * need_update_mesh, update the relevant meshes and clear it. */
+  if (attributes.modified(prev_attributes)) {
+    need_update_mesh = true;
+    scene->mesh_manager->need_update = true;
+  }
+
+  if (has_volume != prev_has_volume) {
+    scene->mesh_manager->need_flags_update = true;
+    scene->object_manager->need_flags_update = true;
+  }
 }
 
 void Shader::tag_used(Scene *scene)
 {
-       /* if an unused shader suddenly gets used somewhere, it needs to be
-        * recompiled because it was skipped for compilation before */
-       if(!used) {
-               need_update = true;
-               scene->shader_manager->need_update = true;
-       }
+  /* if an unused shader suddenly gets used somewhere, it needs to be
+   * recompiled because it was skipped for compilation before */
+  if (!used) {
+    need_update = true;
+    scene->shader_manager->need_update = true;
+  }
 }
 
 /* Shader Manager */
 
 ShaderManager::ShaderManager()
 {
-       need_update = true;
-       beckmann_table_offset = TABLE_OFFSET_INVALID;
+  need_update = true;
+  beckmann_table_offset = TABLE_OFFSET_INVALID;
 
-       xyz_to_r = make_float3( 3.2404542f, -1.5371385f, -0.4985314f);
-       xyz_to_g = make_float3(-0.9692660f,  1.8760108f,  0.0415560f);
-       xyz_to_b = make_float3( 0.0556434f, -0.2040259f,  1.0572252f);
-       rgb_to_y = make_float3( 0.2126729f,  0.7151522f,  0.0721750f);
+  xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
+  xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
+  xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
+  rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
 
 #ifdef WITH_OCIO
-       OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
-       if(config) {
-               if(config->hasRole("XYZ") && config->hasRole("scene_linear")) {
-                       OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
-                       OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
-                       if(to_rgb_processor && to_xyz_processor) {
-                               float r[] = {1.0f, 0.0f, 0.0f};
-                               float g[] = {0.0f, 1.0f, 0.0f};
-                               float b[] = {0.0f, 0.0f, 1.0f};
-                               to_xyz_processor->applyRGB(r);
-                               to_xyz_processor->applyRGB(g);
-                               to_xyz_processor->applyRGB(b);
-                               rgb_to_y = make_float3(r[1], g[1], b[1]);
-
-                               float x[] = {1.0f, 0.0f, 0.0f};
-                               float y[] = {0.0f, 1.0f, 0.0f};
-                               float z[] = {0.0f, 0.0f, 1.0f};
-                               to_rgb_processor->applyRGB(x);
-                               to_rgb_processor->applyRGB(y);
-                               to_rgb_processor->applyRGB(z);
-                               xyz_to_r = make_float3(x[0], y[0], z[0]);
-                               xyz_to_g = make_float3(x[1], y[1], z[1]);
-                               xyz_to_b = make_float3(x[2], y[2], z[2]);
-                       }
-               }
-       }
+  OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
+  if (config) {
+    if (config->hasRole("XYZ") && config->hasRole("scene_linear")) {
+      OCIO::ConstProcessorRcPtr to_rgb_processor = config->getProcessor("XYZ", "scene_linear");
+      OCIO::ConstProcessorRcPtr to_xyz_processor = config->getProcessor("scene_linear", "XYZ");
+      if (to_rgb_processor && to_xyz_processor) {
+        float r[] = {1.0f, 0.0f, 0.0f};
+        float g[] = {0.0f, 1.0f, 0.0f};
+        float b[] = {0.0f, 0.0f, 1.0f};
+        to_xyz_processor->applyRGB(r);
+        to_xyz_processor->applyRGB(g);
+        to_xyz_processor->applyRGB(b);
+        rgb_to_y = make_float3(r[1], g[1], b[1]);
+
+        float x[] = {1.0f, 0.0f, 0.0f};
+        float y[] = {0.0f, 1.0f, 0.0f};
+        float z[] = {0.0f, 0.0f, 1.0f};
+        to_rgb_processor->applyRGB(x);
+        to_rgb_processor->applyRGB(y);
+        to_rgb_processor->applyRGB(z);
+        xyz_to_r = make_float3(x[0], y[0], z[0]);
+        xyz_to_g = make_float3(x[1], y[1], z[1]);
+        xyz_to_b = make_float3(x[2], y[2], z[2]);
+      }
+    }
+  }
 #endif
 }
 
@@ -404,337 +407,337 @@ ShaderManager::~ShaderManager()
 
 ShaderManager *ShaderManager::create(Scene *scene, int shadingsystem)
 {
-       ShaderManager *manager;
+  ShaderManager *manager;
 
-       (void) shadingsystem;  /* Ignored when built without OSL. */
+  (void)shadingsystem; /* Ignored when built without OSL. */
 
 #ifdef WITH_OSL
-       if(shadingsystem == SHADINGSYSTEM_OSL) {
-               manager = new OSLShaderManager();
-       }
-       else
+  if (shadingsystem == SHADINGSYSTEM_OSL) {
+    manager = new OSLShaderManager();
+  }
+  else
 #endif
-       {
-               manager = new SVMShaderManager();
-       }
+  {
+    manager = new SVMShaderManager();
+  }
 
-       add_default(scene);
+  add_default(scene);
 
-       return manager;
+  return manager;
 }
 
 uint ShaderManager::get_attribute_id(ustring name)
 {
-       thread_scoped_spin_lock lock(attribute_lock_);
+  thread_scoped_spin_lock lock(attribute_lock_);
 
-       /* get a unique id for each name, for SVM attribute lookup */
-       AttributeIDMap::iterator it = unique_attribute_id.find(name);
+  /* get a unique id for each name, for SVM attribute lookup */
+  AttributeIDMap::iterator it = unique_attribute_id.find(name);
 
-       if(it != unique_attribute_id.end())
-               return it->second;
+  if (it != unique_attribute_id.end())
+    return it->second;
 
-       uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
-       unique_attribute_id[name] = id;
-       return id;
+  uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size();
+  unique_attribute_id[name] = id;
+  return id;
 }
 
 uint ShaderManager::get_attribute_id(AttributeStandard std)
 {
-       return (uint)std;
+  return (uint)std;
 }
 
 int ShaderManager::get_shader_id(Shader *shader, bool smooth)
 {
-       /* get a shader id to pass to the kernel */
-       int id = shader->id;
+  /* get a shader id to pass to the kernel */
+  int id = shader->id;
 
-       /* smooth flag */
-       if(smooth)
-               id |= SHADER_SMOOTH_NORMAL;
+  /* smooth flag */
+  if (smooth)
+    id |= SHADER_SMOOTH_NORMAL;
 
-       /* default flags */
-       id |= SHADER_CAST_SHADOW|SHADER_AREA_LIGHT;
+  /* default flags */
+  id |= SHADER_CAST_SHADOW | SHADER_AREA_LIGHT;
 
-       return id;
+  return id;
 }
 
 void ShaderManager::device_update_shaders_used(Scene *scene)
 {
-       /* figure out which shaders are in use, so SVM/OSL can skip compiling them
-        * for speed and avoid loading image textures into memory */
-       uint id = 0;
-       foreach(Shader *shader, scene->shaders) {
-               shader->used = false;
-               shader->id = id++;
-       }
-
-       scene->default_surface->used = true;
-       scene->default_light->used = true;
-       scene->default_background->used = true;
-       scene->default_empty->used = true;
-
-       if(scene->background->shader)
-               scene->background->shader->used = true;
-
-       foreach(Mesh *mesh, scene->meshes)
-               foreach(Shader *shader, mesh->used_shaders)
-                       shader->used = true;
-
-       foreach(Light *light, scene->lights)
-               if(light->shader)
-                       light->shader->used = true;
+  /* figure out which shaders are in use, so SVM/OSL can skip compiling them
+   * for speed and avoid loading image textures into memory */
+  uint id = 0;
+  foreach (Shader *shader, scene->shaders) {
+    shader->used = false;
+    shader->id = id++;
+  }
+
+  scene->default_surface->used = true;
+  scene->default_light->used = true;
+  scene->default_background->used = true;
+  scene->default_empty->used = true;
+
+  if (scene->background->shader)
+    scene->background->shader->used = true;
+
+  foreach (Mesh *mesh, scene->meshes)
+    foreach (Shader *shader, mesh->used_shaders)
+      shader->used = true;
+
+  foreach (Light *light, scene->lights)
+    if (light->shader)
+      light->shader->used = true;
 }
 
 void ShaderManager::device_update_common(Device *device,
                                          DeviceScene *dscene,
                                          Scene *scene,
-                                         Progress& /*progress*/)
+                                         Progress & /*progress*/)
 {
-       dscene->shaders.free();
-
-       if(scene->shaders.size() == 0)
-               return;
-
-       KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
-       bool has_volumes = false;
-       bool has_transparent_shadow = false;
-
-       foreach(Shader *shader, scene->shaders) {
-               uint flag = 0;
-
-               if(shader->use_mis)
-                       flag |= SD_USE_MIS;
-               if(shader->has_surface_transparent && shader->use_transparent_shadow)
-                       flag |= SD_HAS_TRANSPARENT_SHADOW;
-               if(shader->has_volume) {
-                       flag |= SD_HAS_VOLUME;
-                       has_volumes = true;
-
-                       /* todo: this could check more fine grained, to skip useless volumes
-                        * enclosed inside an opaque bsdf.
-                        */
-                       flag |= SD_HAS_TRANSPARENT_SHADOW;
-               }
-               /* in this case we can assume transparent surface */
-               if(shader->has_volume_connected && !shader->has_surface)
-                       flag |= SD_HAS_ONLY_VOLUME;
-               if(shader->heterogeneous_volume && shader->has_volume_spatial_varying)
-                       flag |= SD_HETEROGENEOUS_VOLUME;
-               if(shader->has_attribute_dependency)
-                       flag |= SD_NEED_ATTRIBUTES;
-               if(shader->has_bssrdf_bump)
-                       flag |= SD_HAS_BSSRDF_BUMP;
-               if(device->info.has_volume_decoupled) {
-                       if(shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
-                               flag |= SD_VOLUME_EQUIANGULAR;
-                       if(shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
-                               flag |= SD_VOLUME_MIS;
-               }
-               if(shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
-                       flag |= SD_VOLUME_CUBIC;
-               if(shader->has_bump)
-                       flag |= SD_HAS_BUMP;
-               if(shader->displacement_method != DISPLACE_BUMP)
-                       flag |= SD_HAS_DISPLACEMENT;
-
-               /* constant emission check */
-               float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
-               if(shader->is_constant_emission(&constant_emission))
-                       flag |= SD_HAS_CONSTANT_EMISSION;
-
-               uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
-
-               /* regular shader */
-               kshader->flags = flag;
-               kshader->pass_id = shader->pass_id;
-               kshader->constant_emission[0] = constant_emission.x;
-               kshader->constant_emission[1] = constant_emission.y;
-               kshader->constant_emission[2] = constant_emission.z;
-               kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
-               kshader++;
-
-               has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
-       }
-
-       dscene->shaders.copy_to_device();
-
-       /* lookup tables */
-       KernelTables *ktables = &dscene->data.tables;
-
-       /* beckmann lookup table */
-       if(beckmann_table_offset == TABLE_OFFSET_INVALID) {
-               if(!beckmann_table_ready) {
-                       thread_scoped_lock lock(lookup_table_mutex);
-                       if(!beckmann_table_ready) {
-                               beckmann_table_build(beckmann_table);
-                               beckmann_table_ready = true;
-                       }
-               }
-               beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
-       }
-       ktables->beckmann_offset = (int)beckmann_table_offset;
-
-       /* integrator */
-       KernelIntegrator *kintegrator = &dscene->data.integrator;
-       kintegrator->use_volumes = has_volumes;
-       /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
-       kintegrator->transparent_shadows = has_transparent_shadow;
-
-       /* film */
-       KernelFilm *kfilm = &dscene->data.film;
-       /* color space, needs to be here because e.g. displacement shaders could depend on it */
-       kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
-       kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
-       kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
-       kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
+  dscene->shaders.free();
+
+  if (scene->shaders.size() == 0)
+    return;
+
+  KernelShader *kshader = dscene->shaders.alloc(scene->shaders.size());
+  bool has_volumes = false;
+  bool has_transparent_shadow = false;
+
+  foreach (Shader *shader, scene->shaders) {
+    uint flag = 0;
+
+    if (shader->use_mis)
+      flag |= SD_USE_MIS;
+    if (shader->has_surface_transparent && shader->use_transparent_shadow)
+      flag |= SD_HAS_TRANSPARENT_SHADOW;
+    if (shader->has_volume) {
+      flag |= SD_HAS_VOLUME;
+      has_volumes = true;
+
+      /* todo: this could check more fine grained, to skip useless volumes
+       * enclosed inside an opaque bsdf.
+       */
+      flag |= SD_HAS_TRANSPARENT_SHADOW;
+    }
+    /* in this case we can assume transparent surface */
+    if (shader->has_volume_connected && !shader->has_surface)
+      flag |= SD_HAS_ONLY_VOLUME;
+    if (shader->heterogeneous_volume && shader->has_volume_spatial_varying)
+      flag |= SD_HETEROGENEOUS_VOLUME;
+    if (shader->has_attribute_dependency)
+      flag |= SD_NEED_ATTRIBUTES;
+    if (shader->has_bssrdf_bump)
+      flag |= SD_HAS_BSSRDF_BUMP;
+    if (device->info.has_volume_decoupled) {
+      if (shader->volume_sampling_method == VOLUME_SAMPLING_EQUIANGULAR)
+        flag |= SD_VOLUME_EQUIANGULAR;
+      if (shader->volume_sampling_method == VOLUME_SAMPLING_MULTIPLE_IMPORTANCE)
+        flag |= SD_VOLUME_MIS;
+    }
+    if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC)
+      flag |= SD_VOLUME_CUBIC;
+    if (shader->has_bump)
+      flag |= SD_HAS_BUMP;
+    if (shader->displacement_method != DISPLACE_BUMP)
+      flag |= SD_HAS_DISPLACEMENT;
+
+    /* constant emission check */
+    float3 constant_emission = make_float3(0.0f, 0.0f, 0.0f);
+    if (shader->is_constant_emission(&constant_emission))
+      flag |= SD_HAS_CONSTANT_EMISSION;
+
+    uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+
+    /* regular shader */
+    kshader->flags = flag;
+    kshader->pass_id = shader->pass_id;
+    kshader->constant_emission[0] = constant_emission.x;
+    kshader->constant_emission[1] = constant_emission.y;
+    kshader->constant_emission[2] = constant_emission.z;
+    kshader->cryptomatte_id = util_hash_to_float(cryptomatte_id);
+    kshader++;
+
+    has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0;
+  }
+
+  dscene->shaders.copy_to_device();
+
+  /* lookup tables */
+  KernelTables *ktables = &dscene->data.tables;
+
+  /* beckmann lookup table */
+  if (beckmann_table_offset == TABLE_OFFSET_INVALID) {
+    if (!beckmann_table_ready) {
+      thread_scoped_lock lock(lookup_table_mutex);
+      if (!beckmann_table_ready) {
+        beckmann_table_build(beckmann_table);
+        beckmann_table_ready = true;
+      }
+    }
+    beckmann_table_offset = scene->lookup_tables->add_table(dscene, beckmann_table);
+  }
+  ktables->beckmann_offset = (int)beckmann_table_offset;
+
+  /* integrator */
+  KernelIntegrator *kintegrator = &dscene->data.integrator;
+  kintegrator->use_volumes = has_volumes;
+  /* TODO(sergey): De-duplicate with flags set in integrator.cpp. */
+  kintegrator->transparent_shadows = has_transparent_shadow;
+
+  /* film */
+  KernelFilm *kfilm = &dscene->data.film;
+  /* color space, needs to be here because e.g. displacement shaders could depend on it */
+  kfilm->xyz_to_r = float3_to_float4(xyz_to_r);
+  kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
+  kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
+  kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
 }
 
 void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
 {
-       scene->lookup_tables->remove_table(&beckmann_table_offset);
+  scene->lookup_tables->remove_table(&beckmann_table_offset);
 
-       dscene->shaders.free();
+  dscene->shaders.free();
 }
 
 void ShaderManager::add_default(Scene *scene)
 {
-       /* default surface */
-       {
-               ShaderGraph *graph = new ShaderGraph();
-
-               DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
-               diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
-               graph->add(diffuse);
-
-               graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
-
-               Shader *shader = new Shader();
-               shader->name = "default_surface";
-               shader->graph = graph;
-               scene->shaders.push_back(shader);
-               scene->default_surface = shader;
-       }
-
-       /* default light */
-       {
-               ShaderGraph *graph = new ShaderGraph();
-
-               EmissionNode *emission = new EmissionNode();
-               emission->color = make_float3(0.8f, 0.8f, 0.8f);
-               emission->strength = 0.0f;
-               graph->add(emission);
-
-               graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
-
-               Shader *shader = new Shader();
-               shader->name = "default_light";
-               shader->graph = graph;
-               scene->shaders.push_back(shader);
-               scene->default_light = shader;
-       }
-
-       /* default background */
-       {
-               ShaderGraph *graph = new ShaderGraph();
-
-               Shader *shader = new Shader();
-               shader->name = "default_background";
-               shader->graph = graph;
-               scene->shaders.push_back(shader);
-               scene->default_background = shader;
-       }
-
-       /* default empty */
-       {
-               ShaderGraph *graph = new ShaderGraph();
-
-               Shader *shader = new Shader();
-               shader->name = "default_empty";
-               shader->graph = graph;
-               scene->shaders.push_back(shader);
-               scene->default_empty = shader;
-       }
+  /* default surface */
+  {
+    ShaderGraph *graph = new ShaderGraph();
+
+    DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+    diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+    graph->add(diffuse);
+
+    graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
+
+    Shader *shader = new Shader();
+    shader->name = "default_surface";
+    shader->graph = graph;
+    scene->shaders.push_back(shader);
+    scene->default_surface = shader;
+  }
+
+  /* default light */
+  {
+    ShaderGraph *graph = new ShaderGraph();
+
+    EmissionNode *emission = new EmissionNode();
+    emission->color = make_float3(0.8f, 0.8f, 0.8f);
+    emission->strength = 0.0f;
+    graph->add(emission);
+
+    graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
+
+    Shader *shader = new Shader();
+    shader->name = "default_light";
+    shader->graph = graph;
+    scene->shaders.push_back(shader);
+    scene->default_light = shader;
+  }
+
+  /* default background */
+  {
+    ShaderGraph *graph = new ShaderGraph();
+
+    Shader *shader = new Shader();
+    shader->name = "default_background";
+    shader->graph = graph;
+    scene->shaders.push_back(shader);
+    scene->default_background = shader;
+  }
+
+  /* default empty */
+  {
+    ShaderGraph *graph = new ShaderGraph();
+
+    Shader *shader = new Shader();
+    shader->name = "default_empty";
+    shader->graph = graph;
+    scene->shaders.push_back(shader);
+    scene->default_empty = shader;
+  }
 }
 
 void ShaderManager::get_requested_graph_features(ShaderGraph *graph,
                                                  DeviceRequestedFeatures *requested_features)
 {
-       foreach(ShaderNode *node, graph->nodes) {
-               requested_features->max_nodes_group = max(requested_features->max_nodes_group,
-                                                         node->get_group());
-               requested_features->nodes_features |= node->get_feature();
-               if(node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
-                       BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode*>(node);
-                       if(CLOSURE_IS_VOLUME(bsdf_node->closure)) {
-                               requested_features->nodes_features |= NODE_FEATURE_VOLUME;
-                       }
-                       else if(CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
-                               requested_features->use_principled = true;
-                       }
-               }
-               if(node->has_surface_bssrdf()) {
-                       requested_features->use_subsurface = true;
-               }
-               if(node->has_surface_transparent()) {
-                       requested_features->use_transparent = true;
-               }
-               if(node->has_raytrace()) {
-                       requested_features->use_shader_raytrace = true;
-               }
-       }
+  foreach (ShaderNode *node, graph->nodes) {
+    requested_features->max_nodes_group = max(requested_features->max_nodes_group,
+                                              node->get_group());
+    requested_features->nodes_features |= node->get_feature();
+    if (node->special_type == SHADER_SPECIAL_TYPE_CLOSURE) {
+      BsdfBaseNode *bsdf_node = static_cast<BsdfBaseNode *>(node);
+      if (CLOSURE_IS_VOLUME(bsdf_node->closure)) {
+        requested_features->nodes_features |= NODE_FEATURE_VOLUME;
+      }
+      else if (CLOSURE_IS_PRINCIPLED(bsdf_node->closure)) {
+        requested_features->use_principled = true;
+      }
+    }
+    if (node->has_surface_bssrdf()) {
+      requested_features->use_subsurface = true;
+    }
+    if (node->has_surface_transparent()) {
+      requested_features->use_transparent = true;
+    }
+    if (node->has_raytrace()) {
+      requested_features->use_shader_raytrace = true;
+    }
+  }
 }
 
 void ShaderManager::get_requested_features(Scene *scene,
                                            DeviceRequestedFeatures *requested_features)
 {
-       requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
-       requested_features->nodes_features = 0;
-       for(int i = 0; i < scene->shaders.size(); i++) {
-               Shader *shader = scene->shaders[i];
-               /* Gather requested features from all the nodes from the graph nodes. */
-               get_requested_graph_features(shader->graph, requested_features);
-               ShaderNode *output_node = shader->graph->output();
-               if(output_node->input("Displacement")->link != NULL) {
-                       requested_features->nodes_features |= NODE_FEATURE_BUMP;
-                       if(shader->displacement_method == DISPLACE_BOTH) {
-                               requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
-                       }
-               }
-               /* On top of volume nodes, also check if we need volume sampling because
-                * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
-               if(shader->has_volume)
-                       requested_features->use_volume |= true;
-       }
+  requested_features->max_nodes_group = NODE_GROUP_LEVEL_0;
+  requested_features->nodes_features = 0;
+  for (int i = 0; i < scene->shaders.size(); i++) {
+    Shader *shader = scene->shaders[i];
+    /* Gather requested features from all the nodes from the graph nodes. */
+    get_requested_graph_features(shader->graph, requested_features);
+    ShaderNode *output_node = shader->graph->output();
+    if (output_node->input("Displacement")->link != NULL) {
+      requested_features->nodes_features |= NODE_FEATURE_BUMP;
+      if (shader->displacement_method == DISPLACE_BOTH) {
+        requested_features->nodes_features |= NODE_FEATURE_BUMP_STATE;
+      }
+    }
+    /* On top of volume nodes, also check if we need volume sampling because
+     * e.g. an Emission node would slip through the NODE_FEATURE_VOLUME check */
+    if (shader->has_volume)
+      requested_features->use_volume |= true;
+  }
 }
 
 void ShaderManager::free_memory()
 {
-       beckmann_table.free_memory();
+  beckmann_table.free_memory();
 
 #ifdef WITH_OSL
-       OSLShaderManager::free_memory();
+  OSLShaderManager::free_memory();
 #endif
 }
 
 float ShaderManager::linear_rgb_to_gray(float3 c)
 {
-       return dot(c, rgb_to_y);
+  return dot(c, rgb_to_y);
 }
 
 string ShaderManager::get_cryptomatte_materials(Scene *scene)
 {
-       string manifest = "{";
-       unordered_set<ustring, ustringHash> materials;
-       foreach(Shader *shader, scene->shaders) {
-               if(materials.count(shader->name)) {
-                       continue;
-               }
-               materials.insert(shader->name);
-               uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
-               manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
-       }
-       manifest[manifest.size()-1] = '}';
-       return manifest;
+  string manifest = "{";
+  unordered_set<ustring, ustringHash> materials;
+  foreach (Shader *shader, scene->shaders) {
+    if (materials.count(shader->name)) {
+      continue;
+    }
+    materials.insert(shader->name);
+    uint32_t cryptomatte_id = util_murmur_hash3(shader->name.c_str(), shader->name.length(), 0);
+    manifest += string_printf("\"%s\":\"%08x\",", shader->name.c_str(), cryptomatte_id);
+  }
+  manifest[manifest.size() - 1] = '}';
+  return manifest;
 }
 
 CCL_NAMESPACE_END