From be266a1c0c43213fe5b4b4d33553d11022b022e2 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 14 Apr 2025 17:47:56 +0200 Subject: [PATCH] Refactor: Geometry Nodes: replace ComputeContextBuilder with ComputeContextCache While `ComputeContextBuilder` worked well for building simple linear compute contexts, it was fairly limiting for all the slightly more complex cases where an entire tree of compute contexts is built. Using `ComputeContextCache` that is easier to do more explicitly. There were only very few cases where using `ComputeContextBuilder` would have still helped a bit, but it's not really worth keeping that abstraction around just for those few cases. Pull Request: https://projects.blender.org/blender/blender/pulls/137370 --- .../blenkernel/BKE_compute_context_cache.hh | 39 ++++++++ .../BKE_compute_context_cache_fwd.hh | 11 +++ source/blender/blenkernel/CMakeLists.txt | 1 + .../blenkernel/intern/compute_contexts.cc | 96 +++++++++++++++++++ source/blender/blenlib/BLI_compute_context.hh | 75 --------------- .../blender/blenlib/intern/compute_context.cc | 1 + .../editors/geometry/node_group_operator.cc | 6 +- source/blender/editors/include/ED_node.hh | 9 +- .../blender/editors/include/ED_viewer_path.hh | 10 +- .../blender/editors/space_node/node_draw.cc | 23 ++--- .../editors/space_node/node_shader_preview.cc | 8 +- .../blender/editors/space_node/space_node.cc | 30 +++--- .../view3d_gizmo_geometry_nodes.cc | 8 +- source/blender/editors/util/ed_viewer_path.cc | 35 ++++--- source/blender/modifiers/intern/MOD_nodes.cc | 27 +++--- .../NOD_geometry_nodes_closure_location.hh | 1 + .../nodes/NOD_geometry_nodes_gizmos.hh | 6 +- .../blender/nodes/NOD_geometry_nodes_log.hh | 4 +- .../nodes/intern/geometry_nodes_gizmos.cc | 60 ++++++------ .../nodes/intern/geometry_nodes_log.cc | 55 ++++++----- 20 files changed, 301 insertions(+), 204 deletions(-) create mode 100644 source/blender/blenkernel/BKE_compute_context_cache_fwd.hh diff --git a/source/blender/blenkernel/BKE_compute_context_cache.hh b/source/blender/blenkernel/BKE_compute_context_cache.hh index 11056c85829..c1dfad95ddc 100644 --- a/source/blender/blenkernel/BKE_compute_context_cache.hh +++ b/source/blender/blenkernel/BKE_compute_context_cache.hh @@ -4,8 +4,10 @@ #pragma once +#include "BKE_compute_context_cache_fwd.hh" #include "BKE_compute_contexts.hh" +#include "BLI_linear_allocator.hh" #include "BLI_map.hh" #include "BLI_vector.hh" @@ -28,8 +30,18 @@ class ComputeContextCache { Map, const ModifierComputeContext *> modifier_contexts_cache_; + Map operator_contexts_cache_; Map, const GroupNodeComputeContext *> group_node_contexts_cache_; + Map, const SimulationZoneComputeContext *> + simulation_zone_contexts_cache_; + Map>, const RepeatZoneComputeContext *> + repeat_zone_contexts_cache_; + Map>, + const ForeachGeometryElementZoneComputeContext *> + foreach_geometry_element_zone_contexts_cache_; + Map, const EvaluateClosureComputeContext *> + evaluate_closure_contexts_cache_; public: const ModifierComputeContext &for_modifier(const ComputeContext *parent, @@ -37,11 +49,38 @@ class ComputeContextCache { const ModifierComputeContext &for_modifier(const ComputeContext *parent, StringRef modifier_name); + const OperatorComputeContext &for_operator(const ComputeContext *parent); + const OperatorComputeContext &for_operator(const ComputeContext *parent, const bNodeTree &tree); + const GroupNodeComputeContext &for_group_node(const ComputeContext *parent, int32_t node_id); const GroupNodeComputeContext &for_group_node(const ComputeContext *parent, const bNode &caller_group_node, const bNodeTree &caller_tree); + const SimulationZoneComputeContext &for_simulation_zone(const ComputeContext *parent, + int output_node_id); + const SimulationZoneComputeContext &for_simulation_zone(const ComputeContext *parent, + const bNode &output_node); + + const RepeatZoneComputeContext &for_repeat_zone(const ComputeContext *parent, + int32_t output_node_id, + int iteration); + const RepeatZoneComputeContext &for_repeat_zone(const ComputeContext *parent, + const bNode &output_node, + int iteration); + + const ForeachGeometryElementZoneComputeContext &for_foreach_geometry_element_zone( + const ComputeContext *parent, int32_t output_node_id, int index); + const ForeachGeometryElementZoneComputeContext &for_foreach_geometry_element_zone( + const ComputeContext *parent, const bNode &output_node, int index); + + const EvaluateClosureComputeContext &for_evaluate_closure(const ComputeContext *parent, + int32_t node_id); + const EvaluateClosureComputeContext &for_evaluate_closure( + const ComputeContext *parent, + const bNode &evaluate_node, + const std::optional &closure_source_location); + /** * A fallback that does not use caching and can be used for any compute context. * More constructors like the ones above can be added as they become necessary. diff --git a/source/blender/blenkernel/BKE_compute_context_cache_fwd.hh b/source/blender/blenkernel/BKE_compute_context_cache_fwd.hh new file mode 100644 index 00000000000..ae7d6d98d46 --- /dev/null +++ b/source/blender/blenkernel/BKE_compute_context_cache_fwd.hh @@ -0,0 +1,11 @@ +/* SPDX-FileCopyrightText: 2025 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +namespace blender::bke { + +class ComputeContextCache; + +} diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 7f8d4df76f7..abdc7050394 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -365,6 +365,7 @@ set(SRC BKE_colortools.hh BKE_compositor.hh BKE_compute_context_cache.hh + BKE_compute_context_cache_fwd.hh BKE_compute_contexts.hh BKE_constraint.h BKE_context.hh diff --git a/source/blender/blenkernel/intern/compute_contexts.cc b/source/blender/blenkernel/intern/compute_contexts.cc index 1a57d29d168..df513b5979a 100644 --- a/source/blender/blenkernel/intern/compute_contexts.cc +++ b/source/blender/blenkernel/intern/compute_contexts.cc @@ -223,6 +223,19 @@ const ModifierComputeContext &ComputeContextCache::for_modifier(const ComputeCon }); } +const OperatorComputeContext &ComputeContextCache::for_operator(const ComputeContext *parent) +{ + return *operator_contexts_cache_.lookup_or_add_cb( + parent, [&]() { return &this->for_any_uncached(parent); }); +} + +const OperatorComputeContext &ComputeContextCache::for_operator(const ComputeContext *parent, + const bNodeTree &tree) +{ + return *operator_contexts_cache_.lookup_or_add_cb( + parent, [&]() { return &this->for_any_uncached(parent, tree); }); +} + const GroupNodeComputeContext &ComputeContextCache::for_group_node(const ComputeContext *parent, const int32_t node_id) { @@ -242,4 +255,87 @@ const GroupNodeComputeContext &ComputeContextCache::for_group_node(const Compute }); } +const SimulationZoneComputeContext &ComputeContextCache::for_simulation_zone( + const ComputeContext *parent, int output_node_id) +{ + return *simulation_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, output_node_id}, [&]() { + return &this->for_any_uncached(parent, output_node_id); + }); +} + +const SimulationZoneComputeContext &ComputeContextCache::for_simulation_zone( + const ComputeContext *parent, const bNode &output_node) +{ + return *simulation_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, output_node.identifier}, [&]() { + return &this->for_any_uncached(parent, output_node); + }); +} + +const RepeatZoneComputeContext &ComputeContextCache::for_repeat_zone(const ComputeContext *parent, + int32_t output_node_id, + int iteration) +{ + return *repeat_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, std::pair{output_node_id, iteration}}, [&]() { + return &this->for_any_uncached( + parent, output_node_id, iteration); + }); +} + +const RepeatZoneComputeContext &ComputeContextCache::for_repeat_zone(const ComputeContext *parent, + const bNode &output_node, + int iteration) +{ + return *repeat_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, std::pair{output_node.identifier, iteration}}, [&]() { + return &this->for_any_uncached(parent, output_node, iteration); + }); +} + +const ForeachGeometryElementZoneComputeContext &ComputeContextCache:: + for_foreach_geometry_element_zone(const ComputeContext *parent, + int32_t output_node_id, + int index) +{ + return *foreach_geometry_element_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, std::pair{output_node_id, index}}, [&]() { + return &this->for_any_uncached( + parent, output_node_id, index); + }); +} + +const ForeachGeometryElementZoneComputeContext &ComputeContextCache:: + for_foreach_geometry_element_zone(const ComputeContext *parent, + const bNode &output_node, + int index) +{ + return *foreach_geometry_element_zone_contexts_cache_.lookup_or_add_cb( + std::pair{parent, std::pair{output_node.identifier, index}}, [&]() { + return &this->for_any_uncached( + parent, output_node, index); + }); +} + +const EvaluateClosureComputeContext &ComputeContextCache::for_evaluate_closure( + const ComputeContext *parent, int32_t node_id) +{ + return *evaluate_closure_contexts_cache_.lookup_or_add_cb(std::pair{parent, node_id}, [&]() { + return &this->for_any_uncached(parent, node_id); + }); +} + +const EvaluateClosureComputeContext &ComputeContextCache::for_evaluate_closure( + const ComputeContext *parent, + const bNode &evaluate_node, + const std::optional &closure_source_location) +{ + return *evaluate_closure_contexts_cache_.lookup_or_add_cb( + std::pair{parent, evaluate_node.identifier}, [&]() { + return &this->for_any_uncached( + parent, evaluate_node, closure_source_location); + }); +} + } // namespace blender::bke diff --git a/source/blender/blenlib/BLI_compute_context.hh b/source/blender/blenlib/BLI_compute_context.hh index 7dca4124174..ccfc239f623 100644 --- a/source/blender/blenlib/BLI_compute_context.hh +++ b/source/blender/blenlib/BLI_compute_context.hh @@ -34,10 +34,6 @@ * run on different threads. */ -#include - -#include "BLI_linear_allocator.hh" -#include "BLI_stack.hh" #include "BLI_string_ref.hh" #include "BLI_struct_equality_utils.hh" @@ -125,75 +121,4 @@ class ComputeContext { friend std::ostream &operator<<(std::ostream &stream, const ComputeContext &compute_context); }; -/** - * Utility class to build a context stack in one place. This is typically used to get the hash that - * corresponds to a specific nested compute context, in order to look up corresponding logged - * values. - */ -class ComputeContextBuilder { - private: - LinearAllocator<> allocator_; - Stack> contexts_; - std::optional>> old_contexts_; - - public: - /** - * If called, compute contexts are not destructed when they are popped. Instead their lifetime - * will be the lifetime of this builder. - */ - void keep_old_contexts() - { - if (!old_contexts_.has_value()) { - old_contexts_.emplace(); - } - } - - bool is_empty() const - { - return contexts_.is_empty(); - } - - const ComputeContext *current() const - { - if (contexts_.is_empty()) { - return nullptr; - } - return contexts_.peek().get(); - } - - ComputeContextHash hash() const - { - BLI_assert(!contexts_.is_empty()); - return this->current()->hash(); - } - - template void push(Args &&...args) - { - const ComputeContext *current = this->current(); - destruct_ptr context = allocator_.construct(current, std::forward(args)...); - contexts_.push(std::move(context)); - } - - void pop() - { - auto context = contexts_.pop(); - if (old_contexts_) { - old_contexts_->append(std::move(context)); - } - } - - /** Pops all compute contexts until the given one is at the top. */ - void pop_until(const ComputeContext *context) - { - while (!contexts_.is_empty()) { - if (contexts_.peek().get() == context) { - return; - } - this->pop(); - } - /* Should have found the context above if it's not null. */ - BLI_assert(context == nullptr); - } -}; - } // namespace blender diff --git a/source/blender/blenlib/intern/compute_context.cc b/source/blender/blenlib/intern/compute_context.cc index 691457f4a8f..c992b8c517c 100644 --- a/source/blender/blenlib/intern/compute_context.cc +++ b/source/blender/blenlib/intern/compute_context.cc @@ -7,6 +7,7 @@ */ #include "BLI_compute_context.hh" +#include "BLI_stack.hh" #include #include diff --git a/source/blender/editors/geometry/node_group_operator.cc b/source/blender/editors/geometry/node_group_operator.cc index 2777aab0cf3..3183b59fede 100644 --- a/source/blender/editors/geometry/node_group_operator.cc +++ b/source/blender/editors/geometry/node_group_operator.cc @@ -20,6 +20,7 @@ #include "WM_api.hh" #include "BKE_asset.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_curves.hh" @@ -156,11 +157,10 @@ static void find_socket_log_contexts(const Main &bmain, if (snode.edittree == nullptr) { continue; } - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(); + bke::ComputeContextCache compute_context_cache; const Map hash_by_zone = geo_log::GeoModifierLog::get_context_hash_by_zone_for_node_editor( - snode, compute_context_builder); + snode, compute_context_cache, &compute_context_cache.for_operator(nullptr)); for (const ComputeContextHash &hash : hash_by_zone.values()) { r_socket_log_contexts.add(hash); } diff --git a/source/blender/editors/include/ED_node.hh b/source/blender/editors/include/ED_node.hh index 1e5af7f9598..76d08d5808a 100644 --- a/source/blender/editors/include/ED_node.hh +++ b/source/blender/editors/include/ED_node.hh @@ -10,6 +10,8 @@ #include "BLI_string_ref.hh" #include "BLI_vector_set.hh" +#include "BKE_compute_context_cache_fwd.hh" + #include "ED_node_c.hh" struct SpaceNode; @@ -79,10 +81,11 @@ struct ObjectAndModifier { std::optional get_modifier_for_node_editor(const SpaceNode &snode); /** * Used to get the compute context for the (nested) node group that is currently edited. - * Returns true on success. */ -[[nodiscard]] bool push_compute_context_for_tree_path( - const SpaceNode &snode, ComputeContextBuilder &compute_context_builder); +[[nodiscard]] std::optional compute_context_for_tree_path( + const SpaceNode &snode, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context); void ui_template_node_asset_menu_items(uiLayout &layout, const bContext &C, diff --git a/source/blender/editors/include/ED_viewer_path.hh b/source/blender/editors/include/ED_viewer_path.hh index 1d26ca82bea..109cb31f9b1 100644 --- a/source/blender/editors/include/ED_viewer_path.hh +++ b/source/blender/editors/include/ED_viewer_path.hh @@ -10,6 +10,8 @@ #include "BLI_string_ref.hh" #include "BLI_vector.hh" +#include "BKE_compute_context_cache_fwd.hh" + #include "DNA_viewer_path_types.h" struct Main; @@ -81,9 +83,11 @@ UpdateActiveGeometryNodesViewerResult update_active_geometry_nodes_viewer(const * Some viewer path elements correspond to compute-contexts. This function converts from the viewer * path element to the corresponding compute context if possible. * - * \return False, there is no matching compute context. + * \return The corresponding compute context or null. */ -[[nodiscard]] bool add_compute_context_for_viewer_path_elem( - const ViewerPathElem &elem, ComputeContextBuilder &compute_context_builder); +[[nodiscard]] const ComputeContext *compute_context_for_viewer_path_elem( + const ViewerPathElem &elem, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context); } // namespace blender::ed::viewer_path diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc index 4313083af8b..6e3a4abfd28 100644 --- a/source/blender/editors/space_node/node_draw.cc +++ b/source/blender/editors/space_node/node_draw.cc @@ -38,6 +38,7 @@ #include "BLT_translation.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_curves.hh" @@ -4363,26 +4364,22 @@ static Set find_sockets_on_active_gizmo_paths(const bContex } snode.edittree->ensure_topology_cache(); + bke::ComputeContextCache compute_context_cache; /* Compute the compute context hash for the current node tree path. */ - std::optional current_compute_context_hash = - [&]() -> std::optional { - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(*object_and_modifier->nmd); - if (!ed::space_node::push_compute_context_for_tree_path(snode, compute_context_builder)) { - return std::nullopt; - } - return compute_context_builder.current()->hash(); - }(); - if (!current_compute_context_hash) { + const ComputeContext &root_compute_context = compute_context_cache.for_modifier( + nullptr, *object_and_modifier->nmd); + const std::optional current_compute_context = + ed::space_node::compute_context_for_tree_path( + snode, compute_context_cache, &root_compute_context); + if (!current_compute_context.has_value()) { return {}; } Set sockets_on_gizmo_paths; - ComputeContextBuilder compute_context_builder; nodes::gizmos::foreach_active_gizmo( C, - compute_context_builder, + compute_context_cache, [&](const Object &gizmo_object, const NodesModifierData &gizmo_nmd, const ComputeContext &gizmo_context, @@ -4401,7 +4398,7 @@ static Set find_sockets_on_active_gizmo_paths(const bContex [&](const ComputeContext &compute_context, const bNodeSocket &socket, const nodes::inverse_eval::ElemVariant & /*elem*/) { - if (compute_context.hash() == *current_compute_context_hash) { + if (compute_context.hash() == (*current_compute_context)->hash()) { sockets_on_gizmo_paths.add(&socket); } }); diff --git a/source/blender/editors/space_node/node_shader_preview.cc b/source/blender/editors/space_node/node_shader_preview.cc index d585b730320..10466c90615 100644 --- a/source/blender/editors/space_node/node_shader_preview.cc +++ b/source/blender/editors/space_node/node_shader_preview.cc @@ -33,6 +33,7 @@ #include "RNA_prototypes.hh" #include "BKE_colortools.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_global.hh" @@ -117,7 +118,8 @@ static std::optional get_compute_context_hash_for_node_edito hash.v1 = hash.v2 = 0; return hash; } - ComputeContextBuilder compute_context_builder; + bke::ComputeContextCache compute_context_cache; + const ComputeContext *compute_context = nullptr; for (const int i : treepath.index_range().drop_back(1)) { /* The tree path contains the name of the node but not its ID. */ bNodeTree *tree = treepath[i]->nodetree; @@ -127,9 +129,9 @@ static std::optional get_compute_context_hash_for_node_edito * deleted. */ return std::nullopt; } - compute_context_builder.push(*node, *tree); + compute_context = &compute_context_cache.for_group_node(compute_context, *node, *tree); } - return compute_context_builder.hash(); + return compute_context->hash(); } NestedTreePreviews *get_nested_previews(const bContext &C, SpaceNode &snode) diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc index 7a5a153a445..abbd048fa48 100644 --- a/source/blender/editors/space_node/space_node.cc +++ b/source/blender/editors/space_node/space_node.cc @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" #include "BKE_asset.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_gpencil_legacy.h" @@ -343,15 +344,18 @@ std::optional get_modifier_for_node_editor(const SpaceNode &s return ObjectAndModifier{object, used_modifier}; } -bool push_compute_context_for_tree_path(const SpaceNode &snode, - ComputeContextBuilder &compute_context_builder) +std::optional compute_context_for_tree_path( + const SpaceNode &snode, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context) { + const ComputeContext *current = parent_compute_context; Vector tree_path; LISTBASE_FOREACH (const bNodeTreePath *, item, &snode.treepath) { tree_path.append(item); } if (tree_path.is_empty()) { - return true; + return current; } for (const int i : tree_path.index_range().drop_back(1)) { @@ -359,43 +363,43 @@ bool push_compute_context_for_tree_path(const SpaceNode &snode, const char *group_node_name = tree_path[i + 1]->node_name; const bNode *group_node = blender::bke::node_find_node_by_name(*tree, group_node_name); if (group_node == nullptr) { - return false; + return std::nullopt; } const blender::bke::bNodeTreeZones *tree_zones = tree->zones(); if (tree_zones == nullptr) { - return false; + return std::nullopt; } const Vector zone_stack = tree_zones->get_zone_stack_for_node(group_node->identifier); for (const blender::bke::bNodeTreeZone *zone : zone_stack) { switch (zone->output_node->type_legacy) { case GEO_NODE_SIMULATION_OUTPUT: { - compute_context_builder.push(*zone->output_node); + current = &compute_context_cache.for_simulation_zone(current, *zone->output_node); break; } case GEO_NODE_REPEAT_OUTPUT: { const auto &storage = *static_cast( zone->output_node->storage); - compute_context_builder.push(*zone->output_node, - storage.inspection_index); + current = &compute_context_cache.for_repeat_zone( + current, *zone->output_node, storage.inspection_index); break; } case GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT: { const auto &storage = *static_cast( zone->output_node->storage); - compute_context_builder.push( - *zone->output_node, storage.inspection_index); + current = &compute_context_cache.for_foreach_geometry_element_zone( + current, *zone->output_node, storage.inspection_index); break; } case GEO_NODE_CLOSURE_OUTPUT: { // TODO: Need to find a place where this closure is evaluated. - return false; + return std::nullopt; } } } - compute_context_builder.push(*group_node, *tree); + current = &compute_context_cache.for_group_node(current, *group_node, *tree); } - return true; + return current; } /* ******************** default callbacks for node space ***************** */ diff --git a/source/blender/editors/space_view3d/view3d_gizmo_geometry_nodes.cc b/source/blender/editors/space_view3d/view3d_gizmo_geometry_nodes.cc index 62a0796005d..9cfddf22707 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_geometry_nodes.cc +++ b/source/blender/editors/space_view3d/view3d_gizmo_geometry_nodes.cc @@ -12,6 +12,7 @@ #include "DNA_modifier_types.h" #include "DNA_node_types.h" +#include "BKE_compute_context_cache.hh" #include "BKE_context.hh" #include "BKE_geometry_nodes_gizmos_transforms.hh" #include "BKE_geometry_set.hh" @@ -944,12 +945,11 @@ static void WIDGETGROUP_geometry_nodes_refresh(const bContext *C, wmGizmoGroup * /* This needs to stay around for a bit longer because the compute contexts are required when * applying the gizmo changes. */ - auto compute_context_builder = std::make_shared(); - compute_context_builder->keep_old_contexts(); + auto compute_context_cache = std::make_shared(); nodes::gizmos::foreach_active_gizmo( *C, - *compute_context_builder, + *compute_context_cache, [&](const Object &object_orig, const NodesModifierData &nmd_orig, const ComputeContext &compute_context, @@ -1047,7 +1047,7 @@ static void WIDGETGROUP_geometry_nodes_refresh(const bContext *C, wmGizmoGroup * /* Update the callback to apply gizmo changes based on the new context. */ node_gizmos->apply_change = [C = C, - compute_context_builder, + compute_context_cache, compute_context = &compute_context, gizmo_node_tree = &gizmo_node.owner_tree(), gizmo_node = &gizmo_node, diff --git a/source/blender/editors/util/ed_viewer_path.cc b/source/blender/editors/util/ed_viewer_path.cc index c17da34bf94..3ee016076f8 100644 --- a/source/blender/editors/util/ed_viewer_path.cc +++ b/source/blender/editors/util/ed_viewer_path.cc @@ -5,6 +5,7 @@ #include "ED_viewer_path.hh" #include "ED_screen.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_main.hh" @@ -525,49 +526,47 @@ bNode *find_geometry_nodes_viewer(const ViewerPath &viewer_path, SpaceNode &snod return nullptr; } -[[nodiscard]] bool add_compute_context_for_viewer_path_elem( - const ViewerPathElem &elem_generic, ComputeContextBuilder &compute_context_builder) +[[nodiscard]] const ComputeContext *compute_context_for_viewer_path_elem( + const ViewerPathElem &elem_generic, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context) { switch (ViewerPathElemType(elem_generic.type)) { case VIEWER_PATH_ELEM_TYPE_VIEWER_NODE: case VIEWER_PATH_ELEM_TYPE_ID: { - return false; + return nullptr; } case VIEWER_PATH_ELEM_TYPE_MODIFIER: { const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.modifier_name); - return true; + return &compute_context_cache.for_modifier(parent_compute_context, elem.modifier_name); } case VIEWER_PATH_ELEM_TYPE_GROUP_NODE: { const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.node_id); - return true; + return &compute_context_cache.for_group_node(parent_compute_context, elem.node_id); } case VIEWER_PATH_ELEM_TYPE_SIMULATION_ZONE: { const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.sim_output_node_id); - return true; + return &compute_context_cache.for_simulation_zone(parent_compute_context, + elem.sim_output_node_id); } case VIEWER_PATH_ELEM_TYPE_REPEAT_ZONE: { const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.repeat_output_node_id, - elem.iteration); - return true; + return &compute_context_cache.for_repeat_zone( + parent_compute_context, elem.repeat_output_node_id, elem.iteration); } case VIEWER_PATH_ELEM_TYPE_FOREACH_GEOMETRY_ELEMENT_ZONE: { const auto &elem = reinterpret_cast( elem_generic); - compute_context_builder.push( - elem.zone_output_node_id, elem.index); - return true; + return &compute_context_cache.for_foreach_geometry_element_zone( + parent_compute_context, elem.zone_output_node_id, elem.index); } case VIEWER_PATH_ELEM_TYPE_EVALUATE_CLOSURE: { const auto &elem = reinterpret_cast(elem_generic); - compute_context_builder.push(elem.evaluate_node_id); - return true; + return &compute_context_cache.for_evaluate_closure(parent_compute_context, + elem.evaluate_node_id); } } - return false; + return nullptr; } } // namespace blender::ed::viewer_path diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index ac6835051a8..a668350e55e 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -37,6 +37,7 @@ #include "BKE_bake_data_block_map.hh" #include "BKE_bake_geometry_nodes_modifier.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_customdata.hh" #include "BKE_global.hh" @@ -671,18 +672,17 @@ static void find_side_effect_nodes_for_viewer_path( return; } - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(nmd); - + bke::ComputeContextCache compute_context_cache; + const ComputeContext *current = &compute_context_cache.for_modifier(nullptr, nmd); for (const ViewerPathElem *elem : parsed_path->node_path) { - if (!ed::viewer_path::add_compute_context_for_viewer_path_elem(*elem, compute_context_builder)) - { + current = ed::viewer_path::compute_context_for_viewer_path_elem( + *elem, compute_context_cache, current); + if (!current) { return; } } - try_add_side_effect_node( - *compute_context_builder.current(), parsed_path->viewer_node_id, nmd, r_side_effect_nodes); + try_add_side_effect_node(*current, parsed_path->viewer_node_id, nmd, r_side_effect_nodes); } static void find_side_effect_nodes_for_nested_node( @@ -690,8 +690,8 @@ static void find_side_effect_nodes_for_nested_node( const int root_nested_node_id, nodes::GeoNodesSideEffectNodes &r_side_effect_nodes) { - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(nmd); + bke::ComputeContextCache compute_context_cache; + const ComputeContext *compute_context = &compute_context_cache.for_modifier(nullptr, nmd); int nested_node_id = root_nested_node_id; const bNodeTree *tree = nmd.node_group; @@ -716,13 +716,12 @@ static void find_side_effect_nodes_for_nested_node( if (!node->id) { return; } - compute_context_builder.push(*node, *tree); + compute_context = &compute_context_cache.for_group_node(compute_context, *node, *tree); tree = reinterpret_cast(node->id); nested_node_id = ref->path.id_in_node; } else { - try_add_side_effect_node( - *compute_context_builder.current(), ref->path.node_id, nmd, r_side_effect_nodes); + try_add_side_effect_node(*compute_context, ref->path.node_id, nmd, r_side_effect_nodes); return; } } @@ -762,12 +761,12 @@ static void find_side_effect_nodes_for_active_gizmos( Object *object_orig = DEG_get_original_object(ctx.object); const NodesModifierData &nmd_orig = *reinterpret_cast( BKE_modifier_get_original(ctx.object, const_cast(&nmd.modifier))); - ComputeContextBuilder compute_context_builder; + bke::ComputeContextCache compute_context_cache; nodes::gizmos::foreach_active_gizmo_in_modifier( *object_orig, nmd_orig, wm, - compute_context_builder, + compute_context_cache, [&](const ComputeContext &compute_context, const bNode &gizmo_node, const bNodeSocket &gizmo_socket) { diff --git a/source/blender/nodes/NOD_geometry_nodes_closure_location.hh b/source/blender/nodes/NOD_geometry_nodes_closure_location.hh index fa9d0dccc11..b3a7074ffc9 100644 --- a/source/blender/nodes/NOD_geometry_nodes_closure_location.hh +++ b/source/blender/nodes/NOD_geometry_nodes_closure_location.hh @@ -8,6 +8,7 @@ #include #include "BLI_compute_context.hh" +#include "BLI_vector.hh" namespace blender::nodes { diff --git a/source/blender/nodes/NOD_geometry_nodes_gizmos.hh b/source/blender/nodes/NOD_geometry_nodes_gizmos.hh index c7db7f61a3e..fbb076fffd8 100644 --- a/source/blender/nodes/NOD_geometry_nodes_gizmos.hh +++ b/source/blender/nodes/NOD_geometry_nodes_gizmos.hh @@ -11,6 +11,8 @@ #include "NOD_inverse_eval_path.hh" #include "NOD_inverse_eval_run.hh" +#include "BKE_compute_context_cache_fwd.hh" + struct Object; struct NodesModifierData; struct wmWindowManager; @@ -62,7 +64,7 @@ using ForeachGizmoFn = FunctionRef get_context_hash_by_zone_for_node_editor(const SpaceNode &snode, - ComputeContextBuilder &compute_context_builder); + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context); static ContextualGeoTreeLogs get_contextual_tree_logs(const SpaceNode &snode); static const ViewerNodeLog *find_viewer_node_log_for_path(const ViewerPath &viewer_path); diff --git a/source/blender/nodes/intern/geometry_nodes_gizmos.cc b/source/blender/nodes/intern/geometry_nodes_gizmos.cc index 87839c7507a..829d6f33d5f 100644 --- a/source/blender/nodes/intern/geometry_nodes_gizmos.cc +++ b/source/blender/nodes/intern/geometry_nodes_gizmos.cc @@ -4,6 +4,7 @@ #include "BLI_listbase.h" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_context.hh" #include "BKE_node.hh" @@ -174,25 +175,28 @@ bool update_tree_gizmo_propagation(bNodeTree &tree) } static void foreach_gizmo_for_input(const ie::SocketElem &input_socket, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *compute_context, const bNodeTree &tree, const ForeachGizmoInModifierFn fn); static void foreach_gizmo_for_group_input(const bNodeTree &tree, const ie::GroupInputElem &group_input, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *compute_context, const ForeachGizmoInModifierFn fn) { const TreeGizmoPropagation &gizmo_propagation = *tree.runtime->gizmo_propagation; for (const ie::SocketElem &gizmo_input : gizmo_propagation.gizmo_inputs_by_group_inputs.lookup(group_input)) { - foreach_gizmo_for_input(gizmo_input, compute_context_builder, tree, fn); + foreach_gizmo_for_input(gizmo_input, compute_context_cache, compute_context, tree, fn); } } static void foreach_gizmo_for_input(const ie::SocketElem &input_socket, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *compute_context, const bNodeTree &tree, const ForeachGizmoInModifierFn fn) { @@ -211,19 +215,20 @@ static void foreach_gizmo_for_input(const ie::SocketElem &input_socket, return; } /* Found an actual built-in gizmo node. */ - fn(*compute_context_builder.current(), node, *input_socket.socket); + fn(*compute_context, node, *input_socket.socket); return; } if (node.is_group()) { const bNodeTree &group = *reinterpret_cast(node.id); group.ensure_topology_cache(); - compute_context_builder.push(node, tree); + const ComputeContext &group_compute_context = compute_context_cache.for_group_node( + compute_context, node, tree); foreach_gizmo_for_group_input( group, ie::GroupInputElem{input_socket.socket->index(), input_socket.elem}, - compute_context_builder, + compute_context_cache, + &group_compute_context, fn); - compute_context_builder.pop(); } } @@ -231,7 +236,7 @@ static void foreach_active_gizmo_in_open_node_editor( const SpaceNode &snode, const Object *object_filter, const NodesModifierData *nmd_filter, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, const ForeachGizmoFn fn) { if (snode.nodetree == nullptr) { @@ -264,13 +269,13 @@ static void foreach_active_gizmo_in_open_node_editor( return; } - const ComputeContext *prev_compute_context = compute_context_builder.current(); - compute_context_builder.push(nmd); - BLI_SCOPED_DEFER([&]() { compute_context_builder.pop_until(prev_compute_context); }); - - if (!ed::space_node::push_compute_context_for_tree_path(snode, compute_context_builder)) { + std::optional current_compute_context = + ed::space_node::compute_context_for_tree_path( + snode, compute_context_cache, &compute_context_cache.for_modifier(nullptr, nmd)); + if (!current_compute_context.has_value()) { return; } + snode.edittree->ensure_topology_cache(); const TreeGizmoPropagation &gizmo_propagation = *snode.edittree->runtime->gizmo_propagation; Set used_gizmo_inputs; @@ -317,7 +322,8 @@ static void foreach_active_gizmo_in_open_node_editor( } for (const ie::SocketElem &gizmo_input : used_gizmo_inputs) { foreach_gizmo_for_input(gizmo_input, - compute_context_builder, + compute_context_cache, + *current_compute_context, *snode.edittree, [&](const ComputeContext &compute_context, const bNode &gizmo_node, @@ -330,7 +336,7 @@ static void foreach_active_gizmo_in_open_node_editor( static void foreach_active_gizmo_in_open_editors(const wmWindowManager &wm, const Object *object_filter, const NodesModifierData *nmd_filter, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, const ForeachGizmoFn fn) { LISTBASE_FOREACH (const wmWindow *, window, &wm.windows) { @@ -351,7 +357,7 @@ static void foreach_active_gizmo_in_open_editors(const wmWindowManager &wm, } const SpaceNode &snode = *reinterpret_cast(sl); foreach_active_gizmo_in_open_node_editor( - snode, object_filter, nmd_filter, compute_context_builder, fn); + snode, object_filter, nmd_filter, compute_context_cache, fn); } } } @@ -359,7 +365,7 @@ static void foreach_active_gizmo_in_open_editors(const wmWindowManager &wm, static void foreach_active_gizmo_exposed_to_modifier( const NodesModifierData &nmd, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, const ForeachGizmoInModifierFn fn) { if (!nmd.node_group) { @@ -369,12 +375,10 @@ static void foreach_active_gizmo_exposed_to_modifier( if (!tree.runtime->gizmo_propagation) { return; } - compute_context_builder.push(nmd); - BLI_SCOPED_DEFER([&]() { compute_context_builder.pop(); }); - + const ComputeContext &root_compute_context = compute_context_cache.for_modifier(nullptr, nmd); for (auto &&item : tree.runtime->gizmo_propagation->gizmo_inputs_by_group_inputs.items()) { for (const ie::SocketElem &socket_elem : item.value) { - foreach_gizmo_for_input(socket_elem, compute_context_builder, tree, fn); + foreach_gizmo_for_input(socket_elem, compute_context_cache, &root_compute_context, tree, fn); } } } @@ -382,7 +386,7 @@ static void foreach_active_gizmo_exposed_to_modifier( void foreach_active_gizmo_in_modifier(const Object &object, const NodesModifierData &nmd, const wmWindowManager &wm, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, const ForeachGizmoInModifierFn fn) { if (!nmd.node_group) { @@ -392,7 +396,7 @@ void foreach_active_gizmo_in_modifier(const Object &object, foreach_active_gizmo_in_open_editors(wm, &object, &nmd, - compute_context_builder, + compute_context_cache, [&](const Object &object_with_gizmo, const NodesModifierData &nmd_with_gizmo, const ComputeContext &compute_context, @@ -404,18 +408,18 @@ void foreach_active_gizmo_in_modifier(const Object &object, fn(compute_context, gizmo_node, gizmo_socket); }); - foreach_active_gizmo_exposed_to_modifier(nmd, compute_context_builder, fn); + foreach_active_gizmo_exposed_to_modifier(nmd, compute_context_cache, fn); } void foreach_active_gizmo(const bContext &C, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, const ForeachGizmoFn fn) { const wmWindowManager *wm = CTX_wm_manager(&C); if (!wm) { return; } - foreach_active_gizmo_in_open_editors(*wm, nullptr, nullptr, compute_context_builder, fn); + foreach_active_gizmo_in_open_editors(*wm, nullptr, nullptr, compute_context_cache, fn); if (const Base *active_base = CTX_data_active_base(&C)) { if (!(active_base->flag & BASE_SELECTED)) { @@ -431,7 +435,7 @@ void foreach_active_gizmo(const bContext &C, const NodesModifierData &nmd = *reinterpret_cast(md); foreach_active_gizmo_exposed_to_modifier( nmd, - compute_context_builder, + compute_context_cache, [&](const ComputeContext &compute_context, const bNode &gizmo_node, const bNodeSocket &gizmo_socket) { diff --git a/source/blender/nodes/intern/geometry_nodes_log.cc b/source/blender/nodes/intern/geometry_nodes_log.cc index 5a25545b924..4764517cd56 100644 --- a/source/blender/nodes/intern/geometry_nodes_log.cc +++ b/source/blender/nodes/intern/geometry_nodes_log.cc @@ -7,10 +7,12 @@ #include "NOD_geometry_nodes_log.hh" #include "BLI_listbase.h" +#include "BLI_stack.hh" #include "BLI_string_ref.hh" #include "BLI_string_utf8.h" #include "BKE_anonymous_attribute_id.hh" +#include "BKE_compute_context_cache.hh" #include "BKE_compute_contexts.hh" #include "BKE_curves.hh" #include "BKE_geometry_nodes_gizmos_transforms.hh" @@ -788,26 +790,27 @@ GeoTreeLog &GeoModifierLog::get_tree_log(const ComputeContextHash &compute_conte static void find_tree_zone_hash_recursive( const bNodeTreeZone &zone, - ComputeContextBuilder &compute_context_builder, + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *current, Map &r_hash_by_zone) { switch (zone.output_node->type_legacy) { case GEO_NODE_SIMULATION_OUTPUT: { - compute_context_builder.push(*zone.output_node); + current = &compute_context_cache.for_simulation_zone(current, *zone.output_node); break; } case GEO_NODE_REPEAT_OUTPUT: { const auto &storage = *static_cast( zone.output_node->storage); - compute_context_builder.push(*zone.output_node, - storage.inspection_index); + current = &compute_context_cache.for_repeat_zone( + current, *zone.output_node, storage.inspection_index); break; } case GEO_NODE_FOREACH_GEOMETRY_ELEMENT_OUTPUT: { const auto &storage = *static_cast( zone.output_node->storage); - compute_context_builder.push( - *zone.output_node, storage.inspection_index); + current = &compute_context_cache.for_foreach_geometry_element_zone( + current, *zone.output_node, storage.inspection_index); break; } case GEO_NODE_CLOSURE_OUTPUT: { @@ -816,18 +819,20 @@ static void find_tree_zone_hash_recursive( return; } } - r_hash_by_zone.add_new(&zone, compute_context_builder.hash()); + r_hash_by_zone.add_new(&zone, current->hash()); for (const bNodeTreeZone *child_zone : zone.child_zones) { - find_tree_zone_hash_recursive(*child_zone, compute_context_builder, r_hash_by_zone); + find_tree_zone_hash_recursive(*child_zone, compute_context_cache, current, r_hash_by_zone); } - compute_context_builder.pop(); } Map GeoModifierLog:: get_context_hash_by_zone_for_node_editor(const SpaceNode &snode, - ComputeContextBuilder &compute_context_builder) + bke::ComputeContextCache &compute_context_cache, + const ComputeContext *parent_compute_context) { - if (!ed::space_node::push_compute_context_for_tree_path(snode, compute_context_builder)) { + std::optional current = ed::space_node::compute_context_for_tree_path( + snode, compute_context_cache, parent_compute_context); + if (!current.has_value() || !*current) { return {}; } @@ -836,9 +841,9 @@ Map GeoModifierLog:: return {}; } Map hash_by_zone; - hash_by_zone.add_new(nullptr, compute_context_builder.hash()); + hash_by_zone.add_new(nullptr, (*current)->hash()); for (const bNodeTreeZone *zone : tree_zones->root_zones) { - find_tree_zone_hash_recursive(*zone, compute_context_builder, hash_by_zone); + find_tree_zone_hash_recursive(*zone, compute_context_cache, *current, hash_by_zone); } return hash_by_zone; } @@ -846,9 +851,10 @@ Map GeoModifierLog:: Map GeoModifierLog:: get_context_hash_by_zone_for_node_editor(const SpaceNode &snode, const NodesModifierData &nmd) { - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(nmd); - return get_context_hash_by_zone_for_node_editor(snode, compute_context_builder); + bke::ComputeContextCache compute_context_cache; + const ComputeContext &root_compute_context = compute_context_cache.for_modifier(nullptr, nmd); + return get_context_hash_by_zone_for_node_editor( + snode, compute_context_cache, &root_compute_context); } ContextualGeoTreeLogs GeoModifierLog::get_contextual_tree_logs(const SpaceNode &snode) @@ -880,10 +886,10 @@ ContextualGeoTreeLogs GeoModifierLog::get_contextual_tree_logs(const SpaceNode & if (snode.geometry_nodes_tool_tree->id.name + 2 != log.node_group_name) { return {}; } - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(); + bke::ComputeContextCache compute_context_cache; const Map hash_by_zone = - GeoModifierLog::get_context_hash_by_zone_for_node_editor(snode, compute_context_builder); + GeoModifierLog::get_context_hash_by_zone_for_node_editor( + snode, compute_context_cache, &compute_context_cache.for_operator(nullptr)); Map tree_logs_by_zone; for (const auto item : hash_by_zone.items()) { GeoTreeLog &tree_log = log.log->get_tree_log(item.value); @@ -920,15 +926,16 @@ const ViewerNodeLog *GeoModifierLog::find_viewer_node_log_for_path(const ViewerP } nodes::geo_eval_log::GeoModifierLog *modifier_log = nmd->runtime->eval_log.get(); - ComputeContextBuilder compute_context_builder; - compute_context_builder.push(*nmd); + bke::ComputeContextCache compute_context_cache; + const ComputeContext *compute_context = &compute_context_cache.for_modifier(nullptr, *nmd); for (const ViewerPathElem *elem : parsed_path->node_path) { - if (!ed::viewer_path::add_compute_context_for_viewer_path_elem(*elem, compute_context_builder)) - { + compute_context = ed::viewer_path::compute_context_for_viewer_path_elem( + *elem, compute_context_cache, compute_context); + if (!compute_context) { return nullptr; } } - const ComputeContextHash context_hash = compute_context_builder.hash(); + const ComputeContextHash context_hash = compute_context->hash(); nodes::geo_eval_log::GeoTreeLog &tree_log = modifier_log->get_tree_log(context_hash); tree_log.ensure_viewer_node_logs();