diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index 5af97ea8fcb..085fd3d65f4 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -42,23 +42,6 @@ using fn::ValueOrField; using geo_eval_log::NamedAttributeUsage; using geo_eval_log::NodeWarningType; -/** - * An anonymous attribute created by a node. - */ -class NodeAnonymousAttributeID : public AnonymousAttributeID { - std::string long_name_; - std::string socket_name_; - - public: - NodeAnonymousAttributeID(const Object &object, - const ComputeContext &compute_context, - const bNode &bnode, - const StringRef identifier, - const StringRef name); - - std::string user_name() const override; -}; - class GeoNodeExecParams { private: const bNode &node_; @@ -66,18 +49,22 @@ class GeoNodeExecParams { const lf::Context &lf_context_; const Span lf_input_for_output_bsocket_usage_; const Span lf_input_for_attribute_propagation_to_output_; + const FunctionRef get_output_attribute_id_; public: GeoNodeExecParams(const bNode &node, lf::Params ¶ms, const lf::Context &lf_context, const Span lf_input_for_output_bsocket_usage, - const Span lf_input_for_attribute_propagation_to_output) + const Span lf_input_for_attribute_propagation_to_output, + const FunctionRef get_output_attribute_id) : node_(node), params_(params), lf_context_(lf_context), lf_input_for_output_bsocket_usage_(lf_input_for_output_bsocket_usage), - lf_input_for_attribute_propagation_to_output_(lf_input_for_attribute_propagation_to_output) + lf_input_for_attribute_propagation_to_output_( + lf_input_for_attribute_propagation_to_output), + get_output_attribute_id_(get_output_attribute_id) { } @@ -240,8 +227,6 @@ class GeoNodeExecParams { */ void error_message_add(const NodeWarningType type, StringRef message) const; - std::string attribute_producer_name() const; - void set_default_remaining_outputs(); void used_named_attribute(StringRef attribute_name, NamedAttributeUsage usage); @@ -268,14 +253,7 @@ class GeoNodeExecParams { return {}; } const bNodeSocket &output_socket = node_.output_by_identifier(output_identifier); - const GeoNodesLFUserData &user_data = *this->user_data(); - const ComputeContext &compute_context = *user_data.compute_context; - return MEM_new(__func__, - *user_data.modifier_data->self_object, - compute_context, - node_, - output_identifier, - output_socket.name); + return get_output_attribute_id_(output_socket.index()); } /** diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index e9eff6bf625..6c5f6699eb4 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -322,7 +322,9 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { /** * For inputs this means that the input field is evaluated on all geometry inputs. For outputs * it means that this contains an anonymous attribute reference that is available on all geometry - * outputs. + * outputs. This sockets value does not have to be output manually in the node. It's done + * automatically by #LazyFunctionForGeometryNode. This allows outputting this field even if the + * geometry output does not have to be computed. */ Self &field_on_all() { diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc index 6718a0b0d78..6d5596cda27 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_capture.cc @@ -174,8 +174,6 @@ static void node_geo_exec(GeoNodeExecParams params) break; } - const CPPType &type = field.cpp_type(); - /* Run on the instances component separately to only affect the top level of instances. */ if (domain == ATTR_DOMAIN_INSTANCE) { if (geometry_set.has_instances()) { @@ -198,34 +196,6 @@ static void node_geo_exec(GeoNodeExecParams params) }); } - GField output_field{std::make_shared( - std::move(attribute_id), type, params.attribute_producer_name())}; - - switch (data_type) { - case CD_PROP_FLOAT: { - params.set_output(output_identifier, Field(output_field)); - break; - } - case CD_PROP_FLOAT3: { - params.set_output(output_identifier, Field(output_field)); - break; - } - case CD_PROP_COLOR: { - params.set_output(output_identifier, Field(output_field)); - break; - } - case CD_PROP_BOOL: { - params.set_output(output_identifier, Field(output_field)); - break; - } - case CD_PROP_INT32: { - params.set_output(output_identifier, Field(output_field)); - break; - } - default: - break; - } - params.set_output("Geometry", geometry_set); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index b1885970071..0457ab10f36 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -160,11 +160,6 @@ static void node_geo_exec(GeoNodeExecParams params) selection.span[i] = true; } selection.finish(); - - params.set_output( - "Intersecting Edges", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.intersecting_edges_id), params.attribute_producer_name())); } params.set_output("Mesh", GeometrySet::create_with_mesh(result)); diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc index acf3654a166..402e396083c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc @@ -81,9 +81,6 @@ static void node_geo_exec(GeoNodeExecParams params) if (AnonymousAttributeIDPtr outer_points_id = params.get_output_anonymous_attribute_id_if_needed( "Outer Points")) { create_selection_output(output.get_component_for_write(), outer_points_id); - params.set_output("Outer Points", - AnonymousAttributeFieldInput::Create( - std::move(outer_points_id), params.attribute_producer_name())); } params.set_output("Curve", std::move(output)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc index 22286969c24..bae8dc49ef2 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc @@ -200,21 +200,6 @@ static void node_geo_exec(GeoNodeExecParams params) } params.set_output("Points", std::move(geometry_set)); - if (tangent_anonymous_id) { - params.set_output("Tangent", - AnonymousAttributeFieldInput::Create( - std::move(tangent_anonymous_id), params.attribute_producer_name())); - } - if (normal_anonymous_id) { - params.set_output("Normal", - AnonymousAttributeFieldInput::Create( - std::move(normal_anonymous_id), params.attribute_producer_name())); - } - if (rotation_anonymous_id) { - params.set_output("Rotation", - AnonymousAttributeFieldInput::Create( - std::move(rotation_anonymous_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_curve_to_points_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc index b4bc18c465c..5a389203345 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_distribute_points_on_faces.cc @@ -590,19 +590,6 @@ static void node_geo_exec(GeoNodeExecParams params) }); params.set_output("Points", std::move(geometry_set)); - - if (attribute_outputs.normal_id) { - params.set_output( - "Normal", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.normal_id), - params.attribute_producer_name())); - } - if (attribute_outputs.rotation_id) { - params.set_output( - "Rotation", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.rotation_id), - params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_distribute_points_on_faces_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index 68461dfe7b1..0040fb6305e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -1098,12 +1098,6 @@ static void node_geo_exec(GeoNodeExecParams params) return; } - if (attribute_outputs.duplicate_index) { - params.set_output( - "Duplicate Index", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.duplicate_index), - params.attribute_producer_name())); - } params.set_output("Geometry", std::move(geometry_set)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc index 8e93e42f5fd..cf9161c5b7c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_extrude_mesh.cc @@ -1376,16 +1376,6 @@ static void node_geo_exec(GeoNodeExecParams params) }); params.set_output("Mesh", std::move(geometry_set)); - if (attribute_outputs.top_id) { - params.set_output("Top", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.top_id), params.attribute_producer_name())); - } - if (attribute_outputs.side_id) { - params.set_output("Side", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.side_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_extrude_mesh_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc index 2e256caea4a..1528ee9eb13 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_interpolate_curves.cc @@ -836,16 +836,6 @@ static void node_geo_exec(GeoNodeExecParams params) } params.set_output("Curves", std::move(new_curves)); - if (index_attribute_id) { - params.set_output("Closest Index", - AnonymousAttributeFieldInput::Create(std::move(index_attribute_id), - params.attribute_producer_name())); - } - if (weight_attribute_id) { - params.set_output("Closest Weight", - AnonymousAttributeFieldInput::Create( - std::move(weight_attribute_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_interpolate_curves_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index 1089f008a59..1d864d5e154 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -851,29 +851,6 @@ static void node_geo_exec(GeoNodeExecParams params) /* Transform the mesh so that the base of the cone is at the origin. */ BKE_mesh_translate(mesh, float3(0.0f, 0.0f, depth * 0.5f), false); - if (attribute_outputs.top_id) { - params.set_output("Top", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.top_id), params.attribute_producer_name())); - } - if (attribute_outputs.bottom_id) { - params.set_output( - "Bottom", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.bottom_id), - params.attribute_producer_name())); - } - if (attribute_outputs.side_id) { - params.set_output("Side", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.side_id), params.attribute_producer_name())); - } - if (attribute_outputs.uv_map_id) { - params.set_output( - "UV Map", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.uv_map_id), - params.attribute_producer_name())); - } - params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc index bb615d6315e..06524293d69 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cube.cc @@ -112,12 +112,6 @@ static void node_geo_exec(GeoNodeExecParams params) Mesh *mesh = create_cube_mesh(size, verts_x, verts_y, verts_z, uv_map_id.get()); params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); - - if (uv_map_id) { - params.set_output("UV Map", - AnonymousAttributeFieldInput::Create( - std::move(uv_map_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_mesh_primitive_cube_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc index 5c6f206f04d..37952f8cba0 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc @@ -122,29 +122,6 @@ static void node_geo_exec(GeoNodeExecParams params) fill, attribute_outputs); - if (attribute_outputs.top_id) { - params.set_output("Top", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.top_id), params.attribute_producer_name())); - } - if (attribute_outputs.bottom_id) { - params.set_output( - "Bottom", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.bottom_id), - params.attribute_producer_name())); - } - if (attribute_outputs.side_id) { - params.set_output("Side", - AnonymousAttributeFieldInput::Create( - std::move(attribute_outputs.side_id), params.attribute_producer_name())); - } - if (attribute_outputs.uv_map_id) { - params.set_output( - "UV Map", - AnonymousAttributeFieldInput::Create(std::move(attribute_outputs.uv_map_id), - params.attribute_producer_name())); - } - params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index 5d9a8c8f2e8..972a451b140 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -205,12 +205,6 @@ static void node_geo_exec(GeoNodeExecParams params) BKE_id_material_eval_ensure_default_slot(&mesh->id); params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); - - if (uv_map_id) { - params.set_output("UV Map", - AnonymousAttributeFieldInput::Create( - std::move(uv_map_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_mesh_primitive_grid_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc index 74053462f0e..9d71bd3cf53 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_ico_sphere.cc @@ -115,12 +115,6 @@ static void node_geo_exec(GeoNodeExecParams params) Mesh *mesh = create_ico_sphere_mesh(subdivisions, radius, uv_map_id.get()); params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); - - if (uv_map_id) { - params.set_output("UV Map", - AnonymousAttributeFieldInput::Create( - std::move(uv_map_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_mesh_primitive_ico_sphere_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index f527a413866..0d106669de7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -363,11 +363,6 @@ static void node_geo_exec(GeoNodeExecParams params) Mesh *mesh = create_uv_sphere_mesh(radius, segments_num, rings_num, uv_map_id.get()); params.set_output("Mesh", GeometrySet::create_with_mesh(mesh)); - if (uv_map_id) { - params.set_output("UV Map", - AnonymousAttributeFieldInput::Create( - std::move(uv_map_id), params.attribute_producer_name())); - } } } // namespace blender::nodes::node_geo_mesh_primitive_uv_sphere_cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc index 6c52af3956f..e9f6f32c76a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc @@ -348,9 +348,6 @@ static void create_attributes(GeoNodeExecParams ¶ms, *line_id, ATTR_DOMAIN_INSTANCE); line_attribute.span.copy_from(layout.line_numbers); line_attribute.finish(); - params.set_output("Line", - AnonymousAttributeFieldInput::Create(std::move(line_id), - params.attribute_producer_name())); } if (AnonymousAttributeIDPtr pivot_id = params.get_output_anonymous_attribute_id_if_needed( @@ -363,9 +360,6 @@ static void create_attributes(GeoNodeExecParams ¶ms, } pivot_attribute.finish(); - params.set_output("Pivot Point", - AnonymousAttributeFieldInput::Create( - std::move(pivot_id), params.attribute_producer_name())); } } diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc index 0af6bd940a8..00f4617cf5a 100644 --- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc +++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc @@ -21,6 +21,7 @@ #include "BLI_cpp_types.hh" #include "BLI_dot_export.hh" #include "BLI_hash.h" +#include "BLI_hash_md5.h" #include "BLI_lazy_threading.hh" #include "BLI_map.hh" @@ -102,6 +103,43 @@ static void lazy_function_interface_from_node(const bNode &node, } } +/** + * An anonymous attribute created by a node. + */ +class NodeAnonymousAttributeID : public AnonymousAttributeID { + std::string long_name_; + std::string socket_name_; + + public: + NodeAnonymousAttributeID(const Object &object, + const ComputeContext &compute_context, + const bNode &bnode, + const StringRef identifier, + const StringRef name) + : socket_name_(name) + { + const ComputeContextHash &hash = compute_context.hash(); + { + std::stringstream ss; + ss << hash << "_" << object.id.name << "_" << bnode.identifier << "_" << identifier; + long_name_ = ss.str(); + } + { + uint64_t hash_result[2]; + BLI_hash_md5_buffer(long_name_.data(), long_name_.size(), hash_result); + std::stringstream ss; + ss << ".a_" << std::hex << hash_result[0] << hash_result[1]; + name_ = ss.str(); + BLI_assert(name_.size() < MAX_CUSTOMDATA_LAYER_NAME); + } + } + + std::string user_name() const override + { + return socket_name_; + } +}; + /** * Used for most normal geometry nodes like Subdivision Surface and Set Position. */ @@ -117,6 +155,25 @@ class LazyFunctionForGeometryNode : public LazyFunction { * propagated to the output. */ const Span lf_input_for_attribute_propagation_to_output_; + /** + * Maps #bNodeSocket::index_in_tree to input/output indices of the current lazy-function. + */ + const Span lf_index_by_bsocket_; + /** + * A bool for every output bsocket. If true, the socket just outputs a field containing an + * anonymous attribute id. If only such outputs are requested by other nodes, the node itself + * does not have to execute. + */ + Vector is_attribute_output_bsocket_; + + struct OutputAttributeID { + int bsocket_index; + AnonymousAttributeIDPtr attribute_id; + }; + + struct Storage { + Vector attributes; + }; public: LazyFunctionForGeometryNode(const bNode &node, @@ -126,7 +183,9 @@ class LazyFunctionForGeometryNode : public LazyFunction { : node_(node), lf_input_for_output_bsocket_usage_(r_lf_input_for_output_bsocket_usage), lf_input_for_attribute_propagation_to_output_( - r_lf_input_for_attribute_propagation_to_output) + r_lf_input_for_attribute_propagation_to_output), + lf_index_by_bsocket_(r_lf_index_by_bsocket), + is_attribute_output_bsocket_(node.output_sockets().size(), false) { BLI_assert(node.typeinfo->geometry_node_execute != nullptr); debug_name_ = node.name; @@ -137,6 +196,16 @@ class LazyFunctionForGeometryNode : public LazyFunction { if (relations == nullptr) { return; } + if (!relations->available_relations.is_empty()) { + /* Inputs are only used when an output is used that is not just outputting an anonymous + * attribute field. */ + for (lf::Input &input : inputs_) { + input.usage = lf::ValueUsage::Maybe; + } + for (const aal::AvailableRelation &relation : relations->available_relations) { + is_attribute_output_bsocket_[relation.field_output] = true; + } + } Vector handled_field_outputs; for (const aal::AvailableRelation &relation : relations->available_relations) { const bNodeSocket &output_bsocket = node.output_socket(relation.field_output); @@ -160,16 +229,90 @@ class LazyFunctionForGeometryNode : public LazyFunction { } } + void *init_storage(LinearAllocator<> &allocator) const override + { + return allocator.construct().release(); + } + + void destruct_storage(void *storage) const override + { + Storage *s = static_cast(storage); + std::destroy_at(s); + } + void execute_impl(lf::Params ¶ms, const lf::Context &context) const override { + Storage *storage = static_cast(context.storage); GeoNodesLFUserData *user_data = dynamic_cast(context.user_data); BLI_assert(user_data != nullptr); + /* Lazily create the required anonymous attribute ids. */ + auto get_output_attribute_id = [&](const int output_bsocket_index) -> AnonymousAttributeIDPtr { + for (const OutputAttributeID &node_output_attribute : storage->attributes) { + if (node_output_attribute.bsocket_index == output_bsocket_index) { + return node_output_attribute.attribute_id; + } + } + const bNodeSocket &bsocket = node_.output_socket(output_bsocket_index); + AnonymousAttributeIDPtr attribute_id = MEM_new( + __func__, + *user_data->modifier_data->self_object, + *user_data->compute_context, + node_, + bsocket.identifier, + bsocket.name); + storage->attributes.append({output_bsocket_index, attribute_id}); + return attribute_id; + }; + + bool used_non_attribute_output_exists = false; + for (const int output_bsocket_index : node_.output_sockets().index_range()) { + const bNodeSocket &output_bsocket = node_.output_socket(output_bsocket_index); + const int lf_index = lf_index_by_bsocket_[output_bsocket.index_in_tree()]; + if (lf_index == -1) { + continue; + } + const lf::ValueUsage output_usage = params.get_output_usage(lf_index); + if (output_usage == lf::ValueUsage::Unused) { + continue; + } + if (is_attribute_output_bsocket_[output_bsocket_index]) { + if (params.output_was_set(lf_index)) { + continue; + } + this->output_anonymous_attribute_field( + params, lf_index, get_output_attribute_id(output_bsocket_index)); + } + else { + if (output_usage == lf::ValueUsage::Used) { + used_non_attribute_output_exists = true; + } + } + } + + if (!used_non_attribute_output_exists) { + /* Only attribute outputs are used currently, no need to evaluate the full node and its + * inputs. */ + return; + } + + bool missing_input = false; + for (const int lf_index : inputs_.index_range()) { + if (params.try_get_input_data_ptr_or_request(lf_index) == nullptr) { + missing_input = true; + } + } + if (missing_input) { + /* Wait until all inputs are available. */ + return; + } + GeoNodeExecParams geo_params{node_, params, context, lf_input_for_output_bsocket_usage_, - lf_input_for_attribute_propagation_to_output_}; + lf_input_for_attribute_propagation_to_output_, + get_output_attribute_id}; geo_eval_log::TimePoint start_time = geo_eval_log::Clock::now(); node_.typeinfo->geometry_node_execute(geo_params); @@ -182,6 +325,24 @@ class LazyFunctionForGeometryNode : public LazyFunction { } } + /** + * Output the given anonymous attribute id as a field. + */ + void output_anonymous_attribute_field(lf::Params ¶ms, + const int lf_index, + AnonymousAttributeIDPtr attribute_id) const + { + const ValueOrFieldCPPType &value_or_field_cpp_type = *ValueOrFieldCPPType::get_from_self( + *outputs_[lf_index].type); + GField output_field{ + std::make_shared(std::move(attribute_id), + value_or_field_cpp_type.value, + node_.label_or_name() + TIP_(" node"))}; + void *r_value = params.get_output_data_ptr(lf_index); + value_or_field_cpp_type.construct_from_field(r_value, std::move(output_field)); + params.output_set(lf_index); + } + std::string input_name(const int index) const override { for (const bNodeSocket *bsocket : node_.output_sockets()) { diff --git a/source/blender/nodes/intern/node_geometry_exec.cc b/source/blender/nodes/intern/node_geometry_exec.cc index 66c2dbf8547..a7caed7042b 100644 --- a/source/blender/nodes/intern/node_geometry_exec.cc +++ b/source/blender/nodes/intern/node_geometry_exec.cc @@ -9,40 +9,10 @@ #include "NOD_geometry_exec.hh" -#include "BLI_hash_md5.h" - #include "node_geometry_util.hh" namespace blender::nodes { -NodeAnonymousAttributeID::NodeAnonymousAttributeID(const Object &object, - const ComputeContext &compute_context, - const bNode &bnode, - const StringRef identifier, - const StringRef name) - : socket_name_(name) -{ - const ComputeContextHash &hash = compute_context.hash(); - { - std::stringstream ss; - ss << hash << "_" << object.id.name << "_" << bnode.identifier << "_" << identifier; - long_name_ = ss.str(); - } - { - uint64_t hash_result[2]; - BLI_hash_md5_buffer(long_name_.data(), long_name_.size(), hash_result); - std::stringstream ss; - ss << ".a_" << std::hex << hash_result[0] << hash_result[1]; - name_ = ss.str(); - BLI_assert(name_.size() < MAX_CUSTOMDATA_LAYER_NAME); - } -} - -std::string NodeAnonymousAttributeID::user_name() const -{ - return socket_name_; -} - void GeoNodeExecParams::error_message_add(const NodeWarningType type, const StringRef message) const { @@ -153,11 +123,6 @@ const bNodeSocket *GeoNodeExecParams::find_available_socket(const StringRef name return nullptr; } -std::string GeoNodeExecParams::attribute_producer_name() const -{ - return node_.label_or_name() + TIP_(" node"); -} - void GeoNodeExecParams::set_default_remaining_outputs() { params_.set_default_remaining_outputs();