WIP: Functions: new local allocator for better memory reuse and performance #104630

Draft
Jacques Lucke wants to merge 44 commits from JacquesLucke/blender:local-allocator into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
32 changed files with 201 additions and 356 deletions
Showing only changes of commit 2a8b965af8 - Show all commits

View File

@ -313,8 +313,7 @@ class CurveLengthFieldInput final : public CurvesFieldInput {
bool try_capture_field_on_geometry(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const fn::GField &field,
LocalAllocator *allocator = nullptr);
const fn::GField &field);
/**
* Try to find the geometry domain that the field should be evaluated on. If it is not obvious

View File

@ -408,8 +408,7 @@ bool NormalFieldInput::is_equal_to(const fn::FieldNode &other) const
bool try_capture_field_on_geometry(GeometryComponent &component,
const AttributeIDRef &attribute_id,
const eAttrDomain domain,
const fn::GField &field,
LocalAllocator *allocator)
const fn::GField &field)
{
MutableAttributeAccessor attributes = *component.attributes_for_write();
const int domain_size = attributes.domain_size(domain);
@ -429,7 +428,7 @@ bool try_capture_field_on_geometry(GeometryComponent &component,
* - The field does not depend on that attribute (we can't easily check for that yet). */
void *buffer = MEM_mallocN(type.size() * domain_size, __func__);
fn::FieldEvaluator evaluator{field_context, &mask, allocator};
fn::FieldEvaluator evaluator{field_context, &mask};
evaluator.add_with_destination(validator.validate_field_if_necessary(field),
GMutableSpan{type, buffer, domain_size});
evaluator.evaluate();

View File

@ -334,7 +334,6 @@ class FieldEvaluator : NonMovable, NonCopyable {
ResourceScope scope_;
const FieldContext &context_;
const IndexMask mask_;
LocalAllocator *allocator_ = nullptr;
Vector<GField> fields_to_evaluate_;
Vector<GVMutableArray> dst_varrays_;
Vector<GVArray> evaluated_varrays_;
@ -346,18 +345,13 @@ class FieldEvaluator : NonMovable, NonCopyable {
public:
/** Takes #mask by pointer because the mask has to live longer than the evaluator. */
FieldEvaluator(const FieldContext &context,
const IndexMask *mask,
LocalAllocator *allocator = nullptr)
: context_(context), mask_(*mask), allocator_(allocator)
FieldEvaluator(const FieldContext &context, const IndexMask *mask)
: context_(context), mask_(*mask)
{
}
/** Construct a field evaluator for all indices less than #size. */
FieldEvaluator(const FieldContext &context,
const int64_t size,
LocalAllocator *allocator = nullptr)
: context_(context), mask_(size), allocator_(allocator)
FieldEvaluator(const FieldContext &context, const int64_t size) : context_(context), mask_(size)
{
}
@ -480,7 +474,6 @@ class FieldEvaluator : NonMovable, NonCopyable {
* provided virtual arrays are returned.
*/
Vector<GVArray> evaluate_fields(ResourceScope &scope,
LocalAllocator *allocator,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,

View File

@ -12,30 +12,24 @@
* - Pass cached data to called functions.
*/
#include "BLI_local_allocator.hh"
#include "BLI_utildefines.h"
#include "BLI_map.hh"
namespace blender::fn {
class MFContext;
class MFContextBuilder {
private:
std::unique_ptr<LocalAllocatorSet> allocator_set_;
LocalAllocator *allocator_;
Map<std::string, const void *> global_contexts_;
friend MFContext;
public:
MFContextBuilder(LocalAllocator *allocator = nullptr)
template<typename T> void add_global_context(std::string name, const T *context)
{
if (allocator) {
allocator_ = allocator;
}
else {
allocator_set_ = std::make_unique<LocalAllocatorSet>();
allocator_ = &allocator_set_->local();
}
global_contexts_.add_new(std::move(name), static_cast<const void *>(context));
}
};
@ -48,9 +42,11 @@ class MFContext {
{
}
LocalAllocator &allocator()
template<typename T> const T *get_global_context(StringRef name) const
{
return *builder_.allocator_;
const void *context = builder_.global_contexts_.lookup_default_as(name, nullptr);
/* TODO: Implement type checking. */
return static_cast<const T *>(context);
}
};

View File

@ -277,7 +277,6 @@ static void build_multi_function_procedure_for_fields(MFProcedure &procedure,
}
Vector<GVArray> evaluate_fields(ResourceScope &scope,
LocalAllocator *allocator,
Span<GFieldRef> fields_to_evaluate,
IndexMask mask,
const FieldContext &context,
@ -373,7 +372,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
MFProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, &mask};
MFContextBuilder mf_context{allocator};
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) {
@ -424,7 +423,7 @@ Vector<GVArray> evaluate_fields(ResourceScope &scope,
procedure, scope, field_tree_info, constant_fields_to_evaluate);
MFProcedureExecutor procedure_executor{procedure};
MFParamsBuilder mf_params{procedure_executor, 1};
MFContextBuilder mf_context{allocator};
MFContextBuilder mf_context;
/* Provide inputs to the procedure executor. */
for (const GVArray &varray : field_context_inputs) {
@ -501,7 +500,7 @@ void evaluate_constant_field(const GField &field, void *r_value)
ResourceScope scope;
FieldContext context;
Vector<GVArray> varrays = evaluate_fields(scope, nullptr, {field}, IndexRange(1), context);
Vector<GVArray> varrays = evaluate_fields(scope, {field}, IndexRange(1), context);
varrays[0].get_to_uninitialized(0, r_value);
}
@ -772,12 +771,11 @@ int FieldEvaluator::add(GField field)
static IndexMask evaluate_selection(const Field<bool> &selection_field,
const FieldContext &context,
IndexMask full_mask,
ResourceScope &scope,
LocalAllocator *allocator)
ResourceScope &scope)
{
if (selection_field) {
VArray<bool> selection =
evaluate_fields(scope, allocator, {selection_field}, full_mask, context)[0].typed<bool>();
evaluate_fields(scope, {selection_field}, full_mask, context)[0].typed<bool>();
return index_mask_from_selection(full_mask, selection, scope);
}
return full_mask;
@ -787,14 +785,13 @@ void FieldEvaluator::evaluate()
{
BLI_assert_msg(!is_evaluated_, "Cannot evaluate fields twice.");
selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_, allocator_);
selection_mask_ = evaluate_selection(selection_field_, context_, mask_, scope_);
Array<GFieldRef> fields(fields_to_evaluate_.size());
for (const int i : fields_to_evaluate_.index_range()) {
fields[i] = fields_to_evaluate_[i];
}
evaluated_varrays_ = evaluate_fields(
scope_, allocator_, fields, selection_mask_, context_, dst_varrays_);
evaluated_varrays_ = evaluate_fields(scope_, fields, selection_mask_, context_, dst_varrays_);
BLI_assert(fields_to_evaluate_.size() == evaluated_varrays_.size());
for (const int i : fields_to_evaluate_.index_range()) {
OutputPointerInfo &info = output_pointer_infos_[i];

View File

@ -73,7 +73,6 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
threading::parallel_for(mask.index_range(), grain_size, [&](const IndexRange sub_range) {
const IndexMask sliced_mask = mask.slice(sub_range);
MFContextBuilder sub_context{&context.allocator().local()};
if (!hints.allocates_array) {
/* There is no benefit to changing indices in this case. */
this->call(sliced_mask, params, context);
@ -81,7 +80,7 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
}
if (sliced_mask[0] < grain_size) {
/* The indices are low, no need to offset them. */
this->call(sliced_mask, params, sub_context);
this->call(sliced_mask, params, context);
return;
}
const int64_t input_slice_start = sliced_mask[0];
@ -128,7 +127,7 @@ void MultiFunction::call_auto(IndexMask mask, MFParams params, MFContext context
}
}
this->call(offset_mask, offset_params, sub_context);
this->call(offset_mask, offset_params, context);
});
}

View File

@ -117,21 +117,6 @@ static_assert(std::is_trivially_destructible_v<VariableValue_GVectorArray>);
static_assert(std::is_trivially_destructible_v<VariableValue_OneSingle>);
static_assert(std::is_trivially_destructible_v<VariableValue_OneVector>);
static constexpr int64_t max_variable_value_size = int64_t(
std::max<size_t>({sizeof(VariableValue_GVArray),
sizeof(VariableValue_Span),
sizeof(VariableValue_GVVectorArray),
sizeof(VariableValue_GVectorArray),
sizeof(VariableValue_OneSingle),
sizeof(VariableValue_OneVector)}));
static constexpr int64_t max_variable_value_alignment = int64_t(
std::max<size_t>({alignof(VariableValue_GVArray),
alignof(VariableValue_Span),
alignof(VariableValue_GVVectorArray),
alignof(VariableValue_GVectorArray),
alignof(VariableValue_OneSingle),
alignof(VariableValue_OneVector)}));
class VariableState;
/**
@ -144,40 +129,33 @@ class ValueAllocator : NonCopyable, NonMovable {
* Allocate with 64 byte alignment for better reusability of buffers and improved cache
* performance.
*/
static constexpr inline int s_span_alignment = 64;
static constexpr inline int min_alignment = 64;
/** All buffers in the free-lists below have been allocated with this allocator. */
LocalAllocator &local_allocator_;
int array_size_;
LinearAllocator<> &linear_allocator_;
/**
* Use stacks so that the most recently used buffers are reused first. This improves cache
* efficiency.
*/
LocalAllocatorPool *variable_value_pool_;
std::array<Stack<VariableValue *>, tot_variable_value_types> variable_value_free_lists_;
/**
* The integer key is the size of one element (e.g. 4 for an integer buffer). All buffers are
* aligned to #min_alignment bytes.
*/
LocalAllocatorPool *small_span_buffers_pool_;
Stack<void *> small_span_buffers_free_list_;
Map<int, Stack<void *>> span_buffers_free_lists_;
/** Cache buffers for single values of different types. */
static constexpr inline int small_value_max_size = 16;
static constexpr inline int small_value_max_alignment = 8;
LocalAllocatorPool *small_values_pool_;
Stack<void *> small_single_value_free_list_;
Map<const CPPType *, Stack<void *>> single_value_free_lists_;
public:
ValueAllocator(LocalAllocator &local_allocator, const int array_size)
: local_allocator_(local_allocator), array_size_(array_size)
ValueAllocator(LinearAllocator<> &linear_allocator) : linear_allocator_(linear_allocator)
{
variable_value_pool_ = &local_allocator.get_pool(max_variable_value_size,
max_variable_value_alignment);
small_span_buffers_pool_ = &local_allocator.get_pool(
std::max<int64_t>(s_span_alignment, small_value_max_size * array_size), s_span_alignment);
small_values_pool_ = &local_allocator.get_pool(small_value_max_size,
small_value_max_alignment);
}
VariableValue_GVArray *obtain_GVArray(const GVArray &varray)
@ -195,17 +173,30 @@ class ValueAllocator : NonCopyable, NonMovable {
return this->obtain<VariableValue_Span>(buffer, false);
}
VariableValue_Span *obtain_Span(const CPPType &type)
VariableValue_Span *obtain_Span(const CPPType &type, int size)
{
const bool is_small = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment);
void *buffer = nullptr;
if (is_small) {
buffer = local_allocator_.allocate(*small_span_buffers_pool_);
const int64_t element_size = type.size();
const int64_t alignment = type.alignment();
if (alignment > min_alignment) {
/* In this rare case we fallback to not reusing existing buffers. */
buffer = linear_allocator_.allocate(element_size * size, alignment);
}
else {
buffer = local_allocator_.allocate(type.size() * array_size_, type.alignment());
Stack<void *> *stack = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment) ?
&small_span_buffers_free_list_ :
span_buffers_free_lists_.lookup_ptr(element_size);
if (stack == nullptr || stack->is_empty()) {
buffer = linear_allocator_.allocate(
std::max<int64_t>(element_size, small_value_max_size) * size, min_alignment);
}
else {
/* Reuse existing buffer. */
buffer = stack->pop();
}
}
return this->obtain<VariableValue_Span>(buffer, true);
@ -216,9 +207,9 @@ class ValueAllocator : NonCopyable, NonMovable {
return this->obtain<VariableValue_GVectorArray>(data, false);
}
VariableValue_GVectorArray *obtain_GVectorArray(const CPPType &type)
VariableValue_GVectorArray *obtain_GVectorArray(const CPPType &type, int size)
{
GVectorArray *vector_array = new GVectorArray(type, array_size_);
GVectorArray *vector_array = new GVectorArray(type, size);
return this->obtain<VariableValue_GVectorArray>(*vector_array, true);
}
@ -226,12 +217,16 @@ class ValueAllocator : NonCopyable, NonMovable {
{
const bool is_small = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment);
Stack<void *> &stack = is_small ? small_single_value_free_list_ :
single_value_free_lists_.lookup_or_add_default(&type);
void *buffer;
if (is_small) {
buffer = local_allocator_.allocate(*small_values_pool_);
if (stack.is_empty()) {
buffer = linear_allocator_.allocate(
std::max<int>(small_value_max_size, type.size()),
std::max<int>(small_value_max_alignment, type.alignment()));
}
else {
buffer = local_allocator_.allocate(type.size(), type.alignment());
buffer = stack.pop();
}
return this->obtain<VariableValue_OneSingle>(buffer);
}
@ -252,16 +247,12 @@ class ValueAllocator : NonCopyable, NonMovable {
auto *value_typed = static_cast<VariableValue_Span *>(value);
if (value_typed->owned) {
const CPPType &type = data_type.single_type();
const bool is_small = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment);
/* Assumes all values in the buffer are uninitialized already. */
if (is_small) {
local_allocator_.deallocate(value_typed->data, *small_span_buffers_pool_);
}
else {
local_allocator_.deallocate(
value_typed->data, type.size() * array_size_, type.alignment());
}
Stack<void *> &buffers = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment) ?
small_span_buffers_free_list_ :
span_buffers_free_lists_.lookup_or_add_default(type.size());
buffers.push(value_typed->data);
}
break;
}
@ -284,10 +275,10 @@ class ValueAllocator : NonCopyable, NonMovable {
const bool is_small = type.can_exist_in_buffer(small_value_max_size,
small_value_max_alignment);
if (is_small) {
local_allocator_.deallocate(value_typed->data, *small_values_pool_);
small_single_value_free_list_.push(value_typed->data);
}
else {
local_allocator_.deallocate(value_typed->data, type.size(), type.alignment());
single_value_free_lists_.lookup_or_add_default(&type).push(value_typed->data);
}
break;
}
@ -298,15 +289,20 @@ class ValueAllocator : NonCopyable, NonMovable {
}
}
local_allocator_.deallocate(value, *variable_value_pool_);
Stack<VariableValue *> &stack = variable_value_free_lists_[int(value->type)];
stack.push(value);
}
private:
template<typename T, typename... Args> T *obtain(Args &&...args)
{
static_assert(std::is_base_of_v<VariableValue, T>);
void *buffer = static_cast<T *>(local_allocator_.allocate(*variable_value_pool_));
return new (buffer) T(std::forward<Args>(args)...);
Stack<VariableValue *> &stack = variable_value_free_lists_[int(T::static_type)];
if (stack.is_empty()) {
void *buffer = linear_allocator_.allocate(sizeof(T), alignof(T));
return new (buffer) T(std::forward<Args>(args)...);
}
return new (stack.pop()) T(std::forward<Args>(args)...);
}
};
@ -418,7 +414,7 @@ class VariableState : NonCopyable, NonMovable {
const CPPType &type = data_type.single_type();
VariableValue_Span *new_value = nullptr;
if (caller_provided_storage_ == nullptr) {
new_value = value_allocator.obtain_Span(type);
new_value = value_allocator.obtain_Span(type, array_size);
}
else {
/* Reuse the storage provided caller when possible. */
@ -449,7 +445,7 @@ class VariableState : NonCopyable, NonMovable {
const CPPType &type = data_type.vector_base_type();
VariableValue_GVectorArray *new_value = nullptr;
if (caller_provided_storage_ == nullptr) {
new_value = value_allocator.obtain_GVectorArray(type);
new_value = value_allocator.obtain_GVectorArray(type, array_size);
}
else {
new_value = value_allocator.obtain_GVectorArray_not_owned(
@ -833,10 +829,10 @@ class VariableStates {
IndexMask full_mask_;
public:
VariableStates(LocalAllocator &local_allocator,
VariableStates(LinearAllocator<> &linear_allocator,
const MFProcedure &procedure,
IndexMask full_mask)
: value_allocator_(local_allocator, full_mask.min_array_size()),
: value_allocator_(linear_allocator),
procedure_(procedure),
variable_states_(procedure.variables().size()),
full_mask_(full_mask)
@ -1182,8 +1178,11 @@ void MFProcedureExecutor::call(IndexMask full_mask, MFParams params, MFContext c
{
BLI_assert(procedure_.validate());
LocalAllocator &local_allocator = context.allocator();
VariableStates variable_states{local_allocator, procedure_, full_mask};
AlignedBuffer<512, 64> local_buffer;
LinearAllocator<> linear_allocator;
linear_allocator.provide_buffer(local_buffer);
VariableStates variable_states{linear_allocator, procedure_, full_mask};
variable_states.add_initial_variable_states(*this, procedure_, params);
InstructionScheduler scheduler;

View File

@ -263,7 +263,7 @@ TEST(field, SameFieldTwice)
IndexMask mask{IndexRange(2)};
ResourceScope scope;
Vector<GVArray> results = evaluate_fields(
scope, nullptr, {constant_field, constant_field}, mask, field_context);
scope, {constant_field, constant_field}, mask, field_context);
VArray<int> varray1 = results[0].typed<int>();
VArray<int> varray2 = results[1].typed<int>();

View File

@ -257,11 +257,6 @@ class GeoNodeExecParams {
return dynamic_cast<GeoNodesLFUserData *>(lf_context_.user_data);
}
LocalAllocator &allocator()
{
return *lf_context_.allocator;
}
/**
* Add an error message displayed at the top of the node when displaying the node tree,
* and potentially elsewhere in Blender.

View File

@ -82,7 +82,6 @@ void separate_geometry(GeometrySet &geometry_set,
GeometryNodeDeleteGeometryMode mode,
const Field<bool> &selection_field,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator,
bool &r_is_error);
void get_closest_in_bvhtree(BVHTreeFromMesh &tree_data,

View File

@ -181,8 +181,7 @@ static void node_geo_exec(GeoNodeExecParams params)
if (geometry_set.has_instances()) {
GeometryComponent &component = geometry_set.get_component_for_write(
GEO_COMPONENT_TYPE_INSTANCES);
bke::try_capture_field_on_geometry(
component, *attribute_id, domain, field, &params.allocator());
bke::try_capture_field_on_geometry(component, *attribute_id, domain, field);
}
}
else {
@ -193,8 +192,7 @@ static void node_geo_exec(GeoNodeExecParams params)
for (const GeometryComponentType type : types) {
if (geometry_set.has(type)) {
GeometryComponent &component = geometry_set.get_component_for_write(type);
bke::try_capture_field_on_geometry(
component, *attribute_id, domain, field, &params.allocator().local());
bke::try_capture_field_on_geometry(component, *attribute_id, domain, field);
}
}
});

View File

@ -307,15 +307,14 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh,
static void delete_curves_selection(GeometrySet &geometry_set,
const Field<bool> &selection_field,
const eAttrDomain selection_domain,
const bke::AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const bke::AnonymousAttributePropagationInfo &propagation_info)
{
const Curves &src_curves_id = *geometry_set.get_curves_for_read();
const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry);
const int domain_size = src_curves.attributes().domain_size(selection_domain);
bke::CurvesFieldContext field_context{src_curves, selection_domain};
fn::FieldEvaluator evaluator{field_context, domain_size, &allocator};
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.set_selection(selection_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
@ -342,13 +341,12 @@ static void delete_curves_selection(GeometrySet &geometry_set,
static void separate_point_cloud_selection(
GeometrySet &geometry_set,
const Field<bool> &selection_field,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
const PointCloud &src_pointcloud = *geometry_set.get_pointcloud_for_read();
bke::PointCloudFieldContext field_context{src_pointcloud};
fn::FieldEvaluator evaluator{field_context, src_pointcloud.totpoint, &allocator};
fn::FieldEvaluator evaluator{field_context, src_pointcloud.totpoint};
evaluator.set_selection(selection_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
@ -376,13 +374,12 @@ static void separate_point_cloud_selection(
static void delete_selected_instances(GeometrySet &geometry_set,
const Field<bool> &selection_field,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
bke::Instances &instances = *geometry_set.get_instances_for_write();
bke::InstancesFieldContext field_context{instances};
fn::FieldEvaluator evaluator{field_context, instances.instances_num(), &allocator};
fn::FieldEvaluator evaluator{field_context, instances.instances_num()};
evaluator.set_selection(selection_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
@ -1099,7 +1096,6 @@ void separate_geometry(GeometrySet &geometry_set,
const GeometryNodeDeleteGeometryMode mode,
const Field<bool> &selection_field,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator,
bool &r_is_error)
{
namespace file_ns = blender::nodes::node_geo_delete_geometry_cc;
@ -1107,8 +1103,7 @@ void separate_geometry(GeometrySet &geometry_set,
bool some_valid_domain = false;
if (geometry_set.has_pointcloud()) {
if (domain == ATTR_DOMAIN_POINT) {
file_ns::separate_point_cloud_selection(
geometry_set, selection_field, propagation_info, allocator);
file_ns::separate_point_cloud_selection(geometry_set, selection_field, propagation_info);
some_valid_domain = true;
}
}
@ -1121,18 +1116,14 @@ void separate_geometry(GeometrySet &geometry_set,
}
if (geometry_set.has_curves()) {
if (ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
file_ns::delete_curves_selection(geometry_set,
fn::invert_boolean_field(selection_field),
domain,
propagation_info,
allocator);
file_ns::delete_curves_selection(
geometry_set, fn::invert_boolean_field(selection_field), domain, propagation_info);
some_valid_domain = true;
}
}
if (geometry_set.has_instances()) {
if (domain == ATTR_DOMAIN_INSTANCE) {
file_ns::delete_selected_instances(
geometry_set, selection_field, propagation_info, allocator);
file_ns::delete_selected_instances(geometry_set, selection_field, propagation_info);
some_valid_domain = true;
}
}
@ -1197,20 +1188,13 @@ static void node_geo_exec(GeoNodeExecParams params)
if (domain == ATTR_DOMAIN_INSTANCE) {
bool is_error;
separate_geometry(
geometry_set, domain, mode, selection, propagation_info, params.allocator(), is_error);
separate_geometry(geometry_set, domain, mode, selection, propagation_info, is_error);
}
else {
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
bool is_error;
/* Invert here because we want to keep the things not in the selection. */
separate_geometry(geometry_set,
domain,
mode,
selection,
propagation_info,
params.allocator().local(),
is_error);
separate_geometry(geometry_set, domain, mode, selection, propagation_info, is_error);
});
}

View File

@ -385,15 +385,14 @@ BLI_NOINLINE static void compute_attribute_outputs(const Mesh &mesh,
static Array<float> calc_full_density_factors_with_selection(const Mesh &mesh,
const Field<float> &density_field,
const Field<bool> &selection_field,
LocalAllocator &allocator)
const Field<bool> &selection_field)
{
const eAttrDomain domain = ATTR_DOMAIN_CORNER;
const int domain_size = mesh.attributes().domain_size(domain);
Array<float> densities(domain_size, 0.0f);
bke::MeshFieldContext field_context{mesh, domain};
fn::FieldEvaluator evaluator{field_context, domain_size, &allocator};
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.set_selection(selection_field);
evaluator.add_with_destination(density_field, densities.as_mutable_span());
evaluator.evaluate();
@ -404,13 +403,12 @@ static void distribute_points_random(const Mesh &mesh,
const Field<float> &density_field,
const Field<bool> &selection_field,
const int seed,
LocalAllocator &allocator,
Vector<float3> &positions,
Vector<float3> &bary_coords,
Vector<int> &looptri_indices)
{
const Array<float> densities = calc_full_density_factors_with_selection(
mesh, density_field, selection_field, allocator);
mesh, density_field, selection_field);
sample_mesh_surface(mesh, 1.0f, densities, seed, positions, bary_coords, looptri_indices);
}
@ -420,7 +418,6 @@ static void distribute_points_poisson_disk(const Mesh &mesh,
const Field<float> &density_factor_field,
const Field<bool> &selection_field,
const int seed,
LocalAllocator &allocator,
Vector<float3> &positions,
Vector<float3> &bary_coords,
Vector<int> &looptri_indices)
@ -431,7 +428,7 @@ static void distribute_points_poisson_disk(const Mesh &mesh,
update_elimination_mask_for_close_points(positions, minimum_distance, elimination_mask);
const Array<float> density_factors = calc_full_density_factors_with_selection(
mesh, density_factor_field, selection_field, allocator);
mesh, density_factor_field, selection_field);
update_elimination_mask_based_on_density_factors(
mesh, density_factors, bary_coords, looptri_indices, elimination_mask.as_mutable_span());
@ -445,8 +442,7 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
const GeometryNodeDistributePointsOnFacesMode method,
const int seed,
const AttributeOutputs &attribute_outputs,
const GeoNodeExecParams &params,
LocalAllocator &allocator)
const GeoNodeExecParams &params)
{
if (!geometry_set.has_mesh()) {
return;
@ -461,14 +457,8 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
switch (method) {
case GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_RANDOM: {
const Field<float> density_field = params.get_input<Field<float>>("Density");
distribute_points_random(mesh,
density_field,
selection_field,
seed,
allocator,
positions,
bary_coords,
looptri_indices);
distribute_points_random(
mesh, density_field, selection_field, seed, positions, bary_coords, looptri_indices);
break;
}
case GEO_NODE_POINT_DISTRIBUTE_POINTS_ON_FACES_POISSON: {
@ -481,7 +471,6 @@ static void point_distribution_calculate(GeometrySet &geometry_set,
density_factors_field,
selection_field,
seed,
allocator,
positions,
bary_coords,
looptri_indices);
@ -538,13 +527,8 @@ static void node_geo_exec(GeoNodeExecParams params)
lazy_threading::send_hint();
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
point_distribution_calculate(geometry_set,
selection_field,
method,
seed,
attribute_outputs,
params,
params.allocator().local());
point_distribution_calculate(
geometry_set, selection_field, method, seed, attribute_outputs, params);
/* Keep instances because the original geometry set may contain instances that are processed as
* well. */
geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_POINT_CLOUD});

View File

@ -324,8 +324,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
if (!geometry_set.has_curves()) {
geometry_set.remove_geometry_during_modify();
@ -338,7 +337,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
bke::CurvesFieldContext field_context{curves, ATTR_DOMAIN_CURVE};
FieldEvaluator evaluator{field_context, curves.curves_num(), &allocator};
FieldEvaluator evaluator{field_context, curves.curves_num()};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -517,8 +516,7 @@ static void duplicate_faces(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
if (!geometry_set.has_mesh()) {
geometry_set.remove_geometry_during_modify();
@ -533,7 +531,7 @@ static void duplicate_faces(GeometrySet &geometry_set,
const Span<MLoop> loops = mesh.loops();
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE};
FieldEvaluator evaluator(field_context, polys.size(), &allocator);
FieldEvaluator evaluator(field_context, polys.size());
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -720,8 +718,7 @@ static void duplicate_edges(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
if (!geometry_set.has_mesh()) {
geometry_set.remove_geometry_during_modify();
@ -731,7 +728,7 @@ static void duplicate_edges(GeometrySet &geometry_set,
const Span<MEdge> edges = mesh.edges();
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_EDGE};
FieldEvaluator evaluator{field_context, edges.size(), &allocator};
FieldEvaluator evaluator{field_context, edges.size()};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -801,8 +798,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
const Curves &src_curves_id = *geometry_set.get_curves_for_read();
const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry);
@ -811,7 +807,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
}
bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_POINT};
FieldEvaluator evaluator{field_context, src_curves.points_num(), &allocator};
FieldEvaluator evaluator{field_context, src_curves.points_num()};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -906,14 +902,13 @@ static void duplicate_points_mesh(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
const Mesh &mesh = *geometry_set.get_mesh_for_read();
const Span<MVert> src_verts = mesh.verts();
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_POINT};
FieldEvaluator evaluator{field_context, src_verts.size(), &allocator};
FieldEvaluator evaluator{field_context, src_verts.size()};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -959,13 +954,12 @@ static void duplicate_points_pointcloud(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
const PointCloud &src_points = *geometry_set.get_pointcloud_for_read();
bke::PointCloudFieldContext field_context{src_points};
FieldEvaluator evaluator{field_context, src_points.totpoint, &allocator};
FieldEvaluator evaluator{field_context, src_points.totpoint};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -1007,40 +1001,27 @@ static void duplicate_points(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
Vector<GeometryComponentType> component_types = geometry_set.gather_component_types(true, true);
for (const GeometryComponentType component_type : component_types) {
switch (component_type) {
case GEO_COMPONENT_TYPE_POINT_CLOUD:
if (geometry_set.has_pointcloud()) {
duplicate_points_pointcloud(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_points_pointcloud(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
}
break;
case GEO_COMPONENT_TYPE_MESH:
if (geometry_set.has_mesh()) {
duplicate_points_mesh(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_points_mesh(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
}
break;
case GEO_COMPONENT_TYPE_CURVE:
if (geometry_set.has_curves()) {
duplicate_points_curve(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_points_curve(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
}
break;
default:
@ -1061,8 +1042,7 @@ static void duplicate_instances(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
const IndexAttributes &attribute_outputs,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
if (!geometry_set.has_instances()) {
geometry_set.clear();
@ -1072,7 +1052,7 @@ static void duplicate_instances(GeometrySet &geometry_set,
const bke::Instances &src_instances = *geometry_set.get_instances_for_read();
bke::InstancesFieldContext field_context{src_instances};
FieldEvaluator evaluator{field_context, src_instances.instances_num(), &allocator};
FieldEvaluator evaluator{field_context, src_instances.instances_num()};
evaluator.add(count_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -1144,48 +1124,27 @@ static void node_geo_exec(GeoNodeExecParams params)
"Geometry");
if (duplicate_domain == ATTR_DOMAIN_INSTANCE) {
duplicate_instances(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
params.allocator());
duplicate_instances(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
}
else {
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
LocalAllocator &allocator = params.allocator().local();
switch (duplicate_domain) {
case ATTR_DOMAIN_CURVE:
duplicate_curves(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_curves(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
break;
case ATTR_DOMAIN_FACE:
duplicate_faces(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_faces(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
break;
case ATTR_DOMAIN_EDGE:
duplicate_edges(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_edges(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
break;
case ATTR_DOMAIN_POINT:
duplicate_points(geometry_set,
count_field,
selection_field,
attribute_outputs,
propagation_info,
allocator);
duplicate_points(
geometry_set, count_field, selection_field, attribute_outputs, propagation_info);
break;
default:
BLI_assert_unreachable();

View File

@ -25,8 +25,7 @@ static void node_geo_exec(GeoNodeExecParams params)
if (const Mesh *mesh = geometry_set.get_mesh_for_read()) {
bke::MeshFieldContext field_context{*mesh, ATTR_DOMAIN_EDGE};
fn::FieldEvaluator selection_evaluator{
field_context, mesh->totedge, &params.allocator().local()};
fn::FieldEvaluator selection_evaluator{field_context, mesh->totedge};
selection_evaluator.set_selection(selection_field);
selection_evaluator.evaluate();
const IndexMask mask = selection_evaluator.get_evaluated_selection_as_mask();

View File

@ -200,14 +200,13 @@ static Array<Vector<int>> create_vert_to_edge_map(const int vert_size,
static void extrude_mesh_vertices(Mesh &mesh,
const Field<bool> &selection_field,
const Field<float3> &offset_field,
const AttributeOutputs &attribute_outputs,
LocalAllocator &allocator)
const AttributeOutputs &attribute_outputs)
{
const int orig_vert_size = mesh.totvert;
const int orig_edge_size = mesh.totedge;
const bke::MeshFieldContext context{mesh, ATTR_DOMAIN_POINT};
FieldEvaluator evaluator{context, mesh.totvert, &allocator};
FieldEvaluator evaluator{context, mesh.totvert};
evaluator.add(offset_field);
evaluator.set_selection(selection_field);
evaluator.evaluate();
@ -369,8 +368,7 @@ static VectorSet<int> vert_indices_from_edges(const Mesh &mesh, const Span<T> ed
static void extrude_mesh_edges(Mesh &mesh,
const Field<bool> &selection_field,
const Field<float3> &offset_field,
const AttributeOutputs &attribute_outputs,
LocalAllocator &allocator)
const AttributeOutputs &attribute_outputs)
{
const int orig_vert_size = mesh.totvert;
const Span<MEdge> orig_edges = mesh.edges();
@ -378,7 +376,7 @@ static void extrude_mesh_edges(Mesh &mesh,
const int orig_loop_size = mesh.totloop;
const bke::MeshFieldContext edge_context{mesh, ATTR_DOMAIN_EDGE};
FieldEvaluator edge_evaluator{edge_context, mesh.totedge, &allocator};
FieldEvaluator edge_evaluator{edge_context, mesh.totedge};
edge_evaluator.set_selection(selection_field);
edge_evaluator.add(offset_field);
edge_evaluator.evaluate();
@ -649,8 +647,7 @@ static void extrude_mesh_edges(Mesh &mesh,
static void extrude_mesh_face_regions(Mesh &mesh,
const Field<bool> &selection_field,
const Field<float3> &offset_field,
const AttributeOutputs &attribute_outputs,
LocalAllocator &allocator)
const AttributeOutputs &attribute_outputs)
{
const int orig_vert_size = mesh.totvert;
const Span<MEdge> orig_edges = mesh.edges();
@ -658,7 +655,7 @@ static void extrude_mesh_face_regions(Mesh &mesh,
const Span<MLoop> orig_loops = mesh.loops();
const bke::MeshFieldContext poly_context{mesh, ATTR_DOMAIN_FACE};
FieldEvaluator poly_evaluator{poly_context, mesh.totpoly, &allocator};
FieldEvaluator poly_evaluator{poly_context, mesh.totpoly};
poly_evaluator.set_selection(selection_field);
poly_evaluator.add(offset_field);
poly_evaluator.evaluate();
@ -1053,8 +1050,7 @@ static IndexRange selected_corner_range(Span<int> offsets, const int index)
static void extrude_individual_mesh_faces(Mesh &mesh,
const Field<bool> &selection_field,
const Field<float3> &offset_field,
const AttributeOutputs &attribute_outputs,
LocalAllocator &allocator)
const AttributeOutputs &attribute_outputs)
{
const int orig_vert_size = mesh.totvert;
const int orig_edge_size = mesh.totedge;
@ -1065,7 +1061,7 @@ static void extrude_individual_mesh_faces(Mesh &mesh,
* the vertices are moved, and the evaluated result might reference an attribute. */
Array<float3> poly_offset(orig_polys.size());
const bke::MeshFieldContext poly_context{mesh, ATTR_DOMAIN_FACE};
FieldEvaluator poly_evaluator{poly_context, mesh.totpoly, &allocator};
FieldEvaluator poly_evaluator{poly_context, mesh.totpoly};
poly_evaluator.set_selection(selection_field);
poly_evaluator.add_with_destination(offset_field, poly_offset.as_mutable_span());
poly_evaluator.evaluate();
@ -1346,22 +1342,19 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (Mesh *mesh = geometry_set.get_mesh_for_write()) {
LocalAllocator &allocator = params.allocator().local();
switch (mode) {
case GEO_NODE_EXTRUDE_MESH_VERTICES:
extrude_mesh_vertices(*mesh, selection, final_offset, attribute_outputs, allocator);
extrude_mesh_vertices(*mesh, selection, final_offset, attribute_outputs);
break;
case GEO_NODE_EXTRUDE_MESH_EDGES:
extrude_mesh_edges(*mesh, selection, final_offset, attribute_outputs, allocator);
extrude_mesh_edges(*mesh, selection, final_offset, attribute_outputs);
break;
case GEO_NODE_EXTRUDE_MESH_FACES: {
if (extrude_individual) {
extrude_individual_mesh_faces(
*mesh, selection, final_offset, attribute_outputs, allocator);
extrude_individual_mesh_faces(*mesh, selection, final_offset, attribute_outputs);
}
else {
extrude_mesh_face_regions(
*mesh, selection, final_offset, attribute_outputs, allocator);
extrude_mesh_face_regions(*mesh, selection, final_offset, attribute_outputs);
}
break;
}

View File

@ -79,7 +79,7 @@ static void node_geo_exec(GeoNodeExecParams params)
"radius", ATTR_DOMAIN_POINT);
PointsFieldContext context{count};
fn::FieldEvaluator evaluator{context, count, &params.allocator()};
fn::FieldEvaluator evaluator{context, count};
evaluator.add_with_destination(position_field, output_position.varray);
evaluator.add_with_destination(radius_field, output_radii.varray);
evaluator.evaluate();

View File

@ -24,8 +24,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void geometry_set_points_to_vertices(
GeometrySet &geometry_set,
Field<bool> &selection_field,
const AnonymousAttributePropagationInfo &propagation_info,
LocalAllocator &allocator)
const AnonymousAttributePropagationInfo &propagation_info)
{
const PointCloud *points = geometry_set.get_pointcloud_for_read();
if (points == nullptr) {
@ -38,7 +37,7 @@ static void geometry_set_points_to_vertices(
}
bke::PointCloudFieldContext field_context{*points};
fn::FieldEvaluator selection_evaluator{field_context, points->totpoint, &allocator};
fn::FieldEvaluator selection_evaluator{field_context, points->totpoint};
selection_evaluator.add(selection_field);
selection_evaluator.evaluate();
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
@ -79,10 +78,8 @@ static void node_geo_exec(GeoNodeExecParams params)
Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
geometry_set_points_to_vertices(geometry_set,
selection_field,
params.get_output_propagation_info("Mesh"),
params.allocator().local());
geometry_set_points_to_vertices(
geometry_set, selection_field, params.get_output_propagation_info("Mesh"));
});
params.set_output("Mesh", std::move(geometry_set));

View File

@ -307,12 +307,10 @@ static AxisScaleParams evaluate_axis_scale_fields(FieldEvaluator &evaluator,
return out;
}
static void scale_faces_on_axis(Mesh &mesh,
const AxisScaleFields &fields,
LocalAllocator &allocator)
static void scale_faces_on_axis(Mesh &mesh, const AxisScaleFields &fields)
{
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE};
FieldEvaluator evaluator{field_context, mesh.totpoly, &allocator};
FieldEvaluator evaluator{field_context, mesh.totpoly};
AxisScaleParams params = evaluate_axis_scale_fields(evaluator, fields);
Vector<ElementIsland> island = prepare_face_islands(mesh, params.selection);
@ -331,12 +329,10 @@ static UniformScaleParams evaluate_uniform_scale_fields(FieldEvaluator &evaluato
return out;
}
static void scale_faces_uniformly(Mesh &mesh,
const UniformScaleFields &fields,
LocalAllocator &allocator)
static void scale_faces_uniformly(Mesh &mesh, const UniformScaleFields &fields)
{
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE};
FieldEvaluator evaluator{field_context, mesh.totpoly, &allocator};
FieldEvaluator evaluator{field_context, mesh.totpoly};
UniformScaleParams params = evaluate_uniform_scale_fields(evaluator, fields);
Vector<ElementIsland> island = prepare_face_islands(mesh, params.selection);
@ -385,24 +381,20 @@ static void get_edge_verts(const Span<MEdge> edges,
r_vertex_indices.add(edge.v2);
}
static void scale_edges_uniformly(Mesh &mesh,
const UniformScaleFields &fields,
LocalAllocator &allocator)
static void scale_edges_uniformly(Mesh &mesh, const UniformScaleFields &fields)
{
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_EDGE};
FieldEvaluator evaluator{field_context, mesh.totedge, &allocator};
FieldEvaluator evaluator{field_context, mesh.totedge};
UniformScaleParams params = evaluate_uniform_scale_fields(evaluator, fields);
Vector<ElementIsland> island = prepare_edge_islands(mesh, params.selection);
scale_vertex_islands_uniformly(mesh, island, params, get_edge_verts);
}
static void scale_edges_on_axis(Mesh &mesh,
const AxisScaleFields &fields,
LocalAllocator &allocator)
static void scale_edges_on_axis(Mesh &mesh, const AxisScaleFields &fields)
{
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_EDGE};
FieldEvaluator evaluator{field_context, mesh.totedge, &allocator};
FieldEvaluator evaluator{field_context, mesh.totedge};
AxisScaleParams params = evaluate_axis_scale_fields(evaluator, fields);
Vector<ElementIsland> island = prepare_edge_islands(mesh, params.selection);
@ -427,18 +419,15 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry.modify_geometry_sets([&](GeometrySet &geometry) {
if (Mesh *mesh = geometry.get_mesh_for_write()) {
LocalAllocator &allocator = params.allocator().local();
switch (domain) {
case ATTR_DOMAIN_FACE: {
switch (scale_mode) {
case GEO_NODE_SCALE_ELEMENTS_UNIFORM: {
scale_faces_uniformly(
*mesh, {selection_field, scale_field, center_field}, allocator);
scale_faces_uniformly(*mesh, {selection_field, scale_field, center_field});
break;
}
case GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS: {
scale_faces_on_axis(
*mesh, {selection_field, scale_field, center_field, axis_field}, allocator);
scale_faces_on_axis(*mesh, {selection_field, scale_field, center_field, axis_field});
break;
}
}
@ -447,13 +436,11 @@ static void node_geo_exec(GeoNodeExecParams params)
case ATTR_DOMAIN_EDGE: {
switch (scale_mode) {
case GEO_NODE_SCALE_ELEMENTS_UNIFORM: {
scale_edges_uniformly(
*mesh, {selection_field, scale_field, center_field}, allocator);
scale_edges_uniformly(*mesh, {selection_field, scale_field, center_field});
break;
}
case GEO_NODE_SCALE_ELEMENTS_SINGLE_AXIS: {
scale_edges_on_axis(
*mesh, {selection_field, scale_field, center_field, axis_field}, allocator);
scale_edges_on_axis(*mesh, {selection_field, scale_field, center_field, axis_field});
break;
}
}

View File

@ -21,7 +21,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void scale_instances(GeoNodeExecParams &params, bke::Instances &instances)
{
const bke::InstancesFieldContext context{instances};
fn::FieldEvaluator evaluator{context, instances.instances_num(), &params.allocator()};
fn::FieldEvaluator evaluator{context, instances.instances_num()};
evaluator.set_selection(params.extract_input<Field<bool>>("Selection"));
evaluator.add(params.extract_input<Field<float3>>("Scale"));
evaluator.add(params.extract_input<Field<float3>>("Center"));

View File

@ -59,7 +59,6 @@ static void node_geo_exec(GeoNodeExecParams params)
GEO_NODE_DELETE_GEOMETRY_MODE_ALL,
selection,
propagation_info,
params.allocator(),
is_error);
}
else {
@ -69,7 +68,6 @@ static void node_geo_exec(GeoNodeExecParams params)
GEO_NODE_DELETE_GEOMETRY_MODE_ALL,
selection,
propagation_info,
params.allocator().local(),
is_error);
});
}

View File

@ -20,8 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void set_radius(bke::CurvesGeometry &curves,
const Field<bool> &selection_field,
const Field<float> &radius_field,
LocalAllocator &allocator)
const Field<float> &radius_field)
{
if (curves.points_num() == 0) {
return;
@ -31,7 +30,7 @@ static void set_radius(bke::CurvesGeometry &curves,
ATTR_DOMAIN_POINT);
bke::CurvesFieldContext field_context{curves, ATTR_DOMAIN_POINT};
fn::FieldEvaluator evaluator{field_context, curves.points_num(), &allocator};
fn::FieldEvaluator evaluator{field_context, curves.points_num()};
evaluator.set_selection(selection_field);
evaluator.add_with_destination(radius_field, radii.varray);
evaluator.evaluate();
@ -47,10 +46,7 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (Curves *curves_id = geometry_set.get_curves_for_write()) {
set_radius(bke::CurvesGeometry::wrap(curves_id->geometry),
selection_field,
radii_field,
params.allocator().local());
set_radius(bke::CurvesGeometry::wrap(curves_id->geometry), selection_field, radii_field);
}
});

View File

@ -16,8 +16,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void set_tilt(bke::CurvesGeometry &curves,
const Field<bool> &selection_field,
const Field<float> &tilt_field,
LocalAllocator &allocator)
const Field<float> &tilt_field)
{
if (curves.points_num() == 0) {
return;
@ -27,7 +26,7 @@ static void set_tilt(bke::CurvesGeometry &curves,
ATTR_DOMAIN_POINT);
bke::CurvesFieldContext field_context{curves, ATTR_DOMAIN_POINT};
fn::FieldEvaluator evaluator{field_context, curves.points_num(), &allocator};
fn::FieldEvaluator evaluator{field_context, curves.points_num()};
evaluator.set_selection(selection_field);
evaluator.add_with_destination(tilt_field, tilts.varray);
evaluator.evaluate();
@ -43,10 +42,7 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (Curves *curves_id = geometry_set.get_curves_for_write()) {
set_tilt(bke::CurvesGeometry::wrap(curves_id->geometry),
selection_field,
tilt_field,
params.allocator().local());
set_tilt(bke::CurvesGeometry::wrap(curves_id->geometry), selection_field, tilt_field);
}
});

View File

@ -75,8 +75,7 @@ static void node_geo_exec(GeoNodeExecParams params)
Mesh &mesh = *mesh_component.get_for_write();
bke::MeshFieldContext field_context{mesh, ATTR_DOMAIN_FACE};
fn::FieldEvaluator selection_evaluator{
field_context, mesh.totpoly, &params.allocator().local()};
fn::FieldEvaluator selection_evaluator{field_context, mesh.totpoly};
selection_evaluator.add(selection_field);
selection_evaluator.evaluate();
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);

View File

@ -20,8 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void set_radius_in_component(PointCloud &pointcloud,
const Field<bool> &selection_field,
const Field<float> &radius_field,
LocalAllocator &allocator)
const Field<float> &radius_field)
{
if (pointcloud.totpoint == 0) {
return;
@ -31,7 +30,7 @@ static void set_radius_in_component(PointCloud &pointcloud,
ATTR_DOMAIN_POINT);
bke::PointCloudFieldContext field_context{pointcloud};
fn::FieldEvaluator evaluator{field_context, pointcloud.totpoint, &allocator};
fn::FieldEvaluator evaluator{field_context, pointcloud.totpoint};
evaluator.set_selection(selection_field);
evaluator.add_with_destination(radius_field, radii.varray);
evaluator.evaluate();
@ -47,8 +46,7 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (PointCloud *pointcloud = geometry_set.get_pointcloud_for_write()) {
set_radius_in_component(
*pointcloud, selection_field, radii_field, params.allocator().local());
set_radius_in_component(*pointcloud, selection_field, radii_field);
}
});

View File

@ -147,8 +147,7 @@ static void set_computed_position_and_offset(GeometryComponent &component,
static void set_position_in_component(GeometryComponent &component,
const Field<bool> &selection_field,
const Field<float3> &position_field,
const Field<float3> &offset_field,
LocalAllocator &allocator)
const Field<float3> &offset_field)
{
eAttrDomain domain = component.type() == GEO_COMPONENT_TYPE_INSTANCES ? ATTR_DOMAIN_INSTANCE :
ATTR_DOMAIN_POINT;
@ -158,7 +157,7 @@ static void set_position_in_component(GeometryComponent &component,
return;
}
fn::FieldEvaluator evaluator{field_context, domain_size, &allocator};
fn::FieldEvaluator evaluator{field_context, domain_size};
evaluator.set_selection(selection_field);
evaluator.add(position_field);
evaluator.add(offset_field);
@ -183,11 +182,8 @@ static void node_geo_exec(GeoNodeExecParams params)
GEO_COMPONENT_TYPE_CURVE,
GEO_COMPONENT_TYPE_INSTANCES}) {
if (geometry.has(type)) {
set_position_in_component(geometry.get_component_for_write(type),
selection_field,
position_field,
offset_field,
params.allocator());
set_position_in_component(
geometry.get_component_for_write(type), selection_field, position_field, offset_field);
}
}

View File

@ -147,8 +147,7 @@ static void node_geo_exec(GeoNodeExecParams params)
if (geometry_set.has_instances()) {
GeometryComponent &component = geometry_set.get_component_for_write(
GEO_COMPONENT_TYPE_INSTANCES);
if (!bke::try_capture_field_on_geometry(
component, name, domain, field, &params.allocator())) {
if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}
@ -161,8 +160,7 @@ static void node_geo_exec(GeoNodeExecParams params)
{GEO_COMPONENT_TYPE_MESH, GEO_COMPONENT_TYPE_POINT_CLOUD, GEO_COMPONENT_TYPE_CURVE}) {
if (geometry_set.has(type)) {
GeometryComponent &component = geometry_set.get_component_for_write(type);
if (!bke::try_capture_field_on_geometry(
component, name, domain, field, &params.allocator().local())) {
if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}

View File

@ -124,16 +124,14 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
LocalAllocator &allocator = params.allocator().local();
bke::MeshFieldContext point_context{mesh, ATTR_DOMAIN_POINT};
FieldEvaluator point_evaluator(point_context, mesh.totvert, &allocator);
FieldEvaluator point_evaluator(point_context, mesh.totvert);
point_evaluator.add(vertex_crease_field);
point_evaluator.evaluate();
const VArray<float> vertex_creases = point_evaluator.get_evaluated<float>(0);
bke::MeshFieldContext edge_context{mesh, ATTR_DOMAIN_EDGE};
FieldEvaluator edge_evaluator(edge_context, mesh.totedge, &allocator);
FieldEvaluator edge_evaluator(edge_context, mesh.totedge);
edge_evaluator.add(edge_crease_field);
edge_evaluator.evaluate();
const VArray<float> edge_creases = edge_evaluator.get_evaluated<float>(0);

View File

@ -20,7 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b)
static void translate_instances(GeoNodeExecParams &params, bke::Instances &instances)
{
const bke::InstancesFieldContext context{instances};
fn::FieldEvaluator evaluator{context, instances.instances_num(), &params.allocator()};
fn::FieldEvaluator evaluator{context, instances.instances_num()};
evaluator.set_selection(params.extract_input<Field<bool>>("Selection"));
evaluator.add(params.extract_input<Field<float3>>("Translation"));
evaluator.add(params.extract_input<Field<bool>>("Local Space"));

View File

@ -78,7 +78,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const Mesh &mesh_in = *geometry_set.get_mesh_for_read();
bke::MeshFieldContext context{mesh_in, ATTR_DOMAIN_FACE};
FieldEvaluator evaluator{context, mesh_in.totpoly, &params.allocator().local()};
FieldEvaluator evaluator{context, mesh_in.totpoly};
evaluator.add(selection_field);
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_as_mask(0);

View File

@ -148,7 +148,7 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Evaluate input field on a 3D grid. */
Grid3DFieldContext context(resolution, bounds_min, bounds_max);
FieldEvaluator evaluator(context, context.points_num(), &params.allocator());
FieldEvaluator evaluator(context, context.points_num());
Array<float> densities(context.points_num());
evaluator.add_with_destination(std::move(input_field), densities.as_mutable_span());
evaluator.evaluate();

View File

@ -304,7 +304,6 @@ class LazyFunctionForUndefinedNode : public LazyFunction {
* values. If any input is a field, the outputs will also be fields.
*/
static void execute_multi_function_on_value_or_field(
LocalAllocator &allocator,
const MultiFunction &fn,
const std::shared_ptr<MultiFunction> &owned_fn,
const Span<const ValueOrFieldCPPType *> input_types,
@ -355,7 +354,7 @@ static void execute_multi_function_on_value_or_field(
else {
/* In this case, the multi-function is evaluated directly. */
MFParamsBuilder params{fn, 1};
MFContextBuilder context{&allocator};
MFContextBuilder context;
for (const int i : input_types.index_range()) {
const ValueOrFieldCPPType &type = *input_types[i];
@ -413,7 +412,7 @@ class LazyFunctionForMutedNode : public LazyFunction {
}
}
void execute_impl(lf::Params &params, const lf::Context &context) const override
void execute_impl(lf::Params &params, const lf::Context & /*context*/) const override
{
for (const int output_i : outputs_.index_range()) {
if (params.output_was_set(output_i)) {
@ -447,13 +446,8 @@ class LazyFunctionForMutedNode : public LazyFunction {
if (conversions.is_convertible(from_type->value, to_type->value)) {
const MultiFunction &multi_fn = *conversions.get_conversion_multi_function(
MFDataType::ForSingle(from_type->value), MFDataType::ForSingle(to_type->value));
execute_multi_function_on_value_or_field(*context.allocator,
multi_fn,
{},
{from_type},
{to_type},
{input_value},
{output_value});
execute_multi_function_on_value_or_field(
multi_fn, {}, {from_type}, {to_type}, {input_value}, {output_value});
}
params.output_set(output_i);
continue;
@ -486,7 +480,7 @@ class LazyFunctionForMultiFunctionConversion : public LazyFunction {
outputs_.append({"To", to.self});
}
void execute_impl(lf::Params &params, const lf::Context &context) const override
void execute_impl(lf::Params &params, const lf::Context & /*context*/) const override
{
const void *from_value = params.try_get_input_data_ptr(0);
void *to_value = params.get_output_data_ptr(0);
@ -494,7 +488,7 @@ class LazyFunctionForMultiFunctionConversion : public LazyFunction {
BLI_assert(to_value != nullptr);
execute_multi_function_on_value_or_field(
*context.allocator, fn_, {}, {&from_type_}, {&to_type_}, {from_value}, {to_value});
fn_, {}, {&from_type_}, {&to_type_}, {from_value}, {to_value});
params.output_set(0);
}
@ -527,7 +521,7 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
}
}
void execute_impl(lf::Params &params, const lf::Context &context) const override
void execute_impl(lf::Params &params, const lf::Context & /*context*/) const override
{
Vector<const void *> input_values(inputs_.size());
Vector<void *> output_values(outputs_.size());
@ -537,13 +531,8 @@ class LazyFunctionForMultiFunctionNode : public LazyFunction {
for (const int i : outputs_.index_range()) {
output_values[i] = params.get_output_data_ptr(i);
}
execute_multi_function_on_value_or_field(*context.allocator,
*fn_item_.fn,
fn_item_.owned_fn,
input_types_,
output_types_,
input_values,
output_values);
execute_multi_function_on_value_or_field(
*fn_item_.fn, fn_item_.owned_fn, input_types_, output_types_, input_values, output_values);
for (const int i : outputs_.index_range()) {
params.output_set(i);
}