[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