[Bf-blender-cvs] [3d1244c1342] temp-geometry-nodes-evaluator-refactor: comments

Jacques Lucke noreply at git.blender.org
Thu Sep 8 17:22:32 CEST 2022


Commit: 3d1244c1342e06a3cbeb26e87229640e579ac8f7
Author: Jacques Lucke
Date:   Thu Sep 8 16:07:02 2022 +0200
Branches: temp-geometry-nodes-evaluator-refactor
https://developer.blender.org/rB3d1244c1342e06a3cbeb26e87229640e579ac8f7

comments

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

M	source/blender/functions/FN_lazy_function_graph.hh
M	source/blender/functions/intern/lazy_function_graph.cc
M	source/blender/functions/intern/lazy_function_graph_executor.cc

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

diff --git a/source/blender/functions/FN_lazy_function_graph.hh b/source/blender/functions/FN_lazy_function_graph.hh
index 0826bfe7c21..4ede28c4f26 100644
--- a/source/blender/functions/FN_lazy_function_graph.hh
+++ b/source/blender/functions/FN_lazy_function_graph.hh
@@ -4,6 +4,15 @@
 
 /** \file
  * \ingroup fn
+ *
+ * This file contains a graph data structure that allows composing multiple lazy-functions into a
+ * combined lazy-function.
+ *
+ * There are two types of nodes in the graph:
+ * - #FunctionNode: Corresponds to a #LazyFunction. The inputs and outputs of the function become
+ *   input and output sockets of the node.
+ * - #DummyNode: Is used to indicate inputs and outputs of the entire graph. It can have an
+ *   arbitrary number of sockets.
  */
 
 #include "BLI_linear_allocator.hh"
@@ -18,11 +27,27 @@ class OutputSocket;
 class Node;
 class Graph;
 
+/**
+ * A #Socket is the interface of a #Node. Every #Socket is either an #InputSocket or #OutputSocket.
+ * Links can be created from output sockets to input sockets.
+ */
 class Socket : NonCopyable, NonMovable {
  protected:
+  /**
+   * The node the socket belongs to.
+   */
   Node *node_;
+  /**
+   * Data type of the socket. Only sockets with the same type can be linked.
+   */
   const CPPType *type_;
+  /**
+   * Indicates whether this is an #InputSocket or #OutputSocket.
+   */
   bool is_input_;
+  /**
+   * Index of the socket. E.g. 0 for the first input and the first output socket.
+   */
   int index_in_node_;
 
   friend Graph;
@@ -31,7 +56,7 @@ class Socket : NonCopyable, NonMovable {
   bool is_input() const;
   bool is_output() const;
 
-  int index_in_node() const;
+  int index() const;
 
   InputSocket &as_input();
   OutputSocket &as_output();
@@ -48,7 +73,20 @@ class Socket : NonCopyable, NonMovable {
 
 class InputSocket : public Socket {
  private:
+  /**
+   * An input can have at most one link connected to it. The linked socket is the "origin" because
+   * it's where the data is coming from. The type of the origin must be the same as the type of
+   * this socket.
+   */
   OutputSocket *origin_;
+  /**
+   * Can be null or a non-owning pointer to a value of the type of the socket. This value will be
+   * used when the input is used but not linked.
+   *
+   * This is technically not needed, because one could just create a separate node that just
+   * outputs the value, but that would have more overhead. Especially because it's commonly the
+   * case that most inputs are unlinked.
+   */
   const void *default_value_ = nullptr;
 
   friend Graph;
@@ -63,6 +101,9 @@ class InputSocket : public Socket {
 
 class OutputSocket : public Socket {
  private:
+  /**
+   * An output can be linked to an arbitrary number of inputs of the same type.
+   */
   Vector<InputSocket *> targets_;
 
   friend Graph;
@@ -72,11 +113,30 @@ class OutputSocket : public Socket {
   Span<const InputSocket *> targets() const;
 };
 
+/**
+ * A #Node has input and output sockets. Every node is either a #FunctionNode or a #DummyNode.
+ */
 class Node : NonCopyable, NonMovable {
  protected:
+  /**
+   * The function this node corresponds to. If this is null, the node is a #DummyNode.
+   * The function is not owned by this #Node nor by the #Graph.
+   */
   const LazyFunction *fn_ = nullptr;
+  /**
+   * Input sockets of the node.
+   */
   Span<InputSocket *> inputs_;
+  /**
+   * Output sockets of the node.
+   */
   Span<OutputSocket *> outputs_;
+  /**
+   * An index that is set when calling #Graph::update_node_indices. This can be used to create
+   * efficient mappings from nodes to other data using just an array instead of a hash map.
+   *
+   * This is technically not necessary but has better performance than always using hash maps.
+   */
   int index_in_graph_ = -1;
 
   friend Graph;
@@ -99,11 +159,18 @@ class Node : NonCopyable, NonMovable {
   std::string name() const;
 };
 
+/**
+ * A #Node that corresponds to a specific #LazyFunction.
+ */
 class FunctionNode : public Node {
  public:
   const LazyFunction &function() const;
 };
 
+/**
+ * A #Node that does *not* correspond to a #LazyFunction. Instead it can be used to indicate inputs
+ * and outputs of the entire graph. It can have an arbitrary number of inputs and outputs.
+ */
 class DummyNode : public Node {
  private:
   std::string name_;
@@ -111,24 +178,57 @@ class DummyNode : public Node {
   friend Node;
 };
 
+/**
+ * A container for an arbitrary number of nodes and links between their sockets.
+ */
 class Graph : NonCopyable, NonMovable {
  private:
+  /**
+   * Used to allocate nodes and sockets in the graph.
+   */
   LinearAllocator<> allocator_;
+  /**
+   * Contains all nodes in the graph so that it is efficient to iterate over them.
+   */
   Vector<Node *> nodes_;
 
  public:
   ~Graph();
 
+  /**
+   * Get all nodes in the graph. The index in the span corresponds to #Node::index_in_graph.
+   */
   Span<const Node *> nodes() const;
 
+  /**
+   * Add a new function node with sockets that match the passed in #LazyFunction.
+   */
   FunctionNode &add_function(const LazyFunction &fn);
+
+  /**
+   * Add a new dummy node with the given socket types.
+   */
   DummyNode &add_dummy(Span<const CPPType *> input_types, Span<const CPPType *> output_types);
+
+  /**
+   * Add a link between the two given sockets.
+   * This has undefined behavior when the input is linked to something else already.
+   */
   void add_link(OutputSocket &from, InputSocket &to);
-  void remove_link(OutputSocket &from, InputSocket &to);
 
+  /**
+   * Make sure that #Node::index_in_graph is up to date.
+   */
   void update_node_indices();
+
+  /**
+   * Can be used to assert that #update_node_indices has been called.
+   */
   bool node_indices_are_valid() const;
 
+  /**
+   * Utility to generate a dot graph string for the graph. This can be used for debugging.
+   */
   std::string to_dot() const;
 };
 
@@ -146,7 +246,7 @@ inline bool Socket::is_output() const
   return !is_input_;
 }
 
-inline int Socket::index_in_node() const
+inline int Socket::index() const
 {
   return index_in_node_;
 }
diff --git a/source/blender/functions/intern/lazy_function_graph.cc b/source/blender/functions/intern/lazy_function_graph.cc
index c60431d2c3d..cc55b70d166 100644
--- a/source/blender/functions/intern/lazy_function_graph.cc
+++ b/source/blender/functions/intern/lazy_function_graph.cc
@@ -83,14 +83,6 @@ void Graph::add_link(OutputSocket &from, InputSocket &to)
   from.targets_.append(&to);
 }
 
-void Graph::remove_link(OutputSocket &from, InputSocket &to)
-{
-  BLI_assert(to.origin_ == &from);
-  BLI_assert(from.targets_.contains(&to));
-  to.origin_ = nullptr;
-  from.targets_.remove_first_occurrence_and_reorder(&to);
-}
-
 void Graph::update_node_indices()
 {
   for (const int i : nodes_.index_range()) {
@@ -161,11 +153,11 @@ std::string Graph::to_dot() const
   for (const Node *node : nodes_) {
     for (const InputSocket *socket : node->inputs()) {
       const dot::NodeWithSocketsRef &to_dot_node = dot_nodes.lookup(&socket->node());
-      const dot::NodePort to_dot_port = to_dot_node.input(socket->index_in_node());
+      const dot::NodePort to_dot_port = to_dot_node.input(socket->index());
 
       if (const OutputSocket *origin = socket->origin()) {
         dot::NodeWithSocketsRef &from_dot_node = dot_nodes.lookup(&origin->node());
-        digraph.new_edge(from_dot_node.output(origin->index_in_node()), to_dot_port);
+        digraph.new_edge(from_dot_node.output(origin->index()), to_dot_port);
       }
       else if (const void *default_value = socket->default_value()) {
         const CPPType &type = socket->type();
diff --git a/source/blender/functions/intern/lazy_function_graph_executor.cc b/source/blender/functions/intern/lazy_function_graph_executor.cc
index 0e17d0a682c..97393b04f8e 100644
--- a/source/blender/functions/intern/lazy_function_graph_executor.cc
+++ b/source/blender/functions/intern/lazy_function_graph_executor.cc
@@ -371,7 +371,7 @@ class Executor {
       const OutputSocket &socket = *self_.graph_inputs_[i];
       const Node &node = socket.node();
       const NodeState &node_state = *node_states_[node.index_in_graph()];
-      const OutputState &output_state = node_state.outputs[socket.index_in_node()];
+      const OutputState &output_state = node_state.outputs[socket.index()];
       if (output_state.usage == ValueUsage::Unused) {
         params_->set_input_unused(i);
       }
@@ -428,7 +428,7 @@ class Executor {
   void notify_output_required(const OutputSocket &socket, CurrentTask &current_task)
   {
     const Node &node = socket.node();
-    const int index_in_node = socket.index_in_node();
+    const int index_in_node = socket.index();
     NodeState &node_state = *node_states_[node.index_in_graph()];
     OutputState &output_state = node_state.outputs[index_in_node];
 
@@ -464,7 +464,7 @@ class Executor {
   void notify_output_unused(const OutputSocket &socket, CurrentTask &current_task)
   {
     const Node &node = socket.node();
-    const int index_in_node = socket.index_in_node();
+    const int index_in_node = socket.index();
     NodeState &node_state = *node_states_[node.index_in_graph()];
     OutputState &output_state = node_state.outputs[index_in_node];
 
@@ -759,7 +759,7 @@ class Executor {
   void set_input_unused(LockedNode &locked_node, const InputSocket &input_socket)
   {
     NodeState &node_state = locked_node.node_state;
-    const int input_index = input_socket.index_in_node();
+    const int input_index = input_socket.index();
     InputState &input_state = node_state.inputs[input_index];
 
     BLI_assert(input_state.usage != ValueUsage::Used);
@@ -795,7 +795,7 @@ class Executor {
   {
     BLI_assert(&locked_node.node == &input_socket.node());
     NodeState &node_state = locked_node.node_state;
-    const int input_index = input_socket.index_in_node();
+    const int input_index = input_socket.index();
     InputState &input_state = node_state.inputs[input_index];
 
     BLI_assert(input_state.usage != ValueUsage::Unused);
@@ -833,7 +833,7 @@ class Executor {
     for (const InputSocket *target_socket : targets) {
       const Node &target_node = target_socket->node();
    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list