[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