Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenlib/BLI_index_mask_ops.hh14
-rw-r--r--source/blender/blenlib/intern/index_mask.cc49
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc12
-rw-r--r--source/blender/functions/intern/field.cc21
4 files changed, 68 insertions, 28 deletions
diff --git a/source/blender/blenlib/BLI_index_mask_ops.hh b/source/blender/blenlib/BLI_index_mask_ops.hh
index 48a1f27a2fa..f67abb1d550 100644
--- a/source/blender/blenlib/BLI_index_mask_ops.hh
+++ b/source/blender/blenlib/BLI_index_mask_ops.hh
@@ -13,6 +13,7 @@
#include "BLI_index_mask.hh"
#include "BLI_task.hh"
#include "BLI_vector.hh"
+#include "BLI_virtual_array.hh"
namespace blender::index_mask_ops {
@@ -57,4 +58,17 @@ inline IndexMask find_indices_based_on_predicate(const IndexMask indices_to_chec
return detail::find_indices_based_on_predicate__merge(indices_to_check, sub_masks, r_indices);
}
+/**
+ * Find the true indices in a virtual array. This is a version of
+ * #find_indices_based_on_predicate optimised for a virtual array input.
+ *
+ * \param parallel_grain_size: The grain size for when the virtual array isn't a span or a single
+ * value internally. This should be adjusted based on the expected cost of evaluating the virtual
+ * array-- more expensive virtual arrays should have smaller grain sizes.
+ */
+IndexMask find_indices_from_virtual_array(IndexMask indices_to_check,
+ const VArray<bool> &virtual_array,
+ int64_t parallel_grain_size,
+ Vector<int64_t> &r_indices);
+
} // namespace blender::index_mask_ops
diff --git a/source/blender/blenlib/intern/index_mask.cc b/source/blender/blenlib/intern/index_mask.cc
index 1e301bc5fb9..f3590e4a41c 100644
--- a/source/blender/blenlib/intern/index_mask.cc
+++ b/source/blender/blenlib/intern/index_mask.cc
@@ -128,7 +128,9 @@ Vector<IndexRange> IndexMask::extract_ranges_invert(const IndexRange full_range,
} // namespace blender
-namespace blender::index_mask_ops::detail {
+namespace blender::index_mask_ops {
+
+namespace detail {
IndexMask find_indices_based_on_predicate__merge(
IndexMask indices_to_check,
@@ -193,4 +195,47 @@ IndexMask find_indices_based_on_predicate__merge(
return r_indices.as_span();
}
-} // namespace blender::index_mask_ops::detail
+} // namespace detail
+
+IndexMask find_indices_from_virtual_array(const IndexMask indices_to_check,
+ const VArray<bool> &virtual_array,
+ const int64_t parallel_grain_size,
+ Vector<int64_t> &r_indices)
+{
+ if (virtual_array.is_single()) {
+ return virtual_array.get_internal_single() ? indices_to_check : IndexMask(0);
+ }
+ if (virtual_array.is_span()) {
+ const Span<bool> span = virtual_array.get_internal_span();
+ return find_indices_based_on_predicate(
+ indices_to_check, 4096, r_indices, [&](const int64_t i) { return span[i]; });
+ }
+
+ threading::EnumerableThreadSpecific<Vector<bool>> materialize_buffers;
+ threading::EnumerableThreadSpecific<Vector<Vector<int64_t>>> sub_masks;
+
+ threading::parallel_for(
+ indices_to_check.index_range(), parallel_grain_size, [&](const IndexRange range) {
+ const IndexMask sliced_mask = indices_to_check.slice(range);
+
+ /* To avoid virtual function call overhead from accessing the virtual array,
+ * materialize the necessary indices for this chunk into a reused buffer. */
+ Vector<bool> &buffer = materialize_buffers.local();
+ buffer.reinitialize(sliced_mask.size());
+ virtual_array.materialize_compressed(sliced_mask, buffer);
+
+ Vector<int64_t> masked_indices;
+ sliced_mask.to_best_mask_type([&](auto best_mask) {
+ for (const int64_t i : IndexRange(best_mask.size())) {
+ if (buffer[i]) {
+ masked_indices.append(best_mask[i]);
+ }
+ }
+ });
+ sub_masks.local().append(std::move(masked_indices));
+ });
+
+ return detail::find_indices_based_on_predicate__merge(indices_to_check, sub_masks, r_indices);
+}
+
+} // namespace blender::index_mask_ops
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
index bd015784ad7..0fb4ded3b2a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex_color_ops.cc
@@ -177,10 +177,8 @@ static IndexMask get_selected_indices(const Mesh &mesh,
ATTR_DOMAIN_FACE,
domain);
- return index_mask_ops::find_indices_based_on_predicate(
- IndexMask(component.attribute_domain_num(domain)), 4096, indices, [&](const int i) {
- return selection[i];
- });
+ return index_mask_ops::find_indices_from_virtual_array(
+ IndexMask(component.attribute_domain_num(domain)), selection, 4096, indices);
}
if (mesh.editflag & ME_EDIT_PAINT_VERT_SEL) {
const VArray<bool> selection = component.attribute_try_adapt_domain(
@@ -188,10 +186,8 @@ static IndexMask get_selected_indices(const Mesh &mesh,
ATTR_DOMAIN_POINT,
domain);
- return index_mask_ops::find_indices_based_on_predicate(
- IndexMask(component.attribute_domain_num(domain)), 4096, indices, [&](const int i) {
- return selection[i];
- });
+ return index_mask_ops::find_indices_from_virtual_array(
+ IndexMask(component.attribute_domain_num(domain)), selection, 4096, indices);
}
return IndexMask(component.attribute_domain_num(domain));
}
diff --git a/source/blender/functions/intern/field.cc b/source/blender/functions/intern/field.cc
index 47f6a0f19ca..fd5eab57d33 100644
--- a/source/blender/functions/intern/field.cc
+++ b/source/blender/functions/intern/field.cc
@@ -708,20 +708,11 @@ GPointer FieldConstant::value() const
*/
static IndexMask index_mask_from_selection(const IndexMask full_mask,
- VArray<bool> &selection,
+ const VArray<bool> &selection,
ResourceScope &scope)
{
- if (selection.is_span()) {
- Span<bool> span = selection.get_internal_span();
- 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];
- });
- }
- 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];
- });
+ return index_mask_ops::find_indices_from_virtual_array(
+ full_mask, selection, 1024, scope.construct<Vector<int64_t>>());
}
int FieldEvaluator::add_with_destination(GField field, GVMutableArray dst)
@@ -764,12 +755,6 @@ static IndexMask evaluate_selection(const Field<bool> &selection_field,
if (selection_field) {
VArray<bool> selection =
evaluate_fields(scope, {selection_field}, full_mask, context)[0].typed<bool>();
- if (selection.is_single()) {
- if (selection.get_internal_single()) {
- return full_mask;
- }
- return IndexRange(0);
- }
return index_mask_from_selection(full_mask, selection, scope);
}
return full_mask;