[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59746] branches/soc-2013-depsgraph_mt/ source/blender: DerivedRender cleanup and improvements

Sergey Sharybin sergey.vfx at gmail.com
Mon Sep 2 19:33:35 CEST 2013


Revision: 59746
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59746
Author:   nazgul
Date:     2013-09-02 17:33:34 +0000 (Mon, 02 Sep 2013)
Log Message:
-----------
DerivedRender cleanup and improvements

- Use special flags in DagNode for tags and scheduled
  instead of trying to use color for this. This way
  it's possible to have both tag and scheduler working
  at the same time.

- Simplified DAG threaded traversal code, moved comments
  to depsgaph instead of documenting what functions does
  when using them.

- Switch from recursive tag flush to iterative one.

- Set scenes shall be handled properly in convertblender.

- Removed derivedRender construction from handle object
  update function. It doesn't make much sense to have it
  in both there and convertblender.

- Creating new task pool now ensures malloc is switched
  to thread-safe one.

- Create derivedRender in threads using the same way as
  it's done for object update. In really quick tests
  gave around 2x speedup of database_init_objects when
  having 130 suzannes with subsurf level of 3.

Modified Paths:
--------------
    branches/soc-2013-depsgraph_mt/source/blender/blenkernel/BKE_depsgraph.h
    branches/soc-2013-depsgraph_mt/source/blender/blenkernel/depsgraph_private.h
    branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/depsgraph.c
    branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/object.c
    branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/scene.c
    branches/soc-2013-depsgraph_mt/source/blender/blenlib/intern/task.c
    branches/soc-2013-depsgraph_mt/source/blender/render/intern/source/convertblender.c

Modified: branches/soc-2013-depsgraph_mt/source/blender/blenkernel/BKE_depsgraph.h
===================================================================
--- branches/soc-2013-depsgraph_mt/source/blender/blenkernel/BKE_depsgraph.h	2013-09-02 17:28:00 UTC (rev 59745)
+++ branches/soc-2013-depsgraph_mt/source/blender/blenkernel/BKE_depsgraph.h	2013-09-02 17:33:34 UTC (rev 59746)
@@ -123,13 +123,10 @@
 void DAG_threaded_exit(void);
 
 /* Initialize the DAG for threaded update. */
-void DAG_threaded_update_begin(struct Scene *scene);
+void DAG_threaded_update_begin(struct Scene *scene,
+                               void (*func)(void *node, void *user_data),
+                               void *user_data);
 
-/* Run a callback for every node which is ready for update. */
-void DAG_threaded_update_foreach_ready_node(struct Scene *scene,
-                                            void (*func)(void *node, void *user_data),
-                                            void *user_data);
-
 void DAG_threaded_update_handle_node_updated(void *node_v,
                                              void (*func)(void *node, void *user_data),
                                              void *user_data);
@@ -140,14 +137,12 @@
 
 /* Tagging and querying */
 void DAG_tag_clear_nodes(struct Scene *scene);
-void DAG_tag_condition_nodes(struct Scene *scene, bool (*condition) (void *node_v, void *user_data),
-                             void *user_data);
+void DAG_tag_node_for_object(struct Scene *scene, void *object);
 void DAG_tag_flush_nodes(struct Scene *scene);
-void DAG_foreach_tagged_nodes(struct Scene *scene, void (*callback) (void *node_v, void *user_data),
-                              void *user_data);
 
 struct Object *DAG_get_node_object(void *node_v);
 const char *DAG_get_node_name(void *node_v);
+bool DAG_get_node_tag(void *node_v);
 
 #ifdef __cplusplus
 }

Modified: branches/soc-2013-depsgraph_mt/source/blender/blenkernel/depsgraph_private.h
===================================================================
--- branches/soc-2013-depsgraph_mt/source/blender/blenkernel/depsgraph_private.h	2013-09-02 17:28:00 UTC (rev 59745)
+++ branches/soc-2013-depsgraph_mt/source/blender/blenkernel/depsgraph_private.h	2013-09-02 17:33:34 UTC (rev 59746)
@@ -99,6 +99,7 @@
 	                    * Used by threaded update for faster detect whether node could be
 	                    * updated aready.
 	                    */
+	bool tag, scheduled;
 } DagNode;
 
 typedef struct DagNodeQueueElem {

Modified: branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/depsgraph.c
===================================================================
--- branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/depsgraph.c	2013-09-02 17:28:00 UTC (rev 59745)
+++ branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/depsgraph.c	2013-09-02 17:33:34 UTC (rev 59746)
@@ -2696,19 +2696,25 @@
 	BLI_spin_end(&threaded_update_lock);
 }
 
-/* Initialize the DAG for threaded update.
+/* Initialize run-time data in the graph needed for traversing it
+ * from multiple threads and start threaded tree traversal by adding
+ * the root node to the queue.
  *
- * Sets up all the data needed for faster check whether DAG node is
- * updatable already (whether all the dependencies are met).
+ * This will mark DAG nodes as object/non-object and will calculate
+ * "valency" of nodes (which is how many non-updated parents node
+ * have, which helps a lot checking whether node could be scheduled
+ * already or not).
  */
-void DAG_threaded_update_begin(Scene *scene)
+void DAG_threaded_update_begin(Scene *scene,
+                               void (*func)(void *node, void *user_data),
+                               void *user_data)
 {
-	DagNode *node;
+	DagNode *node, *root_node;
 
 	/* We reset valency to zero first... */
 	for (node = scene->theDag->DagNode.first; node; node = node->next) {
 		node->valency = 0;
-		node->color = DAG_WHITE;
+		node->scheduled = false;
 	}
 
 	/* ... and then iterate over all the nodes and
@@ -2723,32 +2729,11 @@
 			}
 		}
 	}
-}
 
-/* Call functor for every node in the graph which is ready for
- * update (all it's dependencies are met). Quick check for this
- * is valency == 0.
- */
-void DAG_threaded_update_foreach_ready_node(Scene *scene,
-                                            void (*func)(void *node, void *user_data),
-                                            void *user_data)
-{
-	DagNode *node;
-
-	for (node = scene->theDag->DagNode.first; node; node = node->next) {
-		if (node->valency == 0) {
-			bool need_schedule;
-
-			BLI_spin_lock(&threaded_update_lock);
-			need_schedule = node->color == DAG_WHITE;
-			node->color = DAG_BLACK;
-			BLI_spin_unlock(&threaded_update_lock);
-
-			if (need_schedule) {
-				func(node, user_data);
-			}
-		}
-	}
+	/* Add root node to the queue. */
+	root_node = scene->theDag->DagNode.first;
+	root_node->scheduled = true;
+	func(root_node, user_data);
 }
 
 /* This function is called when handling node is done.
@@ -2772,8 +2757,8 @@
 				bool need_schedule;
 
 				BLI_spin_lock(&threaded_update_lock);
-				need_schedule = child_node->color == DAG_WHITE;
-				child_node->color = DAG_BLACK;
+				need_schedule = child_node->scheduled == false;
+				child_node->scheduled = true;
 				BLI_spin_unlock(&threaded_update_lock);
 
 				if (need_schedule) {
@@ -2810,62 +2795,66 @@
 	DagNode *node;
 
 	for (node = scene->theDag->DagNode.first; node; node = node->next) {
-		node->color = DAG_BLACK;
+		node->tag = false;
 	}
 }
 
-void DAG_tag_condition_nodes(Scene *scene,
-                             bool (*condition) (void *node_v, void *user_data),
-                             void *user_data)
+void DAG_tag_node_for_object(Scene *scene, void *object)
 {
-	DagNode *node;
+	DagNode *node = dag_get_node(scene->theDag, object);
 
-	for (node = scene->theDag->DagNode.first; node; node = node->next) {
-		if (condition(node, user_data)) {
-			node->color = DAG_WHITE;
-		}
-	}
+	node->tag = true;
 }
 
-static void tag_flush_recurs(DagNode *node)
+void DAG_tag_flush_nodes(Scene *scene)
 {
-	DagAdjList *itA;
-	int color = node->color;
+	DagNodeQueue *node_queue;
+	DagNode *node, *root_node;
 
-	/* Quick hack for recursion detection. */
-	if (node->color == DAG_GRAY) {
-		return;
+	node_queue = queue_create(DAGQUEUEALLOC);
+
+	for (node = scene->theDag->DagNode.first; node; node = node->next) {
+		node->color = DAG_WHITE;
 	}
-	node->color = DAG_GRAY;
 
-	for (itA = node->child; itA; itA = itA->next) {
-		if (itA->node != node) {
-			tag_flush_recurs(itA->node);
+	root_node = scene->theDag->DagNode.first;
+	root_node->color = DAG_GRAY;
+	push_stack(node_queue, root_node);
 
+	while (node_queue->count) {
+		DagAdjList *itA;
+		bool has_new_nodes = false;
+
+		node = get_top_node_queue(node_queue);
+
+		/* Schedule all child nodes. */
+		for (itA = node->child; itA; itA = itA->next) {
 			if (itA->node->color == DAG_WHITE) {
-				color = DAG_WHITE;
+				itA->node->color = DAG_GRAY;
+				push_stack(node_queue, itA->node);
+				has_new_nodes = true;
 			}
 		}
-	}
 
-	node->color = color;
-}
+		if (!has_new_nodes) {
+			node = pop_queue(node_queue);
+			if (node->ob == scene) {
+				break;
+			}
 
-void DAG_tag_flush_nodes(Scene *scene)
-{
-	tag_flush_recurs(scene->theDag->DagNode.first);
-}
+			/* Flush tag from child to current node. */
+			for (itA = node->child; itA; itA = itA->next) {
+				if (itA->node->tag) {
+					node->tag = true;
+					break;
+				}
+			}
 
-void DAG_foreach_tagged_nodes(Scene *scene, void (*callback) (void *node_v, void *user_data),
-                              void *user_data)
-{
-	DagNode *node;
-
-	for (node = scene->theDag->DagNode.first; node; node = node->next) {
-		if (node->color == DAG_WHITE) {
-			callback(node, user_data);
+			node->color = DAG_BLACK;
 		}
 	}
+
+	queue_delete(node_queue);
 }
 
 /* Will return Object ID if node represents Object,
@@ -2889,3 +2878,10 @@
 
 	return dag_node_name(node);
 }
+
+bool DAG_get_node_tag(void *node_v)
+{
+	DagNode *node = node_v;
+
+	return node->tag;
+}

Modified: branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/object.c
===================================================================
--- branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/object.c	2013-09-02 17:28:00 UTC (rev 59745)
+++ branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/object.c	2013-09-02 17:33:34 UTC (rev 59746)
@@ -2750,20 +2750,6 @@
 							makeDerivedMesh(scene, ob, NULL, data_mask, 0);
 						}
 					}
-					else {
-						/* TODO(sergey): Maybe no need to create derivedRender in advance?
-						 *               On the other hand, this might allow us doing a threaded update.
-						 */
-
-						/* TODO(sergey): For now the same mask as in convertblender.c */
-						uint64_t data_mask = CD_MASK_BAREMESH | CD_MASK_MTFACE | CD_MASK_MCOL;
-
-						/* TODO(sergey): We need to load changes from editMesh here,
-						 *               render DM is up-to-date with current changes from dit mode.
-						 */
-
-						makeDerivedMeshRender(scene, ob, data_mask);
-					}
 					break;
 				}
 				case OB_ARMATURE:
@@ -2782,9 +2768,6 @@
 					if (evaluation_context->for_render == false) {
 						BKE_displist_make_mball(scene, ob);
 					}
-					else {
-						/* nothing for now. */
-					}
 					break;
 
 				case OB_CURVE:
@@ -2793,18 +2776,12 @@
 					if (evaluation_context->for_render == false) {
 						BKE_displist_make_curveTypes(scene, ob, 0);
 					}
-					else {
-						/* nothing for now. */
-					}
 					break;
 				
 				case OB_LATTICE:
 					if (evaluation_context->for_render == false) {
 						BKE_lattice_modifiers_calc(scene, ob);
 					}
-					else {
-						/* nothing for now. */
-					}
 					break;
 			}
 			

Modified: branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/scene.c
===================================================================
--- branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/scene.c	2013-09-02 17:28:00 UTC (rev 59745)
+++ branches/soc-2013-depsgraph_mt/source/blender/blenkernel/intern/scene.c	2013-09-02 17:33:34 UTC (rev 59746)
@@ -1337,13 +1337,6 @@
 		return;
 	}
 
-	/* Ensure malloc will go go fine from threads,
-	 * this is needed because we could be in main thread here
-	 * and malloc could be non-threda safe at this point because
-	 * no other jobs are running.
-	 */
-	BLI_begin_threaded_malloc();
-
 	state.evaluation_context = evaluation_context;
 	state.scene = scene;

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list