From d3a1e9cbb92cca04e2fcbce3b8de3fdf25f2fcc6 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Thu, 24 Mar 2022 18:47:48 -0500 Subject: Geometry Nodes: Multi-thread creation of selection from field When boolean fields are evaluated and used as selections, we create a vector of indices. This process is currently single-threaded, but 226f0c4fef7e7792c added a more optimized multi-threaded version of this process. It's simple to use this in the field evaluator. I tested this with the set position node and a random value node set to boolean mode on a Ryzen 2700x: | | Before | After | Improvement | | 10% Selected | 40.5 ms | 29.0 ms | 1.4x | | 90% Selected | 115 ms | 45.3 ms | 2.5x | In the future there could be a specialized version for non-span virtual array selections that uses `materialize` to lower virtual call overhead. Differential Revision: https://developer.blender.org/D14436 --- source/blender/functions/intern/field.cc | 36 +++++++++++++------------------- 1 file changed, 14 insertions(+), 22 deletions(-) (limited to 'source/blender/functions') diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc index 7b514b6a49b..9f742f11ce4 100644 --- a/source/blender/functions/intern/field.cc +++ b/source/blender/functions/intern/field.cc @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_index_mask_ops.hh" #include "BLI_map.hh" #include "BLI_multi_value_map.hh" #include "BLI_set.hh" @@ -692,29 +693,21 @@ GPointer FieldConstant::value() const * FieldEvaluator. */ -static Vector indices_from_selection(IndexMask mask, const VArray &selection) +static IndexMask index_mask_from_selection(const IndexMask full_mask, + VArray &selection, + ResourceScope &scope) { - /* If the selection is just a single value, it's best to avoid calling this - * function when constructing an IndexMask and use an IndexRange instead. */ - BLI_assert(!selection.is_single()); - - Vector indices; if (selection.is_span()) { Span span = selection.get_internal_span(); - for (const int64_t i : mask) { - if (span[i]) { - indices.append(i); - } - } + return index_mask_ops::find_indices_based_on_predicate( + full_mask, 4096, scope.construct>(), [&](const int curve_index) { + return span[curve_index]; + }); } - else { - for (const int i : mask) { - if (selection[i]) { - indices.append(i); - } - } - } - return indices; + return index_mask_ops::find_indices_based_on_predicate( + full_mask, 1024, scope.construct>(), [&](const int curve_index) { + return selection[curve_index]; + }); } int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst) @@ -763,7 +756,7 @@ static IndexMask evaluate_selection(const Field &selection_field, } return IndexRange(0); } - return scope.add_value(indices_from_selection(full_mask, selection)).as_span(); + return index_mask_from_selection(full_mask, selection, scope); } return full_mask; } @@ -799,8 +792,7 @@ IndexMask FieldEvaluator::get_evaluated_as_mask(const int field_index) } return IndexRange(0); } - - return scope_.add_value(indices_from_selection(mask_, varray)).as_span(); + return index_mask_from_selection(mask_, varray, scope_); } IndexMask FieldEvaluator::get_evaluated_selection_as_mask() -- cgit v1.2.3