diff options
author | Jacques Lucke <jacques@blender.org> | 2021-07-07 12:20:19 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-07-07 12:20:19 +0300 |
commit | 0153e99780aef64913dfd4c323984874bf688249 (patch) | |
tree | 28d5aa0587149778e227f69c37793cdf4219ea7a /source/blender/modifiers | |
parent | 77834aff223e49eaa3abed56fb120aeca302a0e0 (diff) |
Geometry Nodes: refactor logging during geometry nodes evaluation
Many ui features for geometry nodes need access to information generated
during evaluation:
* Node warnings.
* Attribute search.
* Viewer node.
* Socket inspection (not in master yet).
The way we logged the required information before had some disadvantages:
* Viewer node used a completely separate system from node warnings and
attribute search.
* Most of the context of logged information is lost when e.g. the same node
group is used multiple times.
* A global lock was needed every time something is logged.
This new implementation solves these problems:
* All four mentioned ui features use the same underlying logging system.
* All context information for logged values is kept intact.
* Every thread has its own local logger. The logged informatiton is combined
in the end.
Differential Revision: https://developer.blender.org/D11785
Diffstat (limited to 'source/blender/modifiers')
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 121 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes_evaluator.cc | 56 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes_evaluator.hh | 7 |
3 files changed, 73 insertions, 111 deletions
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 76eec76acb4..51f9bedc0a9 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -48,6 +48,7 @@ #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" +#include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_geometry_set_instances.hh" #include "BKE_global.h" @@ -56,7 +57,6 @@ #include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_modifier.h" -#include "BKE_node_ui_storage.hh" #include "BKE_object.h" #include "BKE_pointcloud.h" #include "BKE_screen.h" @@ -83,8 +83,10 @@ #include "NOD_derived_node_tree.hh" #include "NOD_geometry.h" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" +using blender::destruct_ptr; using blender::float3; using blender::FunctionRef; using blender::IndexRange; @@ -97,6 +99,7 @@ using blender::Vector; using blender::fn::GMutablePointer; using blender::fn::GPointer; using blender::nodes::GeoNodeExecParams; +using blender::threading::EnumerableThreadSpecific; using namespace blender::fn::multi_function_types; using namespace blender::nodes::derived_node_tree_types; @@ -734,19 +737,6 @@ static void initialize_group_input(NodesModifierData &nmd, property_type->init_cpp_value(*property, r_value); } -static void reset_tree_ui_storage(Span<const blender::nodes::NodeTreeRef *> trees, - const Object &object, - const ModifierData &modifier) -{ - const NodeTreeEvaluationContext context = {object, modifier}; - - for (const blender::nodes::NodeTreeRef *tree : trees) { - bNodeTree *btree_cow = tree->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - BKE_nodetree_ui_storage_free_for_context(*btree_original, context); - } -} - static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) { wmWindowManager *wm = (wmWindowManager *)bmain->wm.first; @@ -766,8 +756,6 @@ static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) return spreadsheets; } -using PreviewSocketMap = blender::MultiValueMap<DSocket, uint64_t>; - static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspreadsheet, NodesModifierData *nmd, const ModifierEvalContext *ctx, @@ -821,19 +809,10 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre } const NodeTreeRef &tree_ref = context->tree(); - for (const NodeRef *node_ref : tree_ref.nodes()) { + for (const NodeRef *node_ref : tree_ref.nodes_by_type("GeometryNodeViewer")) { if (node_ref->name() == last_context->node_name) { const DNode viewer_node{context, node_ref}; - DSocket socket_to_view; - viewer_node.input(0).foreach_origin_socket( - [&](const DSocket socket) { socket_to_view = socket; }); - if (!socket_to_view) { - return {}; - } - bNodeSocket *bsocket = socket_to_view->bsocket(); - if (bsocket->type == SOCK_GEOMETRY && bsocket->flag != SOCK_MULTI_INPUT) { - return socket_to_view; - } + return viewer_node.input(0); } } return {}; @@ -842,7 +821,7 @@ static DSocket try_get_socket_to_preview_for_spreadsheet(SpaceSpreadsheet *sspre static void find_sockets_to_preview(NodesModifierData *nmd, const ModifierEvalContext *ctx, const DerivedNodeTree &tree, - PreviewSocketMap &r_sockets_to_preview) + Set<DSocket> &r_sockets_to_preview) { Main *bmain = DEG_get_bmain(ctx->depsgraph); @@ -852,51 +831,16 @@ static void find_sockets_to_preview(NodesModifierData *nmd, for (SpaceSpreadsheet *sspreadsheet : spreadsheets) { const DSocket socket = try_get_socket_to_preview_for_spreadsheet(sspreadsheet, nmd, ctx, tree); if (socket) { - const uint64_t key = ED_spreadsheet_context_path_hash(sspreadsheet); - r_sockets_to_preview.add_non_duplicates(socket, key); + r_sockets_to_preview.add(socket); } } } -static void log_preview_socket_value(const Span<GPointer> values, - Object *object, - Span<uint64_t> keys) +static void clear_runtime_data(NodesModifierData *nmd) { - GeometrySet geometry_set = *(const GeometrySet *)values[0].get(); - geometry_set.ensure_owns_direct_data(); - for (uint64_t key : keys) { - BKE_object_preview_geometry_set_add(object, key, new GeometrySet(geometry_set)); - } -} - -static void log_ui_hints(const DSocket socket, - const Span<GPointer> values, - Object *self_object, - NodesModifierData *nmd) -{ - const DNode node = socket.node(); - if (node->is_reroute_node() || socket->typeinfo()->type != SOCK_GEOMETRY) { - return; - } - bNodeTree *btree_cow = node->btree(); - bNodeTree *btree_original = (bNodeTree *)DEG_get_original_id((ID *)btree_cow); - const NodeTreeEvaluationContext context{*self_object, nmd->modifier}; - for (const GPointer &data : values) { - if (data.type() == &CPPType::get<GeometrySet>()) { - const GeometrySet &geometry_set = *(const GeometrySet *)data.get(); - blender::bke::geometry_set_instances_attribute_foreach( - geometry_set, - [&](StringRefNull attribute_name, const AttributeMetaData &meta_data) { - BKE_nodetree_attribute_hint_add(*btree_original, - context, - *node->bnode(), - attribute_name, - meta_data.domain, - meta_data.data_type); - return true; - }, - 8); - } + if (nmd->runtime_eval_log != nullptr) { + delete (geo_log::ModifierLog *)nmd->runtime_eval_log; + nmd->runtime_eval_log = nullptr; } } @@ -952,32 +896,32 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, Vector<DInputSocket> group_outputs; group_outputs.append({root_context, &socket_to_compute}); - PreviewSocketMap preview_sockets; - find_sockets_to_preview(nmd, ctx, tree, preview_sockets); - - auto log_socket_value = [&](const DSocket socket, const Span<GPointer> values) { - if (!logging_enabled(ctx)) { - return; - } - Span<uint64_t> keys = preview_sockets.lookup(socket); - if (!keys.is_empty()) { - log_preview_socket_value(values, ctx->object, keys); - } - log_ui_hints(socket, values, ctx->object, nmd); - }; + std::optional<geo_log::GeoLogger> geo_logger; blender::modifiers::geometry_nodes::GeometryNodesEvaluationParams eval_params; + + if (logging_enabled(ctx)) { + Set<DSocket> preview_sockets; + find_sockets_to_preview(nmd, ctx, tree, preview_sockets); + eval_params.force_compute_sockets.extend(preview_sockets.begin(), preview_sockets.end()); + geo_logger.emplace(std::move(preview_sockets)); + } + eval_params.input_values = group_inputs; eval_params.output_sockets = group_outputs; - eval_params.force_compute_sockets.extend(preview_sockets.keys().begin(), - preview_sockets.keys().end()); eval_params.mf_by_node = &mf_by_node; eval_params.modifier_ = nmd; eval_params.depsgraph = ctx->depsgraph; eval_params.self_object = ctx->object; - eval_params.log_socket_value_fn = log_socket_value; + eval_params.geo_logger = geo_logger.has_value() ? &*geo_logger : nullptr; blender::modifiers::geometry_nodes::evaluate_geometry_nodes(eval_params); + if (geo_logger.has_value()) { + NodesModifierData *nmd_orig = (NodesModifierData *)BKE_modifier_get_original(&nmd->modifier); + clear_runtime_data(nmd_orig); + nmd_orig->runtime_eval_log = new geo_log::ModifierLog(*geo_logger); + } + BLI_assert(eval_params.r_output_values.size() == 1); GMutablePointer result = eval_params.r_output_values[0]; return result.relocate_out<GeometrySet>(); @@ -1067,10 +1011,6 @@ static void modifyGeometry(ModifierData *md, return; } - if (logging_enabled(ctx)) { - reset_tree_ui_storage(tree.used_node_tree_refs(), *ctx->object, *md); - } - geometry_set = compute_geometry( tree, input_nodes, *group_outputs[0], std::move(geometry_set), nmd, ctx); } @@ -1215,6 +1155,7 @@ static void blendRead(BlendDataReader *reader, ModifierData *md) NodesModifierData *nmd = reinterpret_cast<NodesModifierData *>(md); BLO_read_data_address(reader, &nmd->settings.properties); IDP_BlendDataRead(reader, &nmd->settings.properties); + nmd->runtime_eval_log = nullptr; } static void copyData(const ModifierData *md, ModifierData *target, const int flag) @@ -1224,6 +1165,8 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla BKE_modifier_copydata_generic(md, target, flag); + tnmd->runtime_eval_log = nullptr; + if (nmd->settings.properties != nullptr) { tnmd->settings.properties = IDP_CopyProperty_ex(nmd->settings.properties, flag); } @@ -1236,6 +1179,8 @@ static void freeData(ModifierData *md) IDP_FreeProperty_ex(nmd->settings.properties, false); nmd->settings.properties = nullptr; } + + clear_runtime_data(nmd); } static void requiredDataMask(Object *UNUSED(ob), diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 205bfa34465..18cc1ce6c86 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -558,11 +558,11 @@ class GeometryNodesEvaluator { for (auto &&item : params_.input_values.items()) { const DOutputSocket socket = item.key; GMutablePointer value = item.value; - this->log_socket_value(socket, value); const DNode node = socket.node(); if (!node_states_.contains_as(node)) { /* The socket is not connected to any output. */ + this->log_socket_value({socket}, value); value.destruct(); continue; } @@ -780,7 +780,6 @@ class GeometryNodesEvaluator { /* Checks if all the linked sockets have been provided already. */ if (multi_value.items.size() == multi_value.expected_size) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, input_state, multi_value.items); } else if (is_required) { /* The input is required but is not fully provided yet. Therefore the node cannot be @@ -792,7 +791,6 @@ class GeometryNodesEvaluator { SingleInputValue &single_value = *input_state.value.single; if (single_value.value != nullptr) { input_state.was_ready_for_execution = true; - this->log_socket_value(socket, GPointer{input_state.type, single_value.value}); } else if (is_required) { /* The input is required but has not been provided yet. Therefore the node cannot be @@ -1170,6 +1168,9 @@ class GeometryNodesEvaluator { { BLI_assert(value_to_forward.get() != nullptr); + Vector<DSocket> sockets_to_log_to; + sockets_to_log_to.append(from_socket); + Vector<DInputSocket> to_sockets; auto handle_target_socket_fn = [&, this](const DInputSocket to_socket) { if (this->should_forward_to_socket(to_socket)) { @@ -1177,9 +1178,7 @@ class GeometryNodesEvaluator { } }; auto handle_skipped_socket_fn = [&, this](const DSocket socket) { - /* Log socket value on intermediate sockets to support e.g. attribute search or spreadsheet - * breadcrumbs on group nodes. */ - this->log_socket_value(socket, value_to_forward); + sockets_to_log_to.append(socket); }; from_socket.foreach_target_socket(handle_target_socket_fn, handle_skipped_socket_fn); @@ -1192,11 +1191,18 @@ class GeometryNodesEvaluator { if (from_type == to_type) { /* All target sockets that do not need a conversion will be handled afterwards. */ to_sockets_same_type.append(to_socket); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + sockets_to_log_to.append(to_socket); + } continue; } this->forward_to_socket_with_different_type( allocator, value_to_forward, from_socket, to_socket, to_type); } + + this->log_socket_value(sockets_to_log_to, value_to_forward); + this->forward_to_sockets_with_same_type( allocator, to_sockets_same_type, value_to_forward, from_socket); } @@ -1227,6 +1233,7 @@ class GeometryNodesEvaluator { /* Allocate a buffer for the converted value. */ void *buffer = allocator.allocate(to_type.size(), to_type.alignment()); + GMutablePointer value{to_type, buffer}; if (conversions_.is_convertible(from_type, to_type)) { /* Do the conversion if possible. */ @@ -1236,7 +1243,11 @@ class GeometryNodesEvaluator { /* Cannot convert, use default value instead. */ to_type.copy_construct(to_type.default_value(), buffer); } - this->add_value_to_input_socket(to_socket, from_socket, {to_type, buffer}); + /* Multi input socket values are logged once all values are available. */ + if (!to_socket->is_multi_input_socket()) { + this->log_socket_value({to_socket}, value); + } + this->add_value_to_input_socket(to_socket, from_socket, value); } void forward_to_sockets_with_same_type(LinearAllocator<> &allocator, @@ -1284,6 +1295,10 @@ class GeometryNodesEvaluator { /* Add a new value to the multi-input. */ MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin, value.get()}); + + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({socket}, input_state, multi_value.items); + } } else { /* Assign the value to the input. */ @@ -1314,10 +1329,14 @@ class GeometryNodesEvaluator { if (input_socket->is_multi_input_socket()) { MultiInputValue &multi_value = *input_state.value.multi; multi_value.items.append({origin_socket, value.get()}); + if (multi_value.expected_size == multi_value.items.size()) { + this->log_socket_value({input_socket}, input_state, multi_value.items); + } } else { SingleInputValue &single_value = *input_state.value.single; single_value.value = value.get(); + this->log_socket_value({input_socket}, value); } } @@ -1370,29 +1389,27 @@ class GeometryNodesEvaluator { return *node_states_.lookup_key_as(node).state; } - void log_socket_value(const DSocket socket, Span<GPointer> values) + void log_socket_value(DSocket socket, InputState &input_state, Span<MultiInputValueItem> values) { - if (params_.log_socket_value_fn) { - params_.log_socket_value_fn(socket, values); + if (params_.geo_logger == nullptr) { + return; } - } - void log_socket_value(const DSocket socket, - InputState &input_state, - Span<MultiInputValueItem> values) - { Vector<GPointer, 16> value_pointers; value_pointers.reserve(values.size()); const CPPType &type = *input_state.type; for (const MultiInputValueItem &item : values) { value_pointers.append({type, item.value}); } - this->log_socket_value(socket, value_pointers); + params_.geo_logger->local().log_multi_value_socket(socket, value_pointers); } - void log_socket_value(const DSocket socket, GPointer value) + void log_socket_value(Span<DSocket> sockets, GPointer value) { - this->log_socket_value(socket, Span<GPointer>(&value, 1)); + if (params_.geo_logger == nullptr) { + return; + } + params_.geo_logger->local().log_value_for_sockets(sockets, value); } /* In most cases when `NodeState` is accessed, the node has to be locked first to avoid race @@ -1431,6 +1448,7 @@ NodeParamsProvider::NodeParamsProvider(GeometryNodesEvaluator &evaluator, this->self_object = evaluator.params_.self_object; this->modifier = &evaluator.params_.modifier_->modifier; this->depsgraph = evaluator.params_.depsgraph; + this->logger = evaluator.params_.geo_logger; } bool NodeParamsProvider::can_get_input(StringRef identifier) const @@ -1530,8 +1548,6 @@ void NodeParamsProvider::set_output(StringRef identifier, GMutablePointer value) const DOutputSocket socket = this->dnode.output_by_identifier(identifier); BLI_assert(socket); - evaluator_.log_socket_value(socket, value); - OutputState &output_state = node_state_.outputs[socket->index()]; BLI_assert(!output_state.has_been_computed); evaluator_.forward_output(socket, value); diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index 58eb6a4cd0b..f4ee6242dcb 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -19,20 +19,21 @@ #include "BLI_map.hh" #include "NOD_derived_node_tree.hh" +#include "NOD_geometry_nodes_eval_log.hh" #include "NOD_node_tree_multi_function.hh" #include "FN_generic_pointer.hh" #include "DNA_modifier_types.h" +namespace geo_log = blender::nodes::geometry_nodes_eval_log; + namespace blender::modifiers::geometry_nodes { using namespace nodes::derived_node_tree_types; using fn::GMutablePointer; using fn::GPointer; -using LogSocketValueFn = std::function<void(DSocket, Span<GPointer>)>; - struct GeometryNodesEvaluationParams { blender::LinearAllocator<> allocator; @@ -48,7 +49,7 @@ struct GeometryNodesEvaluationParams { const NodesModifierData *modifier_; Depsgraph *depsgraph; Object *self_object; - LogSocketValueFn log_socket_value_fn; + geo_log::GeoLogger *geo_logger; Vector<GMutablePointer> r_output_values; }; |