From b08301c865f42ab51b29efb80fcf68074a947d93 Mon Sep 17 00:00:00 2001 From: Erik Abrahamsson Date: Mon, 12 Dec 2022 23:01:49 +0100 Subject: [PATCH] Geometry Nodes: Optimization in Set Position node Adds an early return if Position/Offset inputs won't lead to any changes in the Geometry. It now also compares with the read-only Position attribute instead of getting it for write only, to work correctly with Copy-on-Write. Before, the `is_same`-check only worked for geometry created in the node tree. Differential Revision: https://developer.blender.org/D16738 --- .../geometry/nodes/node_geo_set_position.cc | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc index e243fe3614c..e219d5bc0a1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_position.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_position.cc @@ -29,15 +29,22 @@ static void set_computed_position_and_offset(GeometryComponent &component, const IndexMask selection) { MutableAttributeAccessor attributes = *component.attributes_for_write(); - AttributeWriter positions = attributes.lookup_for_write("position"); + const VArray positions_read_only = attributes.lookup("position"); + if (in_positions.is_same(positions_read_only)) { + if (const std::optional offset = in_offsets.get_if_single()) { + if (math::is_zero(offset.value())) { + return; + } + } + } const int grain_size = 10000; switch (component.type()) { case GEO_COMPONENT_TYPE_MESH: { Mesh *mesh = static_cast(component).get_for_write(); MutableSpan verts = mesh->verts_for_write(); - if (in_positions.is_same(positions.varray)) { + if (in_positions.is_same(positions_read_only)) { devirtualize_varray(in_offsets, [&](const auto in_offsets) { threading::parallel_for( selection.index_range(), grain_size, [&](const IndexRange range) { @@ -63,15 +70,16 @@ static void set_computed_position_and_offset(GeometryComponent &component, break; } case GEO_COMPONENT_TYPE_CURVE: { - CurveComponent &curve_component = static_cast(component); - Curves &curves_id = *curve_component.get_for_write(); - bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); if (attributes.contains("handle_right") && attributes.contains("handle_left")) { + CurveComponent &curve_component = static_cast(component); + Curves &curves_id = *curve_component.get_for_write(); + bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); SpanAttributeWriter handle_right_attribute = attributes.lookup_or_add_for_write_span("handle_right", ATTR_DOMAIN_POINT); SpanAttributeWriter handle_left_attribute = attributes.lookup_or_add_for_write_span("handle_left", ATTR_DOMAIN_POINT); + AttributeWriter positions = attributes.lookup_for_write("position"); MutableVArraySpan out_positions_span = positions.varray; devirtualize_varray2( in_positions, in_offsets, [&](const auto in_positions, const auto in_offsets) { @@ -88,6 +96,7 @@ static void set_computed_position_and_offset(GeometryComponent &component, }); out_positions_span.save(); + positions.finish(); handle_right_attribute.finish(); handle_left_attribute.finish(); @@ -95,13 +104,12 @@ static void set_computed_position_and_offset(GeometryComponent &component, curves.calculate_bezier_auto_handles(); break; } - else { - ATTR_FALLTHROUGH; - } + ATTR_FALLTHROUGH; } default: { + AttributeWriter positions = attributes.lookup_for_write("position"); MutableVArraySpan out_positions_span = positions.varray; - if (in_positions.is_same(positions.varray)) { + if (in_positions.is_same(positions_read_only)) { devirtualize_varray(in_offsets, [&](const auto in_offsets) { threading::parallel_for( selection.index_range(), grain_size, [&](const IndexRange range) { @@ -123,11 +131,10 @@ static void set_computed_position_and_offset(GeometryComponent &component, }); } out_positions_span.save(); + positions.finish(); break; } } - - positions.finish(); } static void set_position_in_component(GeometryComponent &component,