[Bf-blender-cvs] [3fb7eed] depsgraph_refactor: Depsgraph: Initial support for skipping invisible IDs update

Sergey Sharybin noreply at git.blender.org
Fri Dec 19 15:19:20 CET 2014


Commit: 3fb7eedb78f997881dd253ba685cff2260999782
Author: Sergey Sharybin
Date:   Fri Dec 19 19:07:06 2014 +0500
Branches: depsgraph_refactor
https://developer.blender.org/rB3fb7eedb78f997881dd253ba685cff2260999782

Depsgraph: Initial support for skipping invisible IDs update

General idea is quite simple here:

- Store layers in the IDDepsNode (same as we did in the old dependency graph).

  This layer would correspond to ID layers themselves plus layers of nodes which
  depends on it.

  Here's where first tricky part begins: i'm not sure how we could flush layers
  between nodes. Basically because it's totally unclear how do we perform full
  DFS nowadays. Previously it was simple because of having root node and knowing
  for sure nodes which doesn't have dependencies. Would need to think a bit how
  to do it now.

- We keep track of currently visible layers.

  Here's where tricky parts continues. basically the question is: where do we
  store currently visible layers? Evaluation context comes in mind, but that'd
  be wrong idea. basically because evaluation context is shared between scenes
  and since it's possible to have two different scenes visible we can not store
  single value.

  So for now we store visible layers in the depsgraph itself. This way we're
  decoupling visible layers between scenes. This is temporary solution for
  until we'll have some more centralized storage. Should be easy to move stuff
  around anyway, so wouldn't be so much fussed about this.

  Another tricky part here is the render engines. Currently there's no visibility
  check performed for render engine update.

  So after all it seems we'll need to store visible layers somewhere and pass
  what layers we're currently interested in to the depsgraph evaluation, making
  it so we can easily use the same graph for viewport and render engine and
  perform all the visibility checks we want.

- We don't schedule invisible IDs during evaluation.

  We instead put them to the "to be updated when becoming visible list". Now,
  this list is a bit of an overkill, would be better to have some sort of legacy
  (ID->flag & ID_NEEDS_UPDATE) flag, but since we're currently not really sure
  what the storage for such a flags would look like we'll keep a temp list for
  now. Again, it'll be easy to change in the future, so wouldn't be fussed here
  as well.

- When visibility changes depsgraph updates visible layers and re-schedules
  updates of previously invisible objects.

TODOs:

- Implement layers visibility flush.
- Make sure set scenes works all nice.
- Move temp storage to somewhat final storage (well, implement that final
  storage first :)

===================================================================

M	source/blender/blenkernel/intern/depsgraph.c
M	source/blender/depsgraph/DEG_depsgraph.h
M	source/blender/depsgraph/intern/depsgraph.cpp
M	source/blender/depsgraph/intern/depsgraph.h
M	source/blender/depsgraph/intern/depsgraph_build.cpp
M	source/blender/depsgraph/intern/depsgraph_build.h
M	source/blender/depsgraph/intern/depsgraph_build_nodes.cpp
M	source/blender/depsgraph/intern/depsgraph_eval.cpp
M	source/blender/depsgraph/intern/depsgraph_queue.h
M	source/blender/depsgraph/intern/depsgraph_tag.cpp
M	source/blender/depsgraph/intern/depsnode.h
M	source/blender/makesrna/intern/rna_depsgraph.c

===================================================================

diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 6e0847a..4e8e77c 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -2458,6 +2458,16 @@ void DAG_on_visible_update(Main *bmain, const bool do_time)
 			DAG_id_tag_update(&mask->id, 0);
 		}
 	}
+
+	/* Inform new dependnecy graphs about visibility changes. */
+	{
+		Scene *scene;
+		for (scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
+			if (scene->depsgraph != NULL) {
+				DEG_graph_on_visible_update(bmain, scene->depsgraph);
+			}
+		}
+	}
 }
 
 static void dag_id_flush_update__isDependentTexture(void *userData, Object *UNUSED(ob), ID **idpoin)
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index 440fc33..7a406f1 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -56,6 +56,7 @@ typedef struct Depsgraph Depsgraph;
 /* ------------------------------------------------ */
 
 struct EvaluationContext;
+struct Main;
 
 struct PointerRNA;
 struct PropertyRNA;
@@ -87,6 +88,8 @@ Depsgraph *DEG_graph_new(void);
 /* Free Depsgraph itself and all its data */
 void DEG_graph_free(Depsgraph *graph);
 
+/* Update dependency graph for events when visible scenes/layers changes. */
+void DEG_graph_on_visible_update(struct Main *bmain, Depsgraph *graph);
 
 /* Node Types Registry ---------------------------- */
 
@@ -111,7 +114,7 @@ void DEG_property_tag_update(Depsgraph *graph, const struct PointerRNA *ptr, con
 /* Update Flushing ------------------------------- */
 
 /* Flush updates */
-void DEG_graph_flush_updates(Depsgraph *graph);
+void DEG_graph_flush_updates(struct EvaluationContext *eval_ctx, Depsgraph *graph);
 
 /* Clear all update tags 
  * - For aborted updates, or after successful evaluation
diff --git a/source/blender/depsgraph/intern/depsgraph.cpp b/source/blender/depsgraph/intern/depsgraph.cpp
index 1bb087b..773e358 100644
--- a/source/blender/depsgraph/intern/depsgraph.cpp
+++ b/source/blender/depsgraph/intern/depsgraph.cpp
@@ -30,9 +30,19 @@
 
 extern "C" {
 #include "DNA_action_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
 #include "DNA_sequence_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
 
 #include "RNA_access.h"
+
+/* TODO(sergey): because of bloody "new" in the BKE_screen.h. */
+unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene);
 }
 
 #include "depsgraph.h" /* own include */
@@ -43,8 +53,9 @@ extern "C" {
 #include "depsgraph_debug.h"
 
 Depsgraph::Depsgraph()
+  : root_node(NULL),
+    layers((1 << 20) - 1)
 {
-	this->root_node = NULL;
 	BLI_spin_init(&lock);
 }
 
@@ -337,6 +348,23 @@ void Depsgraph::clear_all_nodes()
 	}
 }
 
+/* Layers Visibility -------------------------------------- */
+
+/* Tag a specific invisible node as needing updates when becoming visible. */
+void Depsgraph::add_invisible_entry_tag(OperationDepsNode *node)
+{
+	BLI_assert(node != NULL);
+	IDDepsNode *id_node = node->owner->owner;
+	invisible_entry_tags.insert(node);
+}
+
+/* Get layers for which nodes are to be evaluated. */
+int Depsgraph::layers_for_context(EvaluationContext *eval_ctx)
+{
+	return (eval_ctx->mode == DAG_EVAL_RENDER) ? (1 << 20) - 1
+	                                           : layers;
+}
+
 /* ************************************************** */
 /* Public Graph API */
 
@@ -351,3 +379,46 @@ void DEG_graph_free(Depsgraph *graph)
 {
 	OBJECT_GUARDED_DELETE(graph, Depsgraph);
 }
+
+/* Update dependency graph for events when visible scenes/layers changes. */
+void DEG_graph_on_visible_update(Main *bmain, Depsgraph *graph)
+{
+	wmWindowManager *wm = (wmWindowManager *)bmain->wm.first;
+	int old_layers = graph->layers;
+	if (wm != NULL) {
+		BKE_main_id_flag_listbase(&bmain->scene, LIB_DOIT, true);
+		graph->layers = 0;
+		for (wmWindow *win = (wmWindow *)wm->windows.first;
+		     win != NULL;
+		     win = (wmWindow *)win->next)
+		{
+			Scene *scene = win->screen->scene;
+			if (scene->id.flag & LIB_DOIT) {
+				graph->layers |= BKE_screen_visible_layers(win->screen, scene);
+				scene->id.flag &= ~LIB_DOIT;
+			}
+		}
+	}
+	else {
+		/* All the layers for background render for now. */
+		graph->layers = (1 << 20) - 1;
+	}
+	if (old_layers != graph->layers) {
+		/* Re-tag nodes which became visible. */
+		for (Depsgraph::EntryTags::const_iterator it = graph->invisible_entry_tags.begin();
+		     it != graph->invisible_entry_tags.end();
+		     ++it)
+		{
+			OperationDepsNode *node = *it;
+			/* TODO(sergey): For the simplicity we're trying to re-schedule
+			 * all the nodes, regardless of their layers visibility.
+			 *
+			 * In the future when storage for such flags becomes more permanent
+			 * we'll optimize this out.
+			 */
+			node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+			graph->add_entry_tag(node);
+		}
+		graph->invisible_entry_tags.clear();
+	}
+}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 6503579..add323c 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -193,6 +193,27 @@ struct Depsgraph {
 	 */
 	SpinLock lock;
 
+	/* Layers Visibility .................. */
+
+	/* Tag a specific invisible node as needing updates when becoming visible. */
+	void add_invisible_entry_tag(OperationDepsNode *node);
+
+	/* Get layers for which nodes are to be evaluated. */
+	int layers_for_context(EvaluationContext *eval_ctx);
+
+	/* Visible layers bitfield, used for skipping invisible objects updates. */
+	int layers;
+
+	/* Invisible nodes which have been tagged as "directly modified".
+	 * They're being flushed for update after graph visibility changes.
+	 *
+	 * TODO(sergey): This is a tempotrary solution for until we'll have storage
+	 * associated with the IDs, so we can keep dirty/tagged for update/etc flags
+	 * in there. This would also solve issues with accessing .updated ID flag
+	 * from python.
+	 */
+	EntryTags invisible_entry_tags;
+
 	// XXX: additional stuff like eval contexts, mempools for allocating nodes from, etc.
 };
 
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cpp b/source/blender/depsgraph/intern/depsgraph_build.cpp
index 5ab771b..e3a30f3 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_build.cpp
@@ -489,6 +489,11 @@ static void deg_graph_transitive_reduction(Depsgraph *graph)
 	}
 }
 
+static void deg_graph_flush_node_layers(Depsgraph *graph)
+{
+	/* TODO(sergey): Needs to be implemented. */
+}
+
 /* -------------------------------------------------- */
 
 /* Build depsgraph for the given scene, and dump results in given graph container */
@@ -532,6 +537,7 @@ void DEG_graph_build_from_scene(Depsgraph *graph, Main *bmain, Scene *scene)
 #endif
 	
 	deg_graph_transitive_reduction(graph);
+	deg_graph_flush_node_layers(graph);
 }
 
 /* Tag relations for update. */
@@ -574,6 +580,7 @@ void DEG_scene_relations_update(Main *bmain, Scene *scene)
 	graph->clear_all_nodes();
 	graph->operations.clear();
 	graph->entry_tags.clear();
+	graph->invisible_entry_tags.clear();
 
 	/* Build new nodes and relations. */
 	DEG_graph_build_from_scene(graph, bmain, scene);
diff --git a/source/blender/depsgraph/intern/depsgraph_build.h b/source/blender/depsgraph/intern/depsgraph_build.h
index 006ac9f..6f2bd6c 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.h
+++ b/source/blender/depsgraph/intern/depsgraph_build.h
@@ -82,7 +82,7 @@ struct DepsgraphNodeBuilder {
 	void build_scene(Scene *scene);
 	SubgraphDepsNode *build_subgraph(Group *group);
 	void build_group(Group *group);
-	void build_object(Scene *scene, Object *ob);
+	void build_object(Scene *scene, Base *base, Object *ob);
 	void build_object_transform(Scene *scene, Object *ob);
 	void build_object_constraints(Scene *scene, Object *ob);
 	void build_pose_constraints(Object *ob, bPoseChannel *pchan);
diff --git a/source/blender/depsgraph/intern/depsgraph_build_nodes.cpp b/source/blender/depsgraph/intern/depsgraph_build_nodes.cpp
index c4b6c06..187a738 100644
--- a/source/blender/depsgraph/intern/depsgraph_build_nodes.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_build_nodes.cpp
@@ -118,12 +118,12 @@ void DepsgraphNodeBuilder::build_scene(Scene *scene)
 		Object *ob = base->object;
 		
 		/* object itself */
-		build_object(scene, ob);
+		build_object(scene, base, ob);
 		
 		/* object that this is a proxy for */
 		// XXX: the way that proxies work needs to be completely reviewed!
 		if (ob->proxy) {
-			build_object(scene, ob->proxy);
+			build_object(scene, base, ob->proxy);
 		}
 		
 		/* handled in next loop... 
@@ -209,8 +209,11 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
 	return subgraph_node;
 }
 
-void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob)
+void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
 {
+	IDDepsNode *id_node = add_id_node(&ob->id);
+	id_node->layers |= base->lay;
+
 	/* standard components */
 	build_object_transform(scene, ob);
 	
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cpp b/source/blender/depsgraph/intern/depsgraph_eval.cpp
index be85cd9..887430f 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cpp
@@ -200,15 +200,22 @@ static void calculate_eval_priority(OperationDepsNode *node)
 	}
 }
 
-static void schedule_graph(TaskPool *pool, EvaluationContext *eval_ctx, Depsgraph *graph)
+static void schedule_graph(TaskPool *pool,
+                           EvaluationContext *eval_ctx,
+                           Depsgraph *graph)
 {
+	int layers = graph->layers_for_context(eval_ctx);
 	BLI_spin_lock(&graph->lock);
 	for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin();
 	     it != graph->operations.end();
 	     ++it)
 	{
 		OperationDepsNode *node = *it;
-		if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) && node->num_links_pending == 0) {
+		IDDepsNode *id_nod

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list