[Bf-blender-cvs] [a09accb496d] master: Geometry Nodes: speedup compute context hash generation

Jacques Lucke noreply at git.blender.org
Thu Dec 29 20:46:45 CET 2022


Commit: a09accb496d3b0f0fb11f5e36a95c607d62ba4c6
Author: Jacques Lucke
Date:   Thu Dec 29 20:45:51 2022 +0100
Branches: master
https://developer.blender.org/rBa09accb496d3b0f0fb11f5e36a95c607d62ba4c6

Geometry Nodes: speedup compute context hash generation

Whenever a node group is entered during evaluation, a new compute
context is entered which has a corresponding hash. When node groups
are entered and exited a lot, this can have some overhead. In my test
file with ~100.000 node group invocations, this patch improves performance
by about 7%.

The speedup is achieved in two ways:
* Avoid computing the same hash twice by caching it.
* Invoke the hashing algorithm (md5 currently) only once instead of twice.

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

M	source/blender/blenkernel/BKE_compute_contexts.hh
M	source/blender/blenkernel/intern/compute_contexts.cc
M	source/blender/nodes/intern/geometry_nodes_lazy_function.cc

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

diff --git a/source/blender/blenkernel/BKE_compute_contexts.hh b/source/blender/blenkernel/BKE_compute_contexts.hh
index 8e4bbbba524..92a6a06433c 100644
--- a/source/blender/blenkernel/BKE_compute_contexts.hh
+++ b/source/blender/blenkernel/BKE_compute_contexts.hh
@@ -6,6 +6,8 @@
  * This file implements some specific compute contexts for concepts in Blender.
  */
 
+#include <optional>
+
 #include "BLI_compute_context.hh"
 
 struct bNode;
@@ -41,7 +43,9 @@ class NodeGroupComputeContext : public ComputeContext {
 #endif
 
  public:
-  NodeGroupComputeContext(const ComputeContext *parent, int32_t node_id);
+  NodeGroupComputeContext(const ComputeContext *parent,
+                          int32_t node_id,
+                          const std::optional<ComputeContextHash> &cached_hash = {});
   NodeGroupComputeContext(const ComputeContext *parent, const bNode &node);
 
   int32_t node_id() const
diff --git a/source/blender/blenkernel/intern/compute_contexts.cc b/source/blender/blenkernel/intern/compute_contexts.cc
index 4d0fba49f85..2fc4a31f6c9 100644
--- a/source/blender/blenkernel/intern/compute_contexts.cc
+++ b/source/blender/blenkernel/intern/compute_contexts.cc
@@ -19,11 +19,26 @@ void ModifierComputeContext::print_current_in_line(std::ostream &stream) const
   stream << "Modifier: " << modifier_name_;
 }
 
-NodeGroupComputeContext::NodeGroupComputeContext(const ComputeContext *parent, const int node_id)
+NodeGroupComputeContext::NodeGroupComputeContext(
+    const ComputeContext *parent,
+    const int node_id,
+    const std::optional<ComputeContextHash> &cached_hash)
     : ComputeContext(s_static_type, parent), node_id_(node_id)
 {
-  hash_.mix_in(s_static_type, strlen(s_static_type));
-  hash_.mix_in(&node_id_, sizeof(int32_t));
+  if (cached_hash.has_value()) {
+    hash_ = *cached_hash;
+  }
+  else {
+    /* Mix static type and node id into a single buffer so that only a single call to #mix_in is
+     * necessary. */
+    const int type_size = strlen(s_static_type);
+    const int buffer_size = type_size + 1 + sizeof(int32_t);
+    DynamicStackBuffer<64, 8> buffer_owner(buffer_size, 8);
+    char *buffer = static_cast<char *>(buffer_owner.buffer());
+    memcpy(buffer, s_static_type, type_size + 1);
+    memcpy(buffer + type_size + 1, &node_id_, sizeof(int32_t));
+    hash_.mix_in(buffer, buffer_size);
+  }
 }
 
 NodeGroupComputeContext::NodeGroupComputeContext(const ComputeContext *parent, const bNode &node)
diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
index 57033e89bf7..a8eb532ab3f 100644
--- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
+++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
@@ -601,6 +601,12 @@ class LazyFunctionForGroupNode : public LazyFunction {
   std::optional<GeometryNodesLazyFunctionSideEffectProvider> lf_side_effect_provider_;
   std::optional<lf::GraphExecutor> graph_executor_;
 
+  struct Storage {
+    void *graph_executor_storage = nullptr;
+    /* To avoid computing the hash more than once. */
+    std::optional<ComputeContextHash> context_hash_cache;
+  };
+
  public:
   LazyFunctionForGroupNode(const bNode &group_node,
                            const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
@@ -662,9 +668,13 @@ class LazyFunctionForGroupNode : public LazyFunction {
       params.set_default_remaining_outputs();
     }
 
+    Storage *storage = static_cast<Storage *>(context.storage);
+
     /* The compute context changes when entering a node group. */
-    bke::NodeGroupComputeContext compute_context{user_data->compute_context,
-                                                 group_node_.identifier};
+    bke::NodeGroupComputeContext compute_context{
+        user_data->compute_context, group_node_.identifier, storage->context_hash_cache};
+    storage->context_hash_cache = compute_context.hash();
+
     GeoNodesLFUserData group_user_data = *user_data;
     group_user_data.compute_context = &compute_context;
     if (user_data->modifier_data->socket_log_contexts) {
@@ -674,18 +684,23 @@ class LazyFunctionForGroupNode : public LazyFunction {
 
     lf::Context group_context = context;
     group_context.user_data = &group_user_data;
+    group_context.storage = storage->graph_executor_storage;
 
     graph_executor_->execute(params, group_context);
   }
 
   void *init_storage(LinearAllocator<> &allocator) const override
   {
-    return graph_executor_->init_storage(allocator);
+    Storage *s = allocator.construct<Storage>().release();
+    s->graph_executor_storage = graph_executor_->init_storage(allocator);
+    return s;
   }
 
   void destruct_storage(void *storage) const override
   {
-    graph_executor_->destruct_storage(storage);
+    Storage *s = static_cast<Storage *>(storage);
+    graph_executor_->destruct_storage(s->graph_executor_storage);
+    std::destroy_at(s);
   }
 };



More information about the Bf-blender-cvs mailing list