[Bf-blender-cvs] [6bfe5e6] depsgraph_refactor: Extended scheduler implementation, adding task pools.

Lukas Tönne noreply at git.blender.org
Sun May 25 11:18:26 CEST 2014


Commit: 6bfe5e63aa85ddf96f3b512a5df1ec3c6f6bad84
Author: Lukas Tönne
Date:   Sun May 25 11:09:01 2014 +0200
https://developer.blender.org/rB6bfe5e63aa85ddf96f3b512a5df1ec3c6f6bad84

Extended scheduler implementation, adding task pools.

This is a concept added by Cycles and the current depsgraph. It allows
sorting tasks into groups (pools) and wait/stop/cancel them based on
these groups.

This might come in handy later for different evaluation contexts.

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

M	source/blender/blenkernel/intern/scene.c
M	source/blender/depsgraph/CMakeLists.txt
M	source/blender/depsgraph/intern/depsgraph_eval.cpp
M	source/blender/depsgraph/intern/depsgraph_eval.h
A	source/blender/depsgraph/util/depsgraph_util_task.cpp
A	source/blender/depsgraph/util/depsgraph_util_task.h
M	source/blender/depsgraph/util/depsgraph_util_thread.h

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

diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index dc82661..80a5c88 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1550,7 +1550,7 @@ void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *sc
 {
 	Scene *sce_iter;
 	
-	/********* new depsgraph *********/\
+	/********* new depsgraph *********/
 	if (scene->depsgraph)
 		DEG_evaluate_on_refresh(scene->depsgraph, eval_ctx->for_render ? DEG_EVALUATION_CONTEXT_RENDER : DEG_EVALUATION_CONTEXT_VIEWPORT);
 	/******************/
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 803c316..2a52114 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -76,6 +76,8 @@ set(SRC
 	util/depsgraph_util_rna.h
 	util/depsgraph_util_set.h
 	util/depsgraph_util_string.h
+	util/depsgraph_util_task.h
+	util/depsgraph_util_task.cpp
 	util/depsgraph_util_thread.h
 	util/depsgraph_util_type_traits.h
 )
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cpp b/source/blender/depsgraph/intern/depsgraph_eval.cpp
index 60bd6fa..1b41e98 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cpp
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cpp
@@ -73,13 +73,13 @@ extern "C" {
 /* Initialise threading lock - called during application startup */
 void DEG_threaded_init(void)
 {
-	Scheduler::init();
+	DepsgraphTaskScheduler::init();
 }
 
 /* Free threading lock - called during application shutdown */
 void DEG_threaded_exit(void)
 {
-	Scheduler::exit();
+	DepsgraphTaskScheduler::exit();
 }
 
 /* *************************************************** */
@@ -120,140 +120,6 @@ static void deg_exec_node(Depsgraph *graph, DepsNode *node, eEvaluationContextTy
 	/* NOTE: "generic" nodes cannot be executed, but will still end up calling this */
 }
 
-EvalQueue Scheduler::queue;
-ThreadMutex Scheduler::queue_mutex;
-ThreadCondition Scheduler::queue_cond;
-ThreadMutex Scheduler::mutex;
-Scheduler::Threads Scheduler::threads;
-bool Scheduler::do_exit;
-
-void Scheduler::init(int num_threads)
-{
-	BLI_mutex_init(&mutex);
-	BLI_mutex_init(&queue_mutex);
-	BLI_condition_init(&queue_cond);
-	
-	do_exit = false;
-	
-	if(num_threads == 0) {
-		/* automatic number of threads */
-		num_threads = BLI_system_thread_count();
-	}
-	
-	/* launch threads that will be waiting for work */
-	threads.resize(num_threads);
-	
-	for(size_t i = 0; i < threads.size(); i++)
-		threads[i] = new Thread((Thread::run_cb_t)Scheduler::thread_run, i);
-}
-
-void Scheduler::exit()
-{
-	/* stop all waiting threads */
-	do_exit = true;
-	BLI_condition_notify_all(&queue_cond);
-	
-	/* delete threads */
-	for (Threads::const_iterator it = threads.begin(); it != threads.end(); ++it) {
-		Thread *t = *it;
-		t->join();
-		delete t;
-	}
-	threads.clear();
-	
-	BLI_mutex_end(&mutex);
-	BLI_mutex_end(&queue_mutex);
-	BLI_condition_end(&queue_cond);
-}
-
-bool Scheduler::thread_wait_pop(DepsgraphTask &task)
-{
-	BLI_mutex_lock(&queue_mutex);
-
-	while(queue.empty() && !do_exit)
-		BLI_condition_wait(&queue_cond, &queue_mutex);
-
-	if(queue.empty()) {
-		BLI_assert(do_exit);
-		return false;
-	}
-	
-	task = queue.top();
-	queue.pop();
-	
-	BLI_mutex_unlock(&queue_mutex);
-	
-	return true;
-}
-
-void Scheduler::thread_run(Thread *thread)
-{
-	DepsgraphTask task;
-
-	/* keep popping off tasks */
-	while(thread_wait_pop(task)) {
-		/* run task */
-		
-		deg_exec_node(task.graph, task.node, task.context_type);
-		
-		/* notify pool task was done */
-		finish_node(task.graph, task.context_type, task.node);
-	}
-}
-
-static bool is_node_ready(OperationDepsNode *node)
-{
-	return (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) && node->num_links_pending == 0;
-}
-
-void Scheduler::schedule_graph(Depsgraph *graph, eEvaluationContextType context_type)
-{
-	BLI_mutex_lock(&queue_mutex);
-	
-	for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); it != graph->operations.end(); ++it) {
-		OperationDepsNode *node = *it;
-		
-		if (is_node_ready(node)) {
-			schedule_node(graph, context_type, node);
-		}
-	}
-	
-	BLI_mutex_unlock(&queue_mutex);
-}
-
-void Scheduler::schedule_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node)
-{
-	DepsgraphTask task;
-	task.graph = graph;
-	task.node = node;
-	task.context_type = context_type;
-	
-	queue.push(task);
-}
-
-void Scheduler::finish_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node)
-{
-	bool notify = false;
-	
-	BLI_mutex_lock(&queue_mutex);
-	
-	for (OperationDepsNode::Relations::const_iterator it = node->outlinks.begin(); it != node->outlinks.end(); ++it) {
-		DepsRelation *rel = *it;
-		
-		BLI_assert(rel->to->num_links_pending > 0);
-		--rel->to->num_links_pending;
-		if (rel->to->num_links_pending == 0) {
-			schedule_node(graph, context_type, rel->to);
-			notify = true;
-		}
-	}
-	
-	BLI_mutex_unlock(&queue_mutex);
-	
-	if (notify)
-		BLI_condition_notify_all(&queue_cond);
-}
-
 /* *************************************************** */
 /* Evaluation Entrypoints */
 
@@ -295,6 +161,23 @@ static void calculate_eval_priority(OperationDepsNode *node)
 		node->eval_priority = 0.0f;
 }
 
+static bool is_node_ready(OperationDepsNode *node)
+{
+	return (node->flag & DEPSOP_FLAG_NEEDS_UPDATE) && node->num_links_pending == 0;
+}
+
+static void schedule_graph(DepsgraphTaskPool &pool, Depsgraph *graph, eEvaluationContextType context_type)
+{
+	for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); it != graph->operations.end(); ++it) {
+		OperationDepsNode *node = *it;
+		
+		if (is_node_ready(node)) {
+			/* XXX TODO */
+//			pool.push();
+//			schedule_node(graph, context_type, node);
+		}
+	}
+}
 
 
 /* Evaluate all nodes tagged for updating 
@@ -306,6 +189,9 @@ void DEG_evaluate_on_refresh(Depsgraph *graph, eEvaluationContextType context_ty
 	/* generate base evaluation context, upon which all the others are derived... */
 	// TODO: this needs both main and scene access...
 	
+	/* XXX could use a separate pool for each eval context */
+	static DepsgraphTaskPool task_pool = DepsgraphTaskPool();
+	
 	/* clear tags */
 	for (Depsgraph::OperationNodes::const_iterator it = graph->operations.begin(); it != graph->operations.end(); ++it) {
 		OperationDepsNode *node = *it;
@@ -322,7 +208,7 @@ void DEG_evaluate_on_refresh(Depsgraph *graph, eEvaluationContextType context_ty
 	
 	DEG_debug_eval_step("Eval Priority Calculation");
 	
-	Scheduler::schedule_graph(graph, context_type);
+	schedule_graph(task_pool, graph, context_type);
 	
 	/* from the root node, start queuing up nodes to evaluate */
 	// ... start scheduler, etc.
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.h b/source/blender/depsgraph/intern/depsgraph_eval.h
index 4bfd63e..0eca9c1 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.h
+++ b/source/blender/depsgraph/intern/depsgraph_eval.h
@@ -33,12 +33,9 @@
 #ifndef __DEPSGRAPH_EVAL_TYPES_H__
 #define __DEPSGRAPH_EVAL_TYPES_H__
 
-#include <vector>
-
 #include "DEG_depsgraph.h"
 
-#include "depsgraph_util_priority_queue.h"
-#include "depsgraph_util_thread.h"
+#include "depsgraph_util_task.h"
 
 struct Depsgraph;
 struct OperationDepsNode;
@@ -131,52 +128,4 @@ typedef struct DEG_PoseContext {
 
 /* ****************************************** */
 
-struct DepsgraphTask {
-	Depsgraph *graph;
-	OperationDepsNode *node;
-	eEvaluationContextType context_type;
-};
-
-struct CompareDepsgraphTask {
-	bool operator() (const DepsgraphTask &a, const DepsgraphTask &b)
-	{
-		return a.node->eval_priority < b.node->eval_priority;
-	}
-};
-
-typedef priority_queue<DepsgraphTask, vector<DepsgraphTask>, CompareDepsgraphTask> EvalQueue;
-
-class Scheduler {
-public:
-	typedef std::vector<Thread*> Threads;
-	
-	static void init(int num_threads = 0);
-	static void exit();
-	
-	/* number of threads that can work on task */
-	static int num_threads() { return threads.size(); }
-	
-	static void schedule_graph(Depsgraph *graph, eEvaluationContextType context_type);
-	static void schedule_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node);
-	static void finish_node(Depsgraph *graph, eEvaluationContextType context_type, OperationDepsNode *node);
-	
-	static EvalQueue queue;
-	static ThreadMutex queue_mutex;
-	static ThreadCondition queue_cond;
-	/* XXX consider using spin lock here */
-	
-	static void thread_run(Thread *thread);
-	static bool thread_wait_pop(DepsgraphTask &task);
-	
-	//static void push(Entry& entry, bool front);
-	//static void clear(TaskPool *pool);
-	
-private:
-	static ThreadMutex mutex;
-	static Threads threads;
-	static bool do_exit;
-};
-
-/* ****************************************** */
-
 #endif // __DEPSGRAPH_EVAL_TYPES_H__
diff --git a/source/blender/depsgraph/util/depsgraph_util_task.cpp b/source/blender/depsgraph/util/depsgraph_util_task.cpp
new file mode 100644
index 0000000..e5906be
--- /dev/null
+++ b/source/blender/depsgraph/util/depsgraph_util_task.cpp
@@ -0,0 +1,341 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Brecht van Lommel
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include "BLI_utildefines.h"
+
+#include "depsgraph_util_task.h"
+
+/*

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list