Commit: 079b38f8def1143f1319d367fa32661926ecc8b0
Author: Jacques Lucke
Date: Thu Sep 8 16:37:35 2022 +0200
Branches: temp-geometry-nodes-evaluator-refactor
https://developer.blender.org/rB079b38f8def1143f1319d367fa32661926ecc8b0
comments
===================================================================
M source/blender/functions/FN_lazy_function_graph_executor.hh
M source/blender/functions/intern/lazy_function_graph_executor.cc
===================================================================
diff --git a/source/blender/functions/FN_lazy_function_graph_executor.hh
b/source/blender/functions/FN_lazy_function_graph_executor.hh
index cabc69f34ac..ad4098aeee6 100644
--- a/source/blender/functions/FN_lazy_function_graph_executor.hh
+++ b/source/blender/functions/FN_lazy_function_graph_executor.hh
@@ -4,6 +4,9 @@
/** \file
* \ingroup fn
+ *
+ * This file provides means to create a #LazyFunction from #Graph (which could
then e.g. be used in
+ * another #Graph again).
*/
#include "BLI_vector.hh"
@@ -13,6 +16,9 @@
namespace blender::fn::lazy_function {
+/**
+ * Can be implemented to log values produced during graph evaluation.
+ */
class GraphExecutorLogger {
public:
virtual ~GraphExecutorLogger() = default;
@@ -22,6 +28,11 @@ class GraphExecutorLogger {
GPointer value) const;
};
+/**
+ * Has to be implemented when some of the nodes in the graph may have side
effects. The
+ * #GraphExecutor has to know about that to make sure that these nodes will be
executed even though
+ * their outputs are not needed.
+ */
class GraphExecutorSideEffectProvider {
public:
virtual ~GraphExecutorSideEffectProvider() = default;
diff --git a/source/blender/functions/intern/lazy_function_graph_executor.cc
b/source/blender/functions/intern/lazy_function_graph_executor.cc
index 97393b04f8e..b6b3ca591bc 100644
--- a/source/blender/functions/intern/lazy_function_graph_executor.cc
+++ b/source/blender/functions/intern/lazy_function_graph_executor.cc
@@ -1,5 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+/**
+ * This file implements the evaluation of a lazy-function graph. It's main
objectices are:
+ * - Only compute values that are actually used.
+ * - Allow to spread the work over an arbitrary number of CPU cores.
+ *
+ * Other (simpler) executors with different main objectives could be
implemented in the future. For
+ * some scenarios those could be simpler when many nodes do very little work
or most nodes have to
+ * be processed sequentially. Those assumptions make the first and second
objective less important
+ * respectively.
+ *
+ * The design implemented in this executor requires *no* main thread that
coordinates everything.
+ * Instead, one thread will trigger some initial work and then many threads
coordinate themselves
+ * in a distributed fashion. In an ideal situation, every thread ends up
processing a separate part
+ * of the graph which results in less communication overhead. The way TBB
schedules tasks helps
+ * with that: a thread will next process the task that it added to a task pool
just before.
+ *
+ * Communication between threads is synchronized by using a mutex in every
node. When a thread
+ * wants to access the state of a node, its mutex has to be locked first
(there some documented
+ * exceptions) to that. The assumption here is that most nodes are only ever
touched by a single
+ * thread and therefore the lock contention is reduced the more nodes there
are.
+ *
+ * Similar to how a #LazyFunction can be thought of as a state machine (see
`FN_lazy_function.hh`),
+ * each node can also be thought of as a state machine. The state of a node
contains the evaluation
+ * state of its inputs and outputs. Every time a node is executed, it has to
advance its state in
+ * some way (e.g. it requests a new input or computes a new output).
+ *
+ * At the core of the executor is a task pool. Every task in that pool
represents a node execution.
+ * When a node is executed it may send notifications to other nodes which may
in turn add those
+ * nodes to the task pool. For example, the current node has computed one of
its outputs, then the
+ * computed value is forwarded to all linked inputs, changing their node
states in the process. If
+ * this input was the last missing required input, the node will be added to
the task pool so that
+ * it is executed next.
+ *
+ * When the task pool is empty, the executor gives back control to the caller
which may later
+ * provide new inputs to the graph which in turn adds new nodes to the task
pool and the process
+ * starts again.
+ */
+
#include <mutex>
#include "BLI_enumerable_thread_specific.hh"
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs