[Bf-blender-cvs] [d3a1e9cbb92] master: Geometry Nodes: Multi-thread creation of selection from field

Hans Goudey noreply at git.blender.org
Fri Mar 25 00:48:46 CET 2022


Commit: d3a1e9cbb92cca04e2fcbce3b8de3fdf25f2fcc6
Author: Hans Goudey
Date:   Thu Mar 24 18:47:48 2022 -0500
Branches: master
https://developer.blender.org/rBd3a1e9cbb92cca04e2fcbce3b8de3fdf25f2fcc6

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

===================================================================

M	source/blender/functions/intern/field.cc

===================================================================

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<int64_t> indices_from_selection(IndexMask mask, const VArray<bool> &selection)
+static IndexMask index_mask_from_selection(const IndexMask full_mask,
+                                           VArray<bool> &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<int64_t> indices;
   if (selection.is_span()) {
     Span<bool> 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<Vector<int64_t>>(), [&](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<Vector<int64_t>>(), [&](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<bool> &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()



More information about the Bf-blender-cvs mailing list