Commit: 471f27d66bd71e80db82c41db2a6fd58f854b46a Author: Hans Goudey Date: Thu Mar 3 11:55:13 2022 -0500 Branches: master https://developer.blender.org/rB471f27d66bd71e80db82c41db2a6fd58f854b46a
Curves: Port endpoint selection node to new data-block The node should be faster than in 3.1, for a few reasons: - It doesn't need to calculate and allocate the curve offsets. - It doesn't need to de-reference a pointer for each curve. - The inputs are accessed from the virual arrays fewer times. On top of that, I added two other performance improvements: - The node is multi-threaded when there are many curves. - There are generated special cases for single value and span inputs. **Performance** With a set position node affecting 1 million splines with a selection based on this node, on an Intel i5 8250U (times are approximate): | Before | After | Speedup | | 760 ms | 60 ms | 13x | Differential Revision: https://developer.blender.org/D14233 =================================================================== M source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc =================================================================== diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc index ce3058c7d42..2c72e5f14f5 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "BKE_spline.hh" +#include "BKE_curves.hh" #include "UI_interface.h" #include "UI_resources.h" @@ -27,16 +27,6 @@ static void node_declare(NodeDeclarationBuilder &b) N_("The selection from the start and end of the splines based on the input sizes")); } -static void select_by_spline(const int start, const int end, MutableSpan<bool> r_selection) -{ - const int size = r_selection.size(); - const int start_use = std::min(start, size); - const int end_use = std::min(end, size); - - r_selection.slice(0, start_use).fill(true); - r_selection.slice(size - end_use, end_use).fill(true); -} - class EndpointFieldInput final : public GeometryFieldInput { Field<int> start_size_; Field<int> end_size_; @@ -63,37 +53,35 @@ class EndpointFieldInput final : public GeometryFieldInput { return nullptr; } - const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read()); - - Array<int> control_point_offsets = curve->control_point_offsets(); - if (curve == nullptr || control_point_offsets.last() == 0) { + const Curves &curves_id = *curve_component.get_for_read(); + const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry); + if (curves.points_size() == 0) { return nullptr; } GeometryComponentFieldContext size_context{curve_component, ATTR_DOMAIN_CURVE}; - fn::FieldEvaluator evaluator{size_context, curve->splines().size()}; + fn::FieldEvaluator evaluator{size_context, curves.curves_size()}; evaluator.add(start_size_); evaluator.add(end_size_); evaluator.evaluate(); const VArray<int> &start_size = evaluator.get_evaluated<int>(0); const VArray<int> &end_size = evaluator.get_evaluated<int>(1); - const int point_size = control_point_offsets.last(); - Array<bool> selection(point_size, false); - int current_point = 0; + Array<bool> selection(curves.points_size(), false); MutableSpan<bool> selection_span = selection.as_mutable_span(); - for (int i : IndexRange(curve->splines().size())) { - const SplinePtr &spline = curve->splines()[i]; - if (start_size[i] <= 0 && end_size[i] <= 0) { - selection_span.slice(current_point, spline->size()).fill(false); - } - else { - int start_use = std::max(start_size[i], 0); - int end_use = std::max(end_size[i], 0); - select_by_spline(start_use, end_use, selection_span.slice(current_point, spline->size())); - } - current_point += spline->size(); - } + devirtualize_varray2(start_size, end_size, [&](const auto &start_size, const auto &end_size) { + threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange curves_range) { + for (const int i : curves_range) { + const IndexRange range = curves.range_for_curve(i); + const int start = std::max(start_size[i], 0); + const int end = std::max(end_size[i], 0); + + selection_span.slice(range.take_front(start)).fill(true); + selection_span.slice(range.take_back(end)).fill(true); + } + }); + }); + return VArray<bool>::ForContainer(std::move(selection)); }; _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
