[Bf-blender-cvs] [50cc0aa0d13] blender2.8: Depsgraph: Re-use evaluated mesh across frames and remove time dependency from all CoW components

Sergey Sharybin noreply at git.blender.org
Fri Jul 28 13:02:50 CEST 2017


Commit: 50cc0aa0d136e91208487163efd3744a8e873bcc
Author: Sergey Sharybin
Date:   Fri Jul 28 12:27:34 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB50cc0aa0d136e91208487163efd3744a8e873bcc

Depsgraph: Re-use evaluated mesh across frames and remove time dependency from all CoW components

This commit is a work forward having less updates during playback, which speeds
things up a lot here. The idea is simple: stop update all copy-on-write
datablocks (which implies full re-evaluation actually) on frame change and
re-use existing evaluated meshes as much as possible.

This brings playback speed to 24 fps on the dino test scene here. Performance
drops down a lot when armature is animated tho, but that's because of need of
tangent space calculation which we can't do much about from just a dependency
graph.

Hopefully this doesn't make copy-on-write too unstable, quick tests here are
surviving fine.

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

M	source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
M	source/blender/depsgraph/intern/builder/deg_builder_nodes.h
M	source/blender/depsgraph/intern/builder/deg_builder_relations.cc
M	source/blender/depsgraph/intern/depsgraph.cc
M	source/blender/depsgraph/intern/depsgraph.h
M	source/blender/depsgraph/intern/depsgraph_build.cc
M	source/blender/depsgraph/intern/depsgraph_tag.cc
M	source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
M	source/blender/depsgraph/intern/nodes/deg_node.cc

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

diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 5910a7d8338..81bb8454976 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -144,6 +144,12 @@ void constraint_walk(bConstraint * /*con*/,
 	}
 }
 
+void free_copy_on_write_datablock(void *id_v)
+{
+	ID *id = (ID *)id_v;
+	deg_free_copy_on_write_datablock(id);
+}
+
 }  /* namespace */
 
 /* ************ */
@@ -153,18 +159,30 @@ void constraint_walk(bConstraint * /*con*/,
 
 DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) :
     m_bmain(bmain),
-    m_graph(graph)
+    m_graph(graph),
+    m_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);
+	}
 }
 
-IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
+IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag)
 {
-	IDDepsNode *id_node = m_graph->add_id_node(id);
 #ifdef WITH_COPY_ON_WRITE
+	IDDepsNode *id_node = NULL;
+	ID *id_cow = (ID *)BLI_ghash_lookup(m_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);
+	}
+	id_node = m_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.
@@ -178,6 +196,8 @@ IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id)
 		    "", -1);
 		m_graph->operations.push_back(op_cow);
 	}
+#else
+	IDDepsNode *id_node = m_graph->add_id_node(id);
 #endif
 	return id_node;
 }
@@ -301,7 +321,7 @@ ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig)
 		/* ID is already remapped to copy-on-write. */
 		return id_orig;
 	}
-	IDDepsNode *id_node = m_graph->add_id_node(id_orig, false);
+	IDDepsNode *id_node = add_id_node(id_orig, false);
 	return id_node->id_cow;
 }
 
@@ -328,11 +348,36 @@ void DepsgraphNodeBuilder::begin_build(Main *bmain) {
 	/* XXX nested node trees are not included in tag-clearing above,
 	 * so we need to do this manually.
 	 */
-	FOREACH_NODETREE(bmain, nodetree, id) {
+	FOREACH_NODETREE(bmain, nodetree, id)
+	{
 		if (id != (ID *)nodetree) {
 			nodetree->id.tag &= ~LIB_TAG_DOIT;
 		}
-	} FOREACH_NODETREE_END
+	}
+	FOREACH_NODETREE_END;
+
+#ifdef WITH_COPY_ON_WRITE
+	/* Store existing copy-on-write versions of datablock, so we can re-use
+	 * them for new ID nodes.
+	 */
+	m_cow_id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
+	GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, m_graph->id_hash)
+	{
+		if (GS(id_node->id_orig->name) != ID_SCE) {
+			continue;
+		}
+		if (deg_copy_on_write_is_expanded(id_node->id_cow)) {
+			BLI_ghash_insert(m_cow_id_hash, id_node->id_orig, id_node->id_cow);
+			id_node->id_cow = NULL;
+		}
+	}
+	GHASH_FOREACH_END();
+#endif
+
+	/* Make sure graph has no nodes left from previous state. */
+	m_graph->clear_all_nodes();
+	m_graph->operations.clear();
+	BLI_gset_clear(m_graph->entry_tags, NULL);
 }
 
 void DepsgraphNodeBuilder::build_group(Scene *scene, Group *group)
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 279cc92397b..7e28df1276d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -107,7 +107,7 @@ struct DepsgraphNodeBuilder {
 
 	void begin_build(Main *bmain);
 
-	IDDepsNode *add_id_node(ID *id);
+	IDDepsNode *add_id_node(ID *id, bool do_tag = true);
 	TimeSourceDepsNode *add_time_source();
 
 	ComponentDepsNode *add_component_node(ID *id,
@@ -206,6 +206,7 @@ struct DepsgraphNodeBuilder {
 protected:
 	Main *m_bmain;
 	Depsgraph *m_graph;
+	GHash *m_cow_id_hash;
 };
 
 }  // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 70fbcd3d58a..861aa9521c0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1917,7 +1917,7 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node
 	                               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");
+	// 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.
 	 */
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 868e7c0e3e5..9664d389794 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -279,14 +279,14 @@ IDDepsNode *Depsgraph::find_id_node(const ID *id) const
 	return reinterpret_cast<IDDepsNode *>(BLI_ghash_lookup(id_hash, id));
 }
 
-IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag)
+IDDepsNode *Depsgraph::add_id_node(ID *id, bool do_tag, ID *id_cow_hint)
 {
 	BLI_assert((id->tag & LIB_TAG_COPY_ON_WRITE) == 0);
 	IDDepsNode *id_node = find_id_node(id);
 	if (!id_node) {
 		DepsNodeFactory *factory = deg_get_node_factory(DEG_NODE_TYPE_ID_REF);
 		id_node = (IDDepsNode *)factory->create_node(id, "", id->name);
-		id_node->init_copy_on_write();
+		id_node->init_copy_on_write(id_cow_hint);
 		if (do_tag) {
 			id->tag |= LIB_TAG_DOIT;
 		}
@@ -310,6 +310,12 @@ void Depsgraph::clear_id_nodes()
 	/* Stupid workaround to ensure we free IDs in a proper order. */
 	GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, id_hash)
 	{
+		if (id_node->id_cow == NULL) {
+			/* This means builder "stole" ownership of the copy-on-written
+			 * datablock for her own dirty needs.
+			 */
+			continue;
+		}
 		if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
 			continue;
 		}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 6290dbe4ba7..823a1935e18 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -114,7 +114,7 @@ struct Depsgraph {
 	TimeSourceDepsNode *find_time_source() const;
 
 	IDDepsNode *find_id_node(const ID *id) const;
-	IDDepsNode *add_id_node(ID *id, bool do_tag = true);
+	IDDepsNode *add_id_node(ID *id, bool do_tag = true, ID *id_cow_hint = NULL);
 	void clear_id_nodes();
 
 	/* Add new relationship between two nodes. */
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 68f14790d87..e21c3d29aa5 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -257,6 +257,7 @@ void DEG_graph_tag_relations_update(Depsgraph *graph)
 /* Tag all relations for update. */
 void DEG_relations_tag_update(Main *bmain)
 {
+	DEG_DEBUG_PRINTF("%s: Tagging relations for update.\n", __func__);
 	for (Scene *scene = (Scene *)bmain->scene.first;
 	     scene != NULL;
 	     scene = (Scene *)scene->id.next)
@@ -285,11 +286,6 @@ void DEG_scene_relations_update(Main *bmain, Scene *scene)
 		return;
 	}
 
-	/* Clear all previous nodes and operations. */
-	graph->clear_all_nodes();
-	graph->operations.clear();
-	BLI_gset_clear(graph->entry_tags, NULL);
-
 	/* Build new nodes and relations. */
 	DEG_graph_build_from_scene(reinterpret_cast< ::Depsgraph * >(graph),
 	                           bmain,
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 0c4bc45eb3a..38919fb890e 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -288,6 +288,16 @@ void deg_graph_id_tag_update(Main *bmain, Depsgraph *graph, ID *id, int flag)
 	}
 	if (flag & OB_RECALC_DATA) {
 		id_tag_update_object_data(graph, id_node);
+#ifdef WITH_COPY_ON_WRITE
+		if (flag & DEG_TAG_COPY_ON_WRITE) {
+			const short id_type = GS(id_node->id_orig->name);
+			if (id_type == ID_OB) {
+				Object *object = (Object *)id_node->id_orig;
+				ID *ob_data = (ID *)object->data;
+				DEG_id_tag_update_ex(bmain, ob_data, flag);
+			}
+		}
+#endif
 	}
 	if (flag & OB_RECALC_TIME) {
 		id_tag_update_object_time(graph, id_node);
@@ -337,16 +347,7 @@ void deg_graph_on_visible_update(Main *bmain, Scene *scene, Depsgraph *graph)
 		 * TODO(sergey): Need to generalize this somehow.
 		 */
 		if (id_type == ID_OB) {
-			Object *object = (Object *)id_node->id_orig;
-			flag |= OB_RECALC_OB;
-			if (ELEM(object->type, OB_MESH,
-			                       OB_CURVE,
-			                       OB_SURF,
-			                       OB_FONT,
-			                       OB_MBALL))
-			{
-				flag |= OB_RECALC_DATA;
-			}
+			flag |= OB_RECALC_OB | OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE;
 		}
 		deg_graph_id_tag_update(bmain, graph, id_node->id_orig, flag);
 	}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index a0642210664..3ed93ea5677 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -661,7 +661,13 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
 	DEG_COW_PRINT("Expanding datablock for %s: id_orig=%p id_cow=%p\n",
 	              id_orig->name, id_orig, id_cow);
 	/* Sanity checks. */
-	BLI_assert(check_datablock_expanded(id_cow) == false);
+	/* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
+	 * rebuilding dependencies.
+	 */
+	if (check_datablock_expanded(id_cow) && create_placeholders) {
+		deg_free_copy_on_write_datablock(id_cow);
+	}
+	// BLI_assert(check_datablock_expanded(id_cow) == false);
 	/* Copy data from original ID to a copied version. *

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list