WIP: Functions: new local allocator for better memory reuse and performance #104630
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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, ¶ms.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, ¶ms.allocator().local());
|
||||
bke::try_capture_field_on_geometry(component, *attribute_id, domain, field);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ¶ms,
|
||||
LocalAllocator &allocator)
|
||||
const GeoNodeExecParams ¶ms)
|
||||
{
|
||||
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});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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, ¶ms.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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
"radius", ATTR_DOMAIN_POINT);
|
||||
|
||||
PointsFieldContext context{count};
|
||||
fn::FieldEvaluator evaluator{context, count, ¶ms.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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
static void scale_instances(GeoNodeExecParams ¶ms, bke::Instances &instances)
|
||||
{
|
||||
const bke::InstancesFieldContext context{instances};
|
||||
fn::FieldEvaluator evaluator{context, instances.instances_num(), ¶ms.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"));
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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, ¶ms.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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ¶ms.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, ¶ms.allocator().local())) {
|
||||
if (!bke::try_capture_field_on_geometry(component, name, domain, field)) {
|
||||
if (component.attribute_domain_size(domain) != 0) {
|
||||
failure.store(true);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -20,7 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
static void translate_instances(GeoNodeExecParams ¶ms, bke::Instances &instances)
|
||||
{
|
||||
const bke::InstancesFieldContext context{instances};
|
||||
fn::FieldEvaluator evaluator{context, instances.instances_num(), ¶ms.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"));
|
||||
|
|
|
@ -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, ¶ms.allocator().local()};
|
||||
FieldEvaluator evaluator{context, mesh_in.totpoly};
|
||||
evaluator.add(selection_field);
|
||||
evaluator.evaluate();
|
||||
const IndexMask selection = evaluator.get_evaluated_as_mask(0);
|
||||
|
|
|
@ -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(), ¶ms.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();
|
||||
|
|
|
@ -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 ¶ms, const lf::Context &context) const override
|
||||
void execute_impl(lf::Params ¶ms, 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 ¶ms, const lf::Context &context) const override
|
||||
void execute_impl(lf::Params ¶ms, 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 ¶ms, const lf::Context &context) const override
|
||||
void execute_impl(lf::Params ¶ms, 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue