[Bf-blender-cvs] [471f27d66bd] master: Curves: Port endpoint selection node to new data-block

Hans Goudey noreply at git.blender.org
Thu Mar 3 17:56:04 CET 2022


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));
   };



More information about the Bf-blender-cvs mailing list