BLI: Add generic utlity for gathering values with indices

Add new functions to `array_utils` namespace called `gather(..)`.
Versions of `GVArray::materialize_compressed_to_uninitialized(..)` with
threading have been reimplemented locally in multiple geometry node
contexts. The purpose of this patch is therefore to:
 * Assemble these implementations in a single file.
 * Provide a naming convention that is easier to recognize.

Differential Revision: https://developer.blender.org/D15786
This commit is contained in:
Mattias Fredriksson
2022-09-17 22:12:02 -05:00
committed by Hans Goudey
parent 095516403c
commit ce54f48556
4 changed files with 93 additions and 31 deletions

View File

@@ -6,6 +6,7 @@
#include "BLI_generic_virtual_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_task.hh"
#include "BLI_virtual_array.hh"
namespace blender::array_utils {
@@ -25,6 +26,7 @@ inline void copy(const Span<T> src,
MutableSpan<T> dst,
const int64_t grain_size = 4096)
{
BLI_assert(src.size() == dst.size());
threading::parallel_for(selection.index_range(), grain_size, [&](const IndexRange range) {
for (const int64_t index : selection.slice(range)) {
dst[index] = src[index];
@@ -32,4 +34,77 @@ inline void copy(const Span<T> src,
});
}
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
void gather(const GVArray &src, IndexMask indices, GMutableSpan dst, int64_t grain_size = 4096);
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
template<typename T>
inline void gather(const VArray<T> &src,
const IndexMask indices,
MutableSpan<T> dst,
const int64_t grain_size = 4096)
{
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
});
}
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
template<typename T, typename IndexT>
inline void gather(const Span<T> src,
const IndexMask indices,
MutableSpan<T> dst,
const int64_t grain_size = 4096)
{
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[indices[i]];
}
});
}
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
template<typename T, typename IndexT>
inline void gather(const Span<T> src,
const Span<IndexT> indices,
MutableSpan<T> dst,
const int64_t grain_size = 4096)
{
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[indices[i]];
}
});
}
/**
* Fill the destination span by gathering indexed values from the `src` array.
*/
template<typename T, typename IndexT>
inline void gather(const VArray<T> &src,
const Span<IndexT> indices,
MutableSpan<T> dst,
const int64_t grain_size = 4096)
{
BLI_assert(indices.size() == dst.size());
devirtualize_varray(src, [&](const auto &src) {
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[indices[i]];
}
});
});
}
} // namespace blender::array_utils

View File

@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_task.hh"
namespace blender::array_utils {
@@ -17,4 +16,16 @@ void copy(const GVArray &src,
});
}
void gather(const GVArray &src,
const IndexMask indices,
GMutableSpan dst,
const int64_t grain_size)
{
BLI_assert(src.type() == dst.type());
BLI_assert(indices.size() == dst.size());
threading::parallel_for(indices.index_range(), grain_size, [&](const IndexRange range) {
src.materialize_compressed_to_uninitialized(indices.slice(range), dst.slice(range).data());
});
}
} // namespace blender::array_utils

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_devirtualize_parameters.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"
@@ -18,19 +19,6 @@
namespace blender::geometry {
template<typename T>
static void copy_with_map(const VArray<T> &src, Span<int> map, MutableSpan<T> dst)
{
devirtualize_varray(src, [&](const auto &src) {
threading::parallel_for(map.index_range(), 1024, [&](const IndexRange range) {
for (const int i : range) {
const int vert_index = map[i];
dst[i] = src[vert_index];
}
});
});
}
bke::CurvesGeometry create_curve_from_vert_indices(const Mesh &mesh,
const Span<int> vert_indices,
const Span<int> curve_offsets,
@@ -71,7 +59,7 @@ bke::CurvesGeometry create_curve_from_vert_indices(const Mesh &mesh,
using T = decltype(dummy);
bke::SpanAttributeWriter<T> attribute =
curves_attributes.lookup_or_add_for_write_only_span<T>(attribute_id, ATTR_DOMAIN_POINT);
copy_with_map<T>(mesh_attribute.typed<T>(), vert_indices, attribute.span);
array_utils::gather<T>(mesh_attribute.typed<T>(), vert_indices, attribute.span);
attribute.finish();
});
}

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_array_utils.hh"
#include "BLI_task.hh"
#include "DNA_mesh_types.h"
@@ -44,17 +45,6 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node)
node->storage = data;
}
static void materialize_compressed_to_uninitialized_threaded(const GVArray &src,
const IndexMask mask,
GMutableSpan dst)
{
BLI_assert(src.type() == dst.type());
BLI_assert(mask.size() == dst.size());
threading::parallel_for(mask.index_range(), 4096, [&](IndexRange range) {
src.materialize_compressed_to_uninitialized(mask.slice(range), dst.slice(range).data());
});
}
static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
Field<float3> &position_field,
Field<float> &radius_field,
@@ -88,14 +78,12 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
GSpanAttributeWriter position = dst_attributes.lookup_or_add_for_write_only_span(
"position", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3);
materialize_compressed_to_uninitialized_threaded(
evaluator.get_evaluated(0), selection, position.span);
array_utils::gather(evaluator.get_evaluated(0), selection, position.span);
position.finish();
GSpanAttributeWriter radius = dst_attributes.lookup_or_add_for_write_only_span(
"radius", ATTR_DOMAIN_POINT, CD_PROP_FLOAT);
materialize_compressed_to_uninitialized_threaded(
evaluator.get_evaluated(1), selection, radius.span);
array_utils::gather(evaluator.get_evaluated(1), selection, radius.span);
radius.finish();
Map<AttributeIDRef, AttributeKind> attributes;
@@ -112,7 +100,7 @@ static void geometry_set_mesh_to_points(GeometrySet &geometry_set,
GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
attribute_id, ATTR_DOMAIN_POINT, data_type);
if (dst && src) {
materialize_compressed_to_uninitialized_threaded(src, selection, dst.span);
array_utils::gather(src, selection, dst.span);
dst.finish();
}
}