[Bf-blender-cvs] [f65ea4cfbe8] temp-viewport-compositor-compiler: Viewport Compositor: Publicly expose compiler class
Omar Emara
noreply at git.blender.org
Tue Feb 15 09:38:40 CET 2022
Commit: f65ea4cfbe80c22004cf3212abf363c9b9dff46c
Author: Omar Emara
Date: Mon Feb 14 13:57:11 2022 +0200
Branches: temp-viewport-compositor-compiler
https://developer.blender.org/rBf65ea4cfbe80c22004cf3212abf363c9b9dff46c
Viewport Compositor: Publicly expose compiler class
This patch adds the compiler class to the public header file to be used
by the compositor engine.
===================================================================
M source/blender/nodes/NOD_compositor_execute.hh
M source/blender/nodes/intern/node_compositor_execute.cc
===================================================================
diff --git a/source/blender/nodes/NOD_compositor_execute.hh b/source/blender/nodes/NOD_compositor_execute.hh
index ff93b5954f4..de257629d4f 100644
--- a/source/blender/nodes/NOD_compositor_execute.hh
+++ b/source/blender/nodes/NOD_compositor_execute.hh
@@ -19,11 +19,15 @@
#include "BLI_hash.hh"
#include "BLI_map.hh"
#include "BLI_vector.hh"
+#include "BLI_vector_set.hh"
+#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "GPU_texture.h"
+#include "NOD_derived_node_tree.hh"
+
namespace blender::compositor {
/* --------------------------------------------------------------------
@@ -112,4 +116,46 @@ class CompositorContext {
virtual GPUTexture *get_pass_texture(int view_layer, eScenePassType pass_type) = 0;
};
+using namespace nodes::derived_node_tree_types;
+
+class Compiler {
+ private:
+ /* The derived and reference node trees representing the compositor setup. */
+ NodeTreeRefMap tree_ref_map_;
+ DerivedNodeTree tree_;
+ /* The output node whose result should be computed and drawn. */
+ DNode output_node_;
+ /* Stores a heuristic estimation of the number of needed intermediate buffers
+ * to compute every node and all of its dependencies. */
+ Map<DNode, int> needed_buffers_;
+ /* An ordered set of nodes defining the schedule of node execution. */
+ VectorSet<DNode> node_schedule_;
+
+ public:
+ Compiler(bNodeTree *scene_node_tree);
+
+ void compile();
+
+ void dump_schedule();
+
+ private:
+ /* Computes the output node whose result should be computed and drawn, then store the result in
+ * output_node_. The output node is the node marked as NODE_DO_OUTPUT. If multiple types of
+ * output nodes are marked, then the preference will be CMP_NODE_COMPOSITE > CMP_NODE_VIEWER >
+ * CMP_NODE_SPLITVIEWER. */
+ void compute_output_node();
+
+ /* Computes a heuristic estimation of the number of needed intermediate buffers to compute this
+ * node and all of its dependencies. The method recursively computes the needed buffers for all
+ * node dependencies and stores them in the needed_buffers_ map. So the root/output node can be
+ * provided to compute the needed buffers for all nodes. */
+ int compute_needed_buffers(DNode node);
+
+ /* Computes the execution schedule of the nodes and stores the schedule in node_schedule_. This
+ * is essentially a post-order depth first traversal of the node tree from the output node to the
+ * leaf input nodes, with informed order of traversal of children based on a heuristic estimation
+ * of the number of needed_buffers. */
+ void compute_schedule(DNode node);
+};
+
} // namespace blender::compositor
diff --git a/source/blender/nodes/intern/node_compositor_execute.cc b/source/blender/nodes/intern/node_compositor_execute.cc
index 854bdfc180e..f341a2be8ef 100644
--- a/source/blender/nodes/intern/node_compositor_execute.cc
+++ b/source/blender/nodes/intern/node_compositor_execute.cc
@@ -15,8 +15,6 @@
*/
#include "BLI_map.hh"
-#include "BLI_set.hh"
-#include "BLI_string_ref.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BLI_vector_set.hh"
@@ -64,174 +62,144 @@ void TexturePool::release(GPUTexture *texture)
* Compiler.
*/
-class Compiler {
- public:
- private:
- /* The derived and reference node trees repressing the compositor setup. */
- NodeTreeRefMap tree_ref_map_;
- DerivedNodeTree tree_;
- /* The output node whose result should be computed and drawn. */
- DNode output_node_;
- /* Stores a heuristic estimation of the number of needed intermediate buffers
- * to compute every node and all of its dependencies. */
- Map<DNode, int> needed_buffers_;
- /* An ordered set of nodes defining the schedule of node execution. */
- VectorSet<DNode> node_schedule_;
-
- public:
- Compiler(bNodeTree *scene_node_tree) : tree_(*scene_node_tree, tree_ref_map_){};
-
- void compile()
- {
- compute_output_node();
- compute_needed_buffers(output_node_);
- compute_schedule(output_node_);
+Compiler::Compiler(bNodeTree *scene_node_tree) : tree_(*scene_node_tree, tree_ref_map_){};
+
+void Compiler::compile()
+{
+ compute_output_node();
+ compute_needed_buffers(output_node_);
+ compute_schedule(output_node_);
+}
+
+void Compiler::dump_schedule()
+{
+ for (const DNode &node : node_schedule_) {
+ std::cout << node->name() << std::endl;
}
+}
- void dump_schedule()
- {
- for (const DNode &node : node_schedule_) {
- std::cout << node->name() << std::endl;
+void Compiler::compute_output_node()
+{
+ const NodeTreeRef &root_tree = tree_.root_context().tree();
+ for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeComposite")) {
+ if (node->bnode()->flag & NODE_DO_OUTPUT) {
+ output_node_ = DNode(&tree_.root_context(), node);
+ return;
}
}
-
- private:
- /* Computes the output node whose result should be computed and drawn. The output node is the
- * node marked as NODE_DO_OUTPUT. If multiple types of output nodes are marked, then the
- * preference will be CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER. */
- void compute_output_node()
- {
- const NodeTreeRef &root_tree = tree_.root_context().tree();
- for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeComposite")) {
- if (node->bnode()->flag & NODE_DO_OUTPUT) {
- output_node_ = DNode(&tree_.root_context(), node);
- return;
- }
+ for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeViewer")) {
+ if (node->bnode()->flag & NODE_DO_OUTPUT) {
+ output_node_ = DNode(&tree_.root_context(), node);
+ return;
}
- for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeViewer")) {
- if (node->bnode()->flag & NODE_DO_OUTPUT) {
- output_node_ = DNode(&tree_.root_context(), node);
- return;
- }
+ }
+ for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) {
+ if (node->bnode()->flag & NODE_DO_OUTPUT) {
+ output_node_ = DNode(&tree_.root_context(), node);
+ return;
}
- for (const NodeRef *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) {
- if (node->bnode()->flag & NODE_DO_OUTPUT) {
- output_node_ = DNode(&tree_.root_context(), node);
+ }
+}
+
+/* Consider a node that takes n number of buffers as an input from a number of node dependencies,
+ * which we shall call the input nodes. The node also computes and outputs m number of buffers.
+ * In order for the node to compute its output, a number of intermediate buffers will be needed.
+ * Since the node takes n buffers and outputs m buffers, then the number of buffers directly
+ * needed by the node is (n + m). But each of the input buffers are computed by a node that, in
+ * turn, needs a number of buffers to compute its output. So the total number of buffers needed
+ * to compute the output of the node is max(n + m, d) where d is the number of buffers needed by
+ * the input node that needs the largest number of buffers. We only consider the input node that
+ * needs the largest number of buffers, because those buffers can be reused by any input node
+ * that needs a lesser number of buffers.
+ *
+ * If the node tree was, in fact, a tree, then this would be an accurate computation. However,
+ * the node tree is in fact a graph that allows output sharing, so the computation in this case
+ * is merely a heuristic estimation that works well in most cases. */
+int Compiler::compute_needed_buffers(DNode node)
+{
+ /* Compute the number of buffers that the node takes as an input as well as the number of
+ * buffers needed to compute the most demanding dependency node. */
+ int input_buffers = 0;
+ int buffers_needed_by_dependencies = 0;
+ for (const InputSocketRef *input_ref : node->inputs()) {
+ const DInputSocket input{node.context(), input_ref};
+ /* Only consider inputs that are linked, that is, those that take a buffer. */
+ input.foreach_origin_socket([&](const DSocket origin) {
+ input_buffers++;
+ /* The origin node was already computed before, so skip it. */
+ if (needed_buffers_.contains(origin.node())) {
return;
}
- }
+ /* Recursively compute the number of buffers needed to compute this dependency node. */
+ const int buffers_needed_by_origin = compute_needed_buffers(origin.node());
+ if (buffers_needed_by_origin > buffers_needed_by_dependencies) {
+ buffers_needed_by_dependencies = buffers_needed_by_origin;
+ }
+ });
}
- /* Computes a heuristic estimation of the number of needed intermediate buffers to compute this
- * node and all of its dependencies. The method recursively computes the needed buffers for all
- * node dependencies and stores them in the needed_buffers_ map. So the root/output node can be
- * provided to compute the needed buffers for all nodes.
- *
- * Consider a node that takes n number of buffers as an input from a number of node dependencies,
- * which we shall call the input nodes. The node also computes and outputs m number of buffers.
- * In order for the node to compute its output, a number of intermediate buffers will be needed.
- * Since the node takes n buffers and outputs m buffers, then the number of buffers directly
- * needed by the node is (n + m). But each of the input buffers are computed by a node that, in
- * turn, needs a number of buffers to compute its output. So the total number of buffers needed
- * to compute the output of the node is max(n + m, d) where d is the number of buffers needed by
- * the input node that needs the largest number of buffers. We only consider the input node that
- * needs the largest number of buffers, because those buffers can be reused by any input node
- * that needs a lesser number of buffers.
- *
- * If the node tree was, in fact, a tree, then this would be an accurate computation. However,
- * the node tree is in fact a graph that allows output sharing, so the computation in this case
- * is merely a heuristic estimation that works well in most cases. */
- int compute_needed_buffers(DNode node)
- {
- /* Compute the number of buffers that the node takes as an input as well a
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list