Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Thu, 9 Nov 2017 09:59:15 +0000 (10:59 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 9 Nov 2017 09:59:15 +0000 (10:59 +0100)
12 files changed:
1  2 
intern/cycles/device/device.cpp
intern/cycles/device/device.h
intern/cycles/device/device_cuda.cpp
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes.h
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
source/blender/depsgraph/intern/depsgraph_build.cc

Simple merge
Simple merge
Simple merge
index 0c1a3d21f84073f8a1a2846a662b88a285c50438,7ac94141f396b781817dbe32f1cd75b0e6b615a7..58c9b6f10ca73bf270f06e3785faa55536f8fe69
@@@ -128,7 -126,7 +127,7 @@@ static void modifier_walk(void *user_da
  {
        BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
        if (*obpoin) {
-               data->builder->build_object(data->scene, *obpoin, DEG_ID_LINKED_INDIRECTLY);
 -              data->builder->build_object(NULL, *obpoin);
++              data->builder->build_object(*obpoin, DEG_ID_LINKED_INDIRECTLY);
        }
  }
  
@@@ -141,7 -139,7 +140,7 @@@ void constraint_walk(bConstraint * /*co
        if (*idpoin) {
                ID *id = *idpoin;
                if (GS(id->name) == ID_OB) {
-                       data->builder->build_object(data->scene, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
 -                      data->builder->build_object(NULL, (Object *)id);
++                      data->builder->build_object((Object *)id, DEG_ID_LINKED_INDIRECTLY);
                }
        }
  }
@@@ -159,53 -151,20 +158,54 @@@ void free_copy_on_write_datablock(void 
  
  /* **** General purpose functions **** */
  
- DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) :
-     m_bmain(bmain),
-     m_graph(graph),
-     m_cow_id_hash(NULL)
+ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
+     : bmain_(bmain),
+       graph_(graph),
 -      scene_(NULL)
++      scene_(NULL),
++      cow_id_hash_(NULL)
  {
  }
  
  DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
  {
-       if (m_cow_id_hash != NULL) {
-               BLI_ghash_free(m_cow_id_hash, NULL, free_copy_on_write_datablock);
++      if (cow_id_hash_ != NULL) {
++              BLI_ghash_free(cow_id_hash_, NULL, free_copy_on_write_datablock);
 +      }
 +}
 +
 +IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag)
 +{
 +      if (!DEG_depsgraph_use_copy_on_write()) {
-               return m_graph->add_id_node(id);
++              return graph_->add_id_node(id);
 +      }
 +      IDDepsNode *id_node = NULL;
-       ID *id_cow = (ID *)BLI_ghash_lookup(m_cow_id_hash, id);
++      ID *id_cow = (ID *)BLI_ghash_lookup(cow_id_hash_, id);
 +      if (id_cow != NULL) {
 +              /* TODO(sergey): Is it possible to lookup and pop element from GHash
 +               * at the same time?
 +               */
-               BLI_ghash_remove(m_cow_id_hash, id, NULL, NULL);
++              BLI_ghash_remove(cow_id_hash_, id, NULL, NULL);
 +      }
-       id_node = m_graph->add_id_node(id, do_tag, id_cow);
++      id_node = graph_->add_id_node(id, do_tag, id_cow);
 +      /* Currently all ID nodes are supposed to have copy-on-write logic.
 +       *
 +       * NOTE: Zero number of components indicates that ID node was just created.
 +       */
 +      if (BLI_ghash_size(id_node->components) == 0) {
 +              ComponentDepsNode *comp_cow =
 +                      id_node->add_component(DEG_NODE_TYPE_COPY_ON_WRITE);
 +              OperationDepsNode *op_cow = comp_cow->add_operation(
-                   function_bind(deg_evaluate_copy_on_write, _1, m_graph, id_node),
-                   DEG_OPCODE_COPY_ON_WRITE,
-                   "", -1);
-               m_graph->operations.push_back(op_cow);
++                      function_bind(deg_evaluate_copy_on_write, _1, graph_, id_node),
++                      DEG_OPCODE_COPY_ON_WRITE,
++                      "", -1);
++              graph_->operations.push_back(op_cow);
 +      }
 +      return id_node;
  }
  
 -IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
 +IDDepsNode *DepsgraphNodeBuilder::find_id_node(ID *id)
  {
-       return m_graph->find_id_node(id);
 -      return graph_->add_id_node(id, id->name);
++      return graph_->find_id_node(id);
  }
  
  TimeSourceDepsNode *DepsgraphNodeBuilder::add_time_source()
@@@ -316,35 -275,9 +316,35 @@@ OperationDepsNode *DepsgraphNodeBuilder
        return find_operation_node(id, comp_type, "", opcode, name, name_tag);
  }
  
-       return m_graph->get_cow_id(id_orig);
 +ID *DepsgraphNodeBuilder::get_cow_id(const ID *id_orig) const
 +{
-       return deg_expand_copy_on_write_datablock(m_graph, id_node, this, true);
++      return graph_->get_cow_id(id_orig);
 +}
 +
 +ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig)
 +{
 +      if (id_orig->tag & LIB_TAG_COPY_ON_WRITE) {
 +              /* ID is already remapped to copy-on-write. */
 +              return id_orig;
 +      }
 +      IDDepsNode *id_node = add_id_node(id_orig, false);
 +      return id_node->id_cow;
 +}
 +
 +ID *DepsgraphNodeBuilder::expand_cow_id(IDDepsNode *id_node)
 +{
++      return deg_expand_copy_on_write_datablock(graph_, id_node, this, true);
 +}
 +
 +ID *DepsgraphNodeBuilder::expand_cow_id(ID *id_orig)
 +{
 +      IDDepsNode *id_node = add_id_node(id_orig);
 +      return expand_cow_id(id_node);
 +}
 +
  /* **** Build functions for entity nodes **** */
  
- void DepsgraphNodeBuilder::begin_build(Main *bmain) {
+ void DepsgraphNodeBuilder::begin_build() {
        /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
         * created or not. This flag is being set in add_id_node(), so functions
         * shouldn't bother with setting it, they only might query this flag when
                }
        }
        FOREACH_NODETREE_END;
-               m_cow_id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
-               foreach (IDDepsNode *id_node, m_graph->id_nodes) {
 +
 +      if (DEG_depsgraph_use_copy_on_write()) {
 +              /* Store existing copy-on-write versions of datablock, so we can re-use
 +               * them for new ID nodes.
 +               */
-                               BLI_ghash_insert(m_cow_id_hash,
++              cow_id_hash_ = BLI_ghash_ptr_new("Depsgraph id hash");
++              foreach (IDDepsNode *id_node, graph_->id_nodes) {
 +                      if (GS(id_node->id_orig->name) != ID_SCE) {
 +                              continue;
 +                      }
 +                      if (deg_copy_on_write_is_expanded(id_node->id_cow)) {
-       m_graph->clear_all_nodes();
-       m_graph->operations.clear();
-       BLI_gset_clear(m_graph->entry_tags, NULL);
++                              BLI_ghash_insert(cow_id_hash_,
 +                                               id_node->id_orig,
 +                                               id_node->id_cow);
 +                              id_node->id_cow = NULL;
 +                      }
 +              }
 +      }
 +
 +      /* Make sure graph has no nodes left from previous state. */
++      graph_->clear_all_nodes();
++      graph_->operations.clear();
++      BLI_gset_clear(graph_->entry_tags, NULL);
  }
  
- void DepsgraphNodeBuilder::build_group(Scene *scene, Group *group)
 -void DepsgraphNodeBuilder::build_group(Base *base, Group *group)
++void DepsgraphNodeBuilder::build_group(Group *group)
  {
        ID *group_id = &group->id;
        if (group_id->tag & LIB_TAG_DOIT) {
        group_id->tag |= LIB_TAG_DOIT;
  
        LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
-               build_object(scene, go->ob, DEG_ID_LINKED_INDIRECTLY);
 -              build_object(base, go->ob);
++              build_object(go->ob, DEG_ID_LINKED_INDIRECTLY);
        }
  }
  
- void DepsgraphNodeBuilder::build_object(Scene *scene,
-                                         Object *ob,
 -void DepsgraphNodeBuilder::build_object(Base *base, Object *ob)
++void DepsgraphNodeBuilder::build_object(Object *ob,
 +                                        eDepsNode_LinkedState_Type linked_state)
  {
 -      const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
 -      IDDepsNode *id_node = (has_object)
 -              ? graph_->find_id_node(&ob->id)
 -              : add_id_node(&ob->id);
 -      /* Update node layers.
 -       * Do it for both new and existing ID nodes. This is so because several
 -       * bases might be sharing same object.
 -       */
 -      if (base != NULL) {
 -              id_node->layers |= base->lay;
 -      }
 -      if (ob->type == OB_CAMERA) {
 -              /* Camera should always be updated, it used directly by viewport.
 -               *
 -               * TODO(sergey): Make it only for active scene camera.
 -               */
 -              id_node->layers |= (unsigned int)(-1);
 -      }
        /* Skip rest of components if the ID node was already there. */
 -      if (has_object) {
 +      if (ob->id.tag & LIB_TAG_DOIT) {
 +              IDDepsNode *id_node = find_id_node(&ob->id);
 +              id_node->linked_state = std::max(id_node->linked_state, linked_state);
                return;
        }
        ob->id.tag |= LIB_TAG_DOIT;
        ob->customdata_mask = 0;
  
        /* Standard components. */
-       build_object_transform(scene, ob);
+       build_object_transform(ob);
  
        if (ob->parent != NULL) {
-               build_object(scene, ob->parent, linked_state);
 -              build_object(NULL, ob->parent);
++              build_object(ob->parent, linked_state);
        }
        if (ob->modifiers.first != NULL) {
                BuilderWalkUserData data;
        /* Object that this is a proxy for. */
        if (ob->proxy) {
                ob->proxy->proxy_from = ob;
-               build_object(scene, ob->proxy, DEG_ID_LINKED_INDIRECTLY);
 -              build_object(base, ob->proxy);
++              build_object(ob->proxy, DEG_ID_LINKED_INDIRECTLY);
        }
  
        /* Object dupligroup. */
        if (ob->dup_group != NULL) {
-               build_group(scene, ob->dup_group);
 -              build_group(base, ob->dup_group);
++              build_group(ob->dup_group);
        }
  }
  
- void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
+ void DepsgraphNodeBuilder::build_object_transform(Object *ob)
  {
        OperationDepsNode *op_node;
-       Scene *scene_cow = get_cow_datablock(scene);
++      Scene *scene_cow = get_cow_datablock(scene_);
 +      Object *ob_cow = get_cow_datablock(ob);
  
        /* local transforms (from transform channels - loc/rot/scale + deltas) */
        op_node = add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
        }
  
        /* object constraints */
 -      if (ob->constraints.first) {
 +      if (ob->constraints.first != NULL) {
-               build_object_constraints(scene, ob);
+               build_object_constraints(ob);
        }
  
 -      /* Temporary uber-update node, which does everything.
 -       * It is for the being we're porting old dependencies into the new system.
 -       * We'll get rid of this node as soon as all the granular update functions
 -       * are filled in.
 -       *
 -       * TODO(sergey): Get rid of this node.
 -       */
 +      /* Rest of transformation update. */
        add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
 -                         function_bind(BKE_object_eval_uber_transform, _1, scene_, ob),
 +                         function_bind(BKE_object_eval_uber_transform,
 +                                       _1,
 +                                       scene_cow, ob_cow),
                           DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
  
        /* object transform is done */
@@@ -583,9 -494,7 +580,9 @@@ void DepsgraphNodeBuilder::build_object
  {
        /* create node for constraint stack */
        add_operation_node(&ob->id, DEG_NODE_TYPE_TRANSFORM,
 -                         function_bind(BKE_object_eval_constraints, _1, scene_, ob),
 +                         function_bind(BKE_object_eval_constraints, _1,
-                                        get_cow_datablock(scene),
++                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(ob)),
                           DEG_OPCODE_TRANSFORM_CONSTRAINTS);
  }
  
@@@ -779,10 -667,6 +776,10 @@@ void DepsgraphNodeBuilder::build_partic
        ComponentDepsNode *psys_comp =
                add_component_node(&ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
  
-       Scene *scene_cow = get_cow_datablock(scene);
 +      /* TODO(sergey): Need to get COW of PSYS. */
++      Scene *scene_cow = get_cow_datablock(scene_);
 +      Object *ob_cow = get_cow_datablock(ob);
 +
        add_operation_node(psys_comp,
                           function_bind(BKE_particle_system_eval_init,
                                         _1,
                                   psys->name);
        }
  
 -      /* pointcache */
 -      // TODO...
 +      /* TODO(sergey): Do we need a point cache operations here? */
 +}
 +
 +void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) {
 +      ID *part_id = &part->id;
 +      if (part_id->tag & LIB_TAG_DOIT) {
 +              return;
 +      }
 +      part_id->tag |= LIB_TAG_DOIT;
 +      /* Animation data. */
 +      build_animdata(part_id);
 +      /* Parameters change. */
 +      add_operation_node(part_id,
 +                         DEG_NODE_TYPE_PARAMETERS,
 +                         NULL,
 +                         DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
 +      add_operation_node(part_id,
 +                         DEG_NODE_TYPE_PARAMETERS,
 +                         function_bind(BKE_particle_system_settings_recalc_clear,
 +                                       _1,
 +                                       part),
 +                         DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
  }
  
- void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object)
+ void DepsgraphNodeBuilder::build_cloth(Object *object)
  {
-       Scene *scene_cow = get_cow_datablock(scene);
++      Scene *scene_cow = get_cow_datablock(scene_);
 +      Object *object_cow = get_cow_datablock(object);
        add_operation_node(&object->id,
                           DEG_NODE_TYPE_CACHE,
                           function_bind(BKE_object_eval_cloth,
@@@ -864,11 -717,10 +861,11 @@@ void DepsgraphNodeBuilder::build_shapek
  
  /* ObData Geometry Evaluation */
  // XXX: what happens if the datablock is shared!
- void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
+ void DepsgraphNodeBuilder::build_obdata_geom(Object *ob)
  {
 -      ID *obdata = (ID *)ob->data;
        OperationDepsNode *op_node;
-       Scene *scene_cow = get_cow_datablock(scene);
++      Scene *scene_cow = get_cow_datablock(scene_);
 +      Object *object_cow = get_cow_datablock(ob);
  
        /* TODO(sergey): This way using this object's properties as driver target
         * works fine.
                         */
                        Curve *cu = (Curve *)obdata;
                        if (cu->bevobj != NULL) {
-                               build_object(scene, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
 -                              build_object(NULL, cu->bevobj);
++                              build_object(cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
                        }
                        if (cu->taperobj != NULL) {
-                               build_object(scene, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
 -                              build_object(NULL, cu->taperobj);
++                              build_object(cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
                        }
                        if (ob->type == OB_FONT && cu->textoncurve != NULL) {
-                               build_object(scene, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
 -                              build_object(NULL, cu->textoncurve);
++                              build_object(cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
                        }
                        break;
                }
@@@ -1132,24 -957,36 +1128,36 @@@ void DepsgraphNodeBuilder::build_nodetr
        /* nodetree's nodes... */
        LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
                ID *id = bnode->id;
-               if (id != NULL) {
-                       ID_Type id_type = GS(id->name);
-                       if (id_type == ID_MA) {
-                               build_material((Material *)id);
-                       }
-                       else if (id_type == ID_TE) {
-                               build_texture((Tex *)id);
-                       }
-                       else if (id_type == ID_IM) {
-                               build_image((Image *)id);
-                       }
-                       else if (bnode->type == NODE_GROUP) {
-                               bNodeTree *group_ntree = (bNodeTree *)id;
-                               if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
-                                       build_nodetree(group_ntree);
-                               }
+               if (id == NULL) {
+                       continue;
+               }
+               ID_Type id_type = GS(id->name);
+               if (id_type == ID_MA) {
+                       build_material((Material *)id);
+               }
+               else if (id_type == ID_TE) {
+                       build_texture((Tex *)id);
+               }
+               else if (id_type == ID_IM) {
+                       build_image((Image *)id);
+               }
+               else if (id_type == ID_OB) {
 -                      build_object(NULL, (Object *)id);
++                      build_object((Object *)id, DEG_ID_LINKED_INDIRECTLY);
+               }
+               else if (id_type == ID_SCE) {
+                       /* Scenes are used by compositor trees, and handled by render
+                        * pipeline. No need to build dependencies for them here.
+                        */
+               }
+               else if (bnode->type == NODE_GROUP) {
+                       bNodeTree *group_ntree = (bNodeTree *)id;
+                       if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
+                               build_nodetree(group_ntree);
                        }
                }
+               else {
+                       BLI_assert(!"Unknown ID type used for node");
+               }
        }
  
        // TODO: link from nodetree to owner_component?
index e7bf8c9998da58a3efce076cd105b17c05ef7d64,ec9fe6a40a20df8eff90834fb63ec052e8d3d3c1..40d6a56e789181ae2266ee4f2bcbbf0b100aef4b
@@@ -74,44 -70,9 +74,44 @@@ struct DepsgraphNodeBuilder 
        DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
        ~DepsgraphNodeBuilder();
  
-       void begin_build(Main *bmain);
 +      /* For given original ID get ID which is created by CoW system. */
 +      ID *get_cow_id(const ID *id_orig) const;
 +      /* Similar to above, but for the cases when there is no ID node we create
 +       * one.
 +       */
 +      ID *ensure_cow_id(ID *id_orig);
 +
 +      /* Helper wrapper function which wraps get_cow_id with a needed type cast. */
 +      template<typename T>
 +      T *get_cow_datablock(const T *orig) const {
 +              return (T *)get_cow_id(&orig->id);
 +      }
 +
 +      /* Get fully expanded (ready for use) copy-on-write datablock for the given
 +       * original datablock.
 +       */
 +      ID *expand_cow_id(IDDepsNode *id_node);
 +      ID *expand_cow_id(ID *id_orig);
 +      template<typename T>
 +      T *expand_cow_datablock(T *orig) {
 +              return (T *)expand_cow_id(&orig->id);
 +      }
 +
 +      /* For a given COW datablock get corresponding original one. */
 +      template<typename T>
 +      T *get_orig_datablock(const T *cow) const {
 +              if (DEG_depsgraph_use_copy_on_write()) {
 +                      return (T *)cow->id.newid;
 +              }
 +              else {
 +                      return (T *)cow;
 +              }
 +      }
 +
+       void begin_build();
  
 -      IDDepsNode *add_id_node(ID *id);
 +      IDDepsNode *add_id_node(ID *id, bool do_tag = true);
 +      IDDepsNode *find_id_node(ID *id);
        TimeSourceDepsNode *add_time_source();
  
        ComponentDepsNode *add_component_node(ID *id,
                                               const char *name = "",
                                               int name_tag = -1);
  
-       void build_scene(Main *bmain,
-                        Scene *scene,
 -      void build_scene(Scene *scene);
 -      void build_group(Base *base, Group *group);
 -      void build_object(Base *base, Object *ob);
++      void build_scene(Scene *scene,
 +                       eDepsNode_LinkedState_Type linked_state);
-       void build_group(Scene *scene, Group *group);
-       void build_object(Scene *scene,
-                         Object *ob,
++      void build_group(Group *group);
++      void build_object(Object *ob,
 +                        eDepsNode_LinkedState_Type linked_state);
-       void build_object_transform(Scene *scene, Object *ob);
-       void build_object_constraints(Scene *scene, Object *ob);
-       void build_pose_constraints(Scene *scene, Object *ob, bPoseChannel *pchan);
+       void build_object_transform(Object *ob);
+       void build_object_constraints(Object *ob);
+       void build_pose_constraints(Object *ob, bPoseChannel *pchan);
        void build_rigidbody(Scene *scene);
-       void build_particles(Scene *scene, Object *ob);
+       void build_particles(Object *ob);
 +      void build_particle_settings(ParticleSettings *part);
-       void build_cloth(Scene *scene, Object *object);
+       void build_cloth(Object *object);
        void build_animdata(ID *id);
        OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
-       void build_ik_pose(Scene *scene,
-                          Object *ob,
+       void build_ik_pose(Object *ob,
                           bPoseChannel *pchan,
                           bConstraint *con);
-       void build_splineik_pose(Scene *scene,
-                                Object *ob,
+       void build_splineik_pose(Object *ob,
                                 bPoseChannel *pchan,
                                 bConstraint *con);
-       void build_rig(Scene *scene, Object *ob);
+       void build_rig(Object *ob);
        void build_proxy_rig(Object *ob);
        void build_shapekeys(Key *key);
-       void build_obdata_geom(Scene *scene, Object *ob);
+       void build_obdata_geom(Object *ob);
        void build_camera(Object *ob);
        void build_lamp(Object *ob);
        void build_nodetree(bNodeTree *ntree);
        void build_cachefile(CacheFile *cache_file);
        void build_mask(Mask *mask);
        void build_movieclip(MovieClip *clip);
 -
 +      void build_lightprobe(Object *object);
 +
 +      struct LayerCollectionState {
 +              int index;
 +              LayerCollection *parent;
 +      };
 +      void build_layer_collection(Scene *scene,
 +                                  LayerCollection *layer_collection,
 +                                  LayerCollectionState *state);
 +      void build_layer_collections(Scene *scene,
 +                                   ListBase *layer_collections,
 +                                   LayerCollectionState *state);
 +      void build_scene_layer_collections(Scene *scene);
  protected:
-       Main *m_bmain;
-       Depsgraph *m_graph;
-       GHash *m_cow_id_hash;
+       /* State which never changes, same for the whole builder time. */
+       Main *bmain_;
+       Depsgraph *graph_;
+       /* State which demotes currently built entities. */
+       Scene *scene_;
++
++      GHash *cow_id_hash_;
  };
  
  }  // namespace DEG
index dabebb9d4a9239590cf456a6c8a4005f40db6b95,a1f20b1c683c938680b62f9a9a4bff1e73ab37d2..7b78156b8f8416f8939da0ada2b1699578de7f28
@@@ -72,19 -68,12 +70,18 @@@ void DepsgraphNodeBuilder::build_pose_c
  {
        /* create node for constraint stack */
        add_operation_node(&ob->id, DEG_NODE_TYPE_BONE, pchan->name,
 -                         function_bind(BKE_pose_constraints_evaluate, _1, scene_, ob, pchan),
 +                         function_bind(BKE_pose_constraints_evaluate,
 +                                       _1,
-                                        get_cow_datablock(scene),
++                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(ob),
 +                                       pchan),
                           DEG_OPCODE_BONE_CONSTRAINTS);
  }
  
  /* IK Solver Eval Steps */
- void DepsgraphNodeBuilder::build_ik_pose(Scene *scene,
-                                          Object *ob,
 -void DepsgraphNodeBuilder::build_ik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con)
++void DepsgraphNodeBuilder::build_ik_pose(Object *ob,
 +                                         bPoseChannel *pchan,
 +                                         bConstraint *con)
  {
        bKinematicConstraint *data = (bKinematicConstraint *)con->data;
  
  
        /* Operation node for evaluating/running IK Solver. */
        add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
-                          function_bind(BKE_pose_iktree_evaluate, _1,
-                                        get_cow_datablock(scene),
 -                         function_bind(BKE_pose_iktree_evaluate, _1, scene_, ob, rootchan),
++                         function_bind(BKE_pose_iktree_evaluate,
++                                       _1,
++                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(ob),
 +                                       rootchan),
                           DEG_OPCODE_POSE_IK_SOLVER);
  }
  
  /* Spline IK Eval Steps */
- void DepsgraphNodeBuilder::build_splineik_pose(Scene *scene,
-                                                Object *ob,
 -void DepsgraphNodeBuilder::build_splineik_pose(Object *ob, bPoseChannel *pchan, bConstraint *con)
++void DepsgraphNodeBuilder::build_splineik_pose(Object *ob,
 +                                               bPoseChannel *pchan,
 +                                               bConstraint *con)
  {
        bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
  
        bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
  
        /* Operation node for evaluating/running Spline IK Solver.
 -       * Store the "root bone" of this chain in the solver, so it knows where to start.
 +       * Store the "root bone" of this chain in the solver, so it knows where to
 +       * start.
         */
        add_operation_node(&ob->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name,
 -                         function_bind(BKE_pose_splineik_evaluate, _1, scene_, ob, rootchan),
 +                         function_bind(BKE_pose_splineik_evaluate,
 +                                       _1,
-                                        get_cow_datablock(scene),
++                                       get_cow_datablock(scene_),
 +                                       get_cow_datablock(ob),
 +                                       rootchan),
                           DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
  }
  
  /* Pose/Armature Bones Graph */
- void DepsgraphNodeBuilder::build_rig(Scene *scene, Object *object)
 -void DepsgraphNodeBuilder::build_rig(Object *ob)
++void DepsgraphNodeBuilder::build_rig(Object *object)
  {
 -      bArmature *arm = (bArmature *)ob->data;
 +      bArmature *armature = (bArmature *)object->data;
 +      const short armature_tag = armature->id.tag;
 +      Scene *scene_cow;
 +      Object *object_cow;
 +      bArmature *armature_cow;
 +      if (DEG_depsgraph_use_copy_on_write()) {
 +              /* NOTE: We need to expand both object and armature, so this way we can
 +               * safely create object level pose.
 +               */
-               scene_cow = get_cow_datablock(scene);
++              scene_cow = get_cow_datablock(scene_);
 +              object_cow = expand_cow_datablock(object);
 +              armature_cow = expand_cow_datablock(armature);
 +      }
 +      else {
-               scene_cow = scene;
++              scene_cow = scene_;
 +              object_cow = object;
 +              armature_cow = armature;
 +      }
        OperationDepsNode *op_node;
  
 -      /* animation and/or drivers linking posebones to base-armature used to define them
 +      /* Animation and/or drivers linking posebones to base-armature used to
 +       * define them.
 +       *
         * NOTE: AnimData here is really used to control animated deform properties,
 -       *       which ideally should be able to be unique across different instances.
 -       *       Eventually, we need some type of proxy/isolation mechanism in-between here
 -       *       to ensure that we can use same rig multiple times in same scene...
 +       *       which ideally should be able to be unique across different
 +       *       instances. Eventually, we need some type of proxy/isolation
 +       *       mechanism in-between here to ensure that we can use same rig
 +       *       multiple times in same scene.
         */
 -      if ((arm->id.tag & LIB_TAG_DOIT) == 0) {
 -              build_animdata(&arm->id);
 +      if ((armature_tag & LIB_TAG_DOIT) == 0) {
 +              build_animdata(&armature->id);
  
                /* Make sure pose is up-to-date with armature updates. */
 -              add_operation_node(&arm->id,
 +              add_operation_node(&armature->id,
                                   DEG_NODE_TYPE_PARAMETERS,
                                   NULL,
                                   DEG_OPCODE_PLACEHOLDER,
                                             function_bind(BKE_pose_bone_done, _1, pchan),
                                             DEG_OPCODE_BONE_DONE);
                op_node->set_as_exit();
 -
 -              /* constraints */
 +              /* Build constraints. */
                if (pchan->constraints.first != NULL) {
-                       build_pose_constraints(scene, object, pchan);
 -                      build_pose_constraints(ob, pchan);
++                      build_pose_constraints(object, pchan);
                }
 -
                /**
 -               * IK Solvers...
 +               * IK Solvers.
                 *
                 * - These require separate processing steps are pose-level
                 *   to be executed between chains of bones (i.e. once the
                LINKLIST_FOREACH (bConstraint *, con, &pchan->constraints) {
                        switch (con->type) {
                                case CONSTRAINT_TYPE_KINEMATIC:
-                                       build_ik_pose(scene, object, pchan, con);
 -                                      build_ik_pose(ob, pchan, con);
++                                      build_ik_pose(object, pchan, con);
                                        break;
  
                                case CONSTRAINT_TYPE_SPLINEIK:
-                                       build_splineik_pose(scene, object, pchan, con);
 -                                      build_splineik_pose(ob, pchan, con);
++                                      build_splineik_pose(object, pchan, con);
                                        break;
  
                                default:
                                        break;
                        }
                }
-                       build_object(scene, get_orig_datablock(pchan->custom), DEG_ID_LINKED_INDIRECTLY);
 +              /* Custom shape. */
 +              /* NOTE: Custom shape datablock is already remapped to CoW version. */
 +              if (pchan->custom != NULL) {
++                      build_object(get_orig_datablock(pchan->custom), DEG_ID_LINKED_INDIRECTLY);
 +              }
        }
  }
  
index 097720f514a43c471483cdc5c1abe5ff480daa67,1ea44093cd7a46af9c6a517c75f94d7632f85835..941a9bed5f169ed7ee4875a0b108fd102ea76665
@@@ -65,7 -63,7 +65,7 @@@ extern "C" 
  
  namespace DEG {
  
- void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene, eDepsNode_LinkedState_Type linked_state)
 -void DepsgraphNodeBuilder::build_scene(Scene *scene)
++void DepsgraphNodeBuilder::build_scene(Scene *scene, eDepsNode_LinkedState_Type linked_state)
  {
        /* scene ID block */
        add_id_node(&scene->id);
        // XXX: depending on how this goes, that scene itself could probably store its
        //      own little partial depsgraph?
        if (scene->set) {
-               build_scene(bmain, scene->set, DEG_ID_LINKED_VIA_SET);
 -              build_scene(scene->set);
++              build_scene(scene->set, DEG_ID_LINKED_VIA_SET);
        }
  
+       /* Setup currently building context. */
+       scene_ = scene;
        /* scene objects */
 -      LINKLIST_FOREACH (Base *, base, &scene->base) {
 -              Object *ob = base->object;
 -              build_object(base, ob);
 +      int select_color = 1;
 +      for (SceneLayer *sl = (SceneLayer *)scene->render_layers.first; sl; sl = sl->next) {
 +              for (Base *base = (Base *)sl->object_bases.first; base; base = base->next) {
 +                      /* object itself */
-                       build_object(scene, base->object, linked_state);
++                      build_object(base->object, linked_state);
 +                      base->object->select_color = select_color++;
 +              }
 +      }
 +      if (scene->camera != NULL) {
-               build_object(scene, scene->camera, linked_state);
++              build_object(scene->camera, linked_state);
        }
  
        /* rigidbody */
index 91902ed0ea605da1d30b72a524ed2a20c93a9d0f,3448525a50de1f8d644e0c168115748437a94b6d..34df44ae046b0e87570df131a600f81eced4c1fb
@@@ -385,13 -386,11 +387,11 @@@ void DepsgraphRelationBuilder::begin_bu
                if (id != (ID *)nodetree) {
                        nodetree->id.tag &= ~LIB_TAG_DOIT;
                }
-       } FOREACH_NODETREE_END
+       }
 -      FOREACH_NODETREE_END;
++      FOREACH_NODETREE_END
  }
  
- void DepsgraphRelationBuilder::build_group(Main *bmain,
-                                            Scene *scene,
-                                            Object *object,
-                                            Group *group)
+ void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
  {
        ID *group_id = &group->id;
        bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0;
@@@ -1018,9 -1010,10 +1011,9 @@@ void DepsgraphRelationBuilder::build_dr
                /* Drivers on armature-level bone settings (i.e. bbone stuff),
                 * which will affect the evaluation of corresponding pose bones.
                 */
-               IDDepsNode *arm_node = m_graph->find_id_node(id);
+               IDDepsNode *arm_node = graph_->find_id_node(id);
                char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
 -
 -              if (arm_node && bone_name) {
 +              if (arm_node != NULL && bone_name != NULL) {
                        /* Find objects which use this, and make their eval callbacks
                         * depend on this.
                         */
@@@ -1404,33 -1358,14 +1397,33 @@@ void DepsgraphRelationBuilder::build_pa
  
                /* collisions */
                if (part->type != PART_HAIR) {
 -                      add_collision_relations(psys_key, scene_, ob, part->collision_group, ob->lay, true, "Particle Collision");
 +                      add_collision_relations(psys_key,
-                                               scene,
++                                              scene_,
 +                                              ob,
 +                                              part->collision_group,
 +                                              true,
 +                                              "Particle Collision");
                }
 -              else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
 -                      add_collision_relations(psys_key, scene_, ob, psys->clmd->coll_parms->group, ob->lay | scene_->lay, true, "Hair Collision");
 +              else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
 +                       psys->clmd != NULL &&
 +                       psys->clmd->coll_parms != NULL)
 +              {
 +                      add_collision_relations(psys_key,
-                                               scene,
++                                              scene_,
 +                                              ob,
 +                                              psys->clmd->coll_parms->group,
 +                                              true,
 +                                              "Hair Collision");
                }
  
                /* effectors */
 -              add_forcefield_relations(psys_key, scene_, ob, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
 +              add_forcefield_relations(psys_key,
-                                        scene,
++                                       scene_,
 +                                       ob,
 +                                       psys,
 +                                       part->effector_weights,
 +                                       part->type == PART_HAIR,
 +                                       "Particle Field");
  
                /* boids */
                if (part->boids) {
        ComponentKey transform_key(&ob->id, DEG_NODE_TYPE_TRANSFORM);
        add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
  
 -      /* pointcache */
 -      // TODO...
 +      /* TODO(sergey): Do we need a point cache operations here? */
 +}
 +
 +void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
 +{
 +      ID *part_id = &part->id;
 +      if (part_id->tag & LIB_TAG_DOIT) {
 +              return;
 +      }
 +      part_id->tag |= LIB_TAG_DOIT;
 +
 +      /* Animation data relations. */
 +      build_animdata(&part->id);
 +
 +      OperationKey eval_key(part_id,
 +                            DEG_NODE_TYPE_PARAMETERS,
 +                            DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
 +      OperationKey recalc_clear_key(part_id,
 +                                   DEG_NODE_TYPE_PARAMETERS,
 +                                   DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
 +      add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc");
  }
  
- void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/,
-                                            Object *object,
+ void DepsgraphRelationBuilder::build_cloth(Object *object,
                                             ModifierData * /*md*/)
  {
        OperationKey cache_key(&object->id,
@@@ -1560,22 -1475,12 +1552,22 @@@ void DepsgraphRelationBuilder::build_ob
        /* link components to each other */
        add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
  
-       OperationKey scene_key(&scene->id,
 +      OperationKey obdata_ubereval_key(&ob->id,
 +                                       DEG_NODE_TYPE_GEOMETRY,
 +                                       DEG_OPCODE_GEOMETRY_UBEREVAL);
 +
 +      /* Special case: modifiers and DerivedMesh creation queries scene for various
 +       * things like data mask to be used. We add relation here to ensure object is
 +       * never evaluated prior to Scene's CoW is ready.
 +       */
++      OperationKey scene_key(&scene_->id,
 +                             DEG_NODE_TYPE_PARAMETERS,
 +                             DEG_OPCODE_PLACEHOLDER,
 +                             "Scene Eval");
 +      add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
 +
        /* Modifiers */
        if (ob->modifiers.first != NULL) {
 -              OperationKey obdata_ubereval_key(&ob->id,
 -                                               DEG_NODE_TYPE_GEOMETRY,
 -                                               DEG_OPCODE_GEOMETRY_UBEREVAL);
 -
                LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
                        const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
  
@@@ -1818,31 -1694,54 +1809,48 @@@ void DepsgraphRelationBuilder::build_la
  
  void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
  {
 -      if (!ntree)
 +      if (ntree == NULL) {
                return;
 -
 +      }
        ID *ntree_id = &ntree->id;
 -
        build_animdata(ntree_id);
 -
 -      OperationKey parameters_key(ntree_id,
 -                                  DEG_NODE_TYPE_PARAMETERS,
 -                                  DEG_OPCODE_PARAMETERS_EVAL);
 -
 +      ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING);
        /* nodetree's nodes... */
        LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
-               if (bnode->id) {
-                       if (GS(bnode->id->name) == ID_MA) {
-                               build_material((Material *)bnode->id);
-                       }
-                       else if (bnode->type == ID_TE) {
-                               build_texture((Tex *)bnode->id);
-                       }
-                       else if (bnode->type == NODE_GROUP) {
-                               bNodeTree *group_ntree = (bNodeTree *)bnode->id;
-                               if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
-                                       build_nodetree(group_ntree);
-                                       group_ntree->id.tag |= LIB_TAG_DOIT;
-                               }
-                               ComponentKey group_shading_key(&group_ntree->id,
-                                                              DEG_NODE_TYPE_SHADING);
-                               add_relation(group_shading_key, shading_key, "Group Node");
+               ID *id = bnode->id;
+               if (id == NULL) {
+                       continue;
+               }
+               ID_Type id_type = GS(id->name);
+               if (id_type == ID_MA) {
+                       build_material((Material *)bnode->id);
+               }
+               else if (id_type == ID_TE) {
+                       build_texture((Tex *)bnode->id);
+               }
+               else if (id_type == ID_IM) {
+                       /* nothing for now. */
+               }
+               else if (id_type == ID_OB) {
+                       build_object((Object *)id);
+               }
+               else if (id_type == ID_SCE) {
+                       /* Scenes are used by compositor trees, and handled by render
+                        * pipeline. No need to build dependencies for them here.
+                        */
+               }
+               else if (bnode->type == NODE_GROUP) {
+                       bNodeTree *group_ntree = (bNodeTree *)id;
+                       if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) {
+                               build_nodetree(group_ntree);
+                               group_ntree->id.tag |= LIB_TAG_DOIT;
                        }
 -                      OperationKey group_parameters_key(&group_ntree->id,
 -                                                        DEG_NODE_TYPE_PARAMETERS,
 -                                                        DEG_OPCODE_PARAMETERS_EVAL);
 -                      add_relation(group_parameters_key, parameters_key, "Group Node");
++                      ComponentKey group_shading_key(&group_ntree->id,
++                                                     DEG_NODE_TYPE_SHADING);
++                      add_relation(group_shading_key, shading_key, "Group Node");
+               }
+               else {
+                       BLI_assert(!"Unknown ID type used for node");
                }
        }
  
@@@ -1967,85 -1859,4 +1975,85 @@@ void DepsgraphRelationBuilder::build_mo
        build_animdata(&clip->id);
  }
  
-       foreach (IDDepsNode *id_node, m_graph->id_nodes) {
 +void DepsgraphRelationBuilder::build_lightprobe(Object *object)
 +{
 +      LightProbe *probe = (LightProbe *)object->data;
 +      ID *probe_id = &probe->id;
 +      if (probe_id->tag & LIB_TAG_DOIT) {
 +              return;
 +      }
 +      probe_id->tag |= LIB_TAG_DOIT;
 +      build_animdata(&probe->id);
 +
 +      OperationKey probe_key(probe_id,
 +                             DEG_NODE_TYPE_PARAMETERS,
 +                             DEG_OPCODE_PLACEHOLDER,
 +                             "LightProbe Eval");
 +      OperationKey object_key(&object->id,
 +                              DEG_NODE_TYPE_PARAMETERS,
 +                              DEG_OPCODE_PLACEHOLDER,
 +                              "LightProbe Eval");
 +      add_relation(probe_key, object_key, "LightProbe Update");
 +}
 +
 +void DepsgraphRelationBuilder::build_copy_on_write_relations()
 +{
-                       m_graph->add_new_relation(op_cow, op_entry, "CoW Dependency");
++      foreach (IDDepsNode *id_node, graph_->id_nodes) {
 +              build_copy_on_write_relations(id_node);
 +      }
 +}
 +
 +void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node)
 +{
 +      ID *id_orig = id_node->id_orig;
 +
 +      TimeSourceKey time_source_key;
 +      OperationKey copy_on_write_key(id_orig,
 +                                     DEG_NODE_TYPE_COPY_ON_WRITE,
 +                                     DEG_OPCODE_COPY_ON_WRITE);
 +      /* XXX: This is a quick hack to make Alt-A to work. */
 +      // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
 +      /* Resat of code is using rather low level trickery, so need to get some
 +       * explicit pointers.
 +       */
 +      DepsNode *node_cow = find_node(copy_on_write_key);
 +      OperationDepsNode *op_cow = node_cow->get_exit_operation();
 +      /* Plug any other components to this one. */
 +      GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
 +      {
 +              if (comp_node->type == DEG_NODE_TYPE_COPY_ON_WRITE) {
 +                      /* Copy-on-write component never depends on itself. */
 +                      continue;
 +              }
 +              if (!comp_node->depends_on_cow()) {
 +                      /* Component explicitly requests to not add relation. */
 +                      continue;
 +              }
 +              /* All entry operations of each component should wait for a proper
 +               * copy of ID.
 +               */
 +              OperationDepsNode *op_entry = comp_node->get_entry_operation();
 +              if (op_entry != NULL) {
-                               m_graph->add_new_relation(op_cow, op_node, "CoW Dependency");
++                      graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
 +              }
 +              /* All dangling operations should also be executed after copy-on-write. */
 +              GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, comp_node->operations_map)
 +              {
 +                      if (op_node->inlinks.size() == 0) {
++                              graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
 +                      }
 +              }
 +              GHASH_FOREACH_END();
 +              /* NOTE: We currently ignore implicit relations to an external
 +               * datablocks for copy-on-write operations. This means, for example,
 +               * copy-on-write component of Object will not wait for copy-on-write
 +               * component of it's Mesh. This is because pointers are all known
 +               * already so remapping will happen all correct. And then If some object
 +               * evaluation step needs geometry, it will have transitive dependency
 +               * to Mesh copy-on-write already.
 +               */
 +      }
 +      GHASH_FOREACH_END();
 +}
 +
  }  // namespace DEG
index e8bdc662bd608ae46d960b4471fca0a5a5ede0b7,86227f4aaf801e58febc18e0398719ef37eaedda..81636db0bcf0d031e7cef8d0c1d749360819e2b1
@@@ -199,9 -197,8 +199,9 @@@ struct DepsgraphRelationBuilde
        void build_driver(ID *id, FCurve *fcurve);
        void build_world(World *world);
        void build_rigidbody(Scene *scene);
-       void build_particles(Scene *scene, Object *ob);
+       void build_particles(Object *ob);
 +      void build_particle_settings(ParticleSettings *part);
-       void build_cloth(Scene *scene, Object *object, ModifierData *md);
+       void build_cloth(Object *object, ModifierData *md);
        void build_ik_pose(Object *ob,
                           bPoseChannel *pchan,
                           bConstraint *con,
        void build_cachefile(CacheFile *cache_file);
        void build_mask(Mask *mask);
        void build_movieclip(MovieClip *clip);
 +      void build_lightprobe(Object *object);
  
        void add_collision_relations(const OperationKey &key,
-                                    Scene *scene, Object *ob, Group *group,
-                                    bool dupli, const char *name);
+                                    Scene *scene,
+                                    Object *ob,
+                                    Group *group,
 -                                   int layer,
+                                    bool dupli,
+                                    const char *name);
        void add_forcefield_relations(const OperationKey &key,
-                                     Scene *scene, Object *ob, ParticleSystem *psys,
+                                     Scene *scene,
+                                     Object *ob,
+                                     ParticleSystem *psys,
                                      EffectorWeights *eff,
 -                                    bool add_absorption,
 -                                    const char *name);
 +                                    bool add_absorption, const char *name);
 +
 +      struct LayerCollectionState {
 +              int index;
 +              OperationKey init_key;
 +              OperationKey done_key;
 +              OperationKey prev_key;
 +      };
 +      void build_layer_collection(Scene *scene,
 +                                  LayerCollection *layer_collection,
 +                                  LayerCollectionState *state);
 +      void build_layer_collections(Scene *scene,
 +                                   ListBase *layer_collections,
 +                                   LayerCollectionState *state);
 +      void build_scene_layer_collections(Scene *scene);
 +
 +      void build_copy_on_write_relations();
 +      void build_copy_on_write_relations(IDDepsNode *id_node);
  
        template <typename KeyType>
        OperationDepsNode *find_operation_node(const KeyType &key);
index c23d6d3a2bd1320d718907ca731048146ec45221,6ff21393ed6a1fffe8669a7afd6c18f89285d585..476e793d3f715c9450db84cb326c68db78ea4d8d
@@@ -412,10 -416,11 +412,10 @@@ void DepsgraphRelationBuilder::build_ri
                        OperationKey parent_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
                        add_relation(parent_key, bone_pose_key, "[Parent Bone -> Child Bone]");
                }
 -
 -              /* constraints */
 +              /* Buil constraints. */
                if (pchan->constraints.first != NULL) {
                        /* constraints stack and constraint dependencies */
-                       build_constraints(scene, &ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
+                       build_constraints(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
  
                        /* pose -> constraints */
                        OperationKey constraints_key(&ob->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
  
                /* assume that all bones must be done for the pose to be ready (for deformers) */
                add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link");
-                       build_object(bmain, scene, pchan->custom);
 +              /* Custom shape. */
 +              if (pchan->custom != NULL) {
++                      build_object(pchan->custom);
 +              }
        }
  }
  
index b8a2fe4851d75a93c9fce3d0b95d24b503109746,bedcb5aa223f68a503ce7c1058781baacf0532c0..af37decdbc7837bbcd2957e758a5cb1c6231229e
@@@ -68,23 -67,19 +68,26 @@@ extern "C" 
  
  namespace DEG {
  
- void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
+ void DepsgraphRelationBuilder::build_scene(Scene *scene)
  {
        if (scene->set) {
-               build_scene(bmain, scene->set);
+               build_scene(scene->set);
        }
  
-       m_graph->scene = scene;
 +      /* XXX store scene to access from DAG_get_scene */
++      graph_->scene = scene;
++
+       /* Setup currently building context. */
+       scene_ = scene;
  
        /* scene objects */
 -      LINKLIST_FOREACH (Base *, base, &scene->base) {
 -              Object *ob = base->object;
 -              build_object(ob);
 +      for (SceneLayer *sl = (SceneLayer *)scene->render_layers.first; sl; sl = sl->next) {
 +              for (Base *base = (Base *)sl->object_bases.first; base; base = base->next) {
-                       build_object(bmain, scene, base->object);
++                      build_object(base->object);
 +              }
 +      }
 +      if (scene->camera != NULL) {
-               build_object(bmain, scene, scene->camera);
++              build_object(scene->camera);
        }
  
        /* rigidbody */
                build_movieclip(clip);
        }
  
-       for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
-            it_op != m_graph->operations.end();
 +      /* Collections. */
 +      build_scene_layer_collections(scene);
 +
 +      /* TODO(sergey): Do this flush on CoW object? */
+       for (Depsgraph::OperationNodes::const_iterator it_op = graph_->operations.begin();
+            it_op != graph_->operations.end();
             ++it_op)
        {
                OperationDepsNode *node = *it_op;
index ab7e28e16389355a71bed351c7dab5ba0b300411,fb762505ed2795d744b4f0e4ac5cf729845e7003..c8c36646ade4d5f4eea85f776c621e1523e4e0ac
@@@ -206,28 -205,17 +206,28 @@@ void DEG_graph_build_from_scene(Depsgra
  
        DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
  
 +      /* TODO(sergey): This is a bit tricky, but ensures that all the data
 +       * is evaluated properly when depsgraph is becoming "visible".
 +       *
 +       * This now could happen for both visible scene is changed and extra
 +       * dependency graph was created for render engine.
 +       */
 +      const bool need_on_visible_update = (deg_graph->scene == NULL);
 +
        /* 1) Generate all the nodes in the graph first */
        DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
-       node_builder.begin_build(bmain);
-       node_builder.build_scene(bmain, scene, DEG::DEG_ID_LINKED_DIRECTLY);
+       node_builder.begin_build();
 -      node_builder.build_scene(scene);
++      node_builder.build_scene(scene, DEG::DEG_ID_LINKED_DIRECTLY);
  
        /* 2) Hook up relationships between operations - to determine evaluation
         *    order.
         */
-       DEG::DepsgraphRelationBuilder relation_builder(deg_graph);
-       relation_builder.begin_build(bmain);
-       relation_builder.build_scene(bmain, scene);
+       DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph);
+       relation_builder.begin_build();
+       relation_builder.build_scene(scene);
 +      if (DEG_depsgraph_use_copy_on_write()) {
 +              relation_builder.build_copy_on_write_relations();
 +      }
  
        /* Detect and solve cycles. */
        DEG::deg_graph_detect_cycles(deg_graph);