[Bf-blender-cvs] [83f519b7c18] master: Functions: initialize node storage and default values on first execution

Jacques Lucke noreply at git.blender.org
Wed Jan 4 18:47:46 CET 2023


Commit: 83f519b7c18f68d5410610bdbcc90fe7b425f50a
Author: Jacques Lucke
Date:   Wed Jan 4 18:46:16 2023 +0100
Branches: master
https://developer.blender.org/rB83f519b7c18f68d5410610bdbcc90fe7b425f50a

Functions: initialize node storage and default values on first execution

Previously, this happened when the "node task" first runs, which might
not actually execute the node if there are missing inputs. Deferring the
allocation of storage and default inputs allows for better memory reuse
later (currently the memory is not reused).

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

M	source/blender/functions/intern/lazy_function_graph_executor.cc

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

diff --git a/source/blender/functions/intern/lazy_function_graph_executor.cc b/source/blender/functions/intern/lazy_function_graph_executor.cc
index b9cf3a82bcb..fc74b3cd213 100644
--- a/source/blender/functions/intern/lazy_function_graph_executor.cc
+++ b/source/blender/functions/intern/lazy_function_graph_executor.cc
@@ -151,9 +151,15 @@ struct NodeState {
    */
   bool node_has_finished = false;
   /**
-   * Set to true once the node is done running for the first time.
+   * Set to true once the always required inputs have been requested.
+   * This happens the first time the node is run.
    */
-  bool had_initialization = false;
+  bool always_used_inputs_requested = false;
+  /**
+   * Set to true when the storage and defaults have been initialized.
+   * This happens the first time the node function is executed.
+   */
+  bool storage_and_defaults_initialized = false;
   /**
    * Nodes with side effects should always be executed when their required inputs have been
    * computed.
@@ -729,39 +735,20 @@ class Executor {
         return;
       }
 
-      if (!node_state.had_initialization) {
-        /* Initialize storage. */
-        node_state.storage = fn.init_storage(allocator);
-
-        /* Load unlinked inputs. */
-        for (const int input_index : node.inputs().index_range()) {
-          const InputSocket &input_socket = node.input(input_index);
-          if (input_socket.origin() != nullptr) {
-            continue;
-          }
-          InputState &input_state = node_state.inputs[input_index];
-          const CPPType &type = input_socket.type();
-          const void *default_value = input_socket.default_value();
-          BLI_assert(default_value != nullptr);
-          if (self_.logger_ != nullptr) {
-            self_.logger_->log_socket_value(input_socket, {type, default_value}, *context_);
-          }
-          void *buffer = allocator.allocate(type.size(), type.alignment());
-          type.copy_construct(default_value, buffer);
-          this->forward_value_to_input(locked_node, input_state, {type, buffer}, current_task);
-        }
-
+      if (!node_state.always_used_inputs_requested) {
         /* Request linked inputs that are always needed. */
         const Span<Input> fn_inputs = fn.inputs();
         for (const int input_index : fn_inputs.index_range()) {
           const Input &fn_input = fn_inputs[input_index];
           if (fn_input.usage == ValueUsage::Used) {
             const InputSocket &input_socket = node.input(input_index);
-            this->set_input_required(locked_node, input_socket);
+            if (input_socket.origin() != nullptr) {
+              this->set_input_required(locked_node, input_socket);
+            }
           }
         }
 
-        node_state.had_initialization = true;
+        node_state.always_used_inputs_requested = true;
       }
 
       for (const int input_index : node_state.inputs.index_range()) {
@@ -784,6 +771,32 @@ class Executor {
     });
 
     if (node_needs_execution) {
+      if (!node_state.storage_and_defaults_initialized) {
+        /* Initialize storage. */
+        node_state.storage = fn.init_storage(allocator);
+
+        /* Load unlinked inputs. */
+        for (const int input_index : node.inputs().index_range()) {
+          const InputSocket &input_socket = node.input(input_index);
+          if (input_socket.origin() != nullptr) {
+            continue;
+          }
+          InputState &input_state = node_state.inputs[input_index];
+          const CPPType &type = input_socket.type();
+          const void *default_value = input_socket.default_value();
+          BLI_assert(default_value != nullptr);
+          if (self_.logger_ != nullptr) {
+            self_.logger_->log_socket_value(input_socket, {type, default_value}, *context_);
+          }
+          BLI_assert(input_state.value == nullptr);
+          input_state.value = allocator.allocate(type.size(), type.alignment());
+          type.copy_construct(default_value, input_state.value);
+          input_state.was_ready_for_execution = true;
+        }
+
+        node_state.storage_and_defaults_initialized = true;
+      }
+
       /* Importantly, the node must not be locked when it is executed. That would result in locks
        * being hold very long in some cases and results in multiple locks being hold by the same
        * thread in the same graph which can lead to deadlocks. */



More information about the Bf-blender-cvs mailing list