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.
6 changed files with 19 additions and 9 deletions
Showing only changes of commit e566e6d4cf - Show all commits

View File

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

View File

@ -408,7 +408,8 @@ 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)
const fn::GField &field,
LocalAllocator *allocator)
{
MutableAttributeAccessor attributes = *component.attributes_for_write();
const int domain_size = attributes.domain_size(domain);
@ -428,7 +429,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};
fn::FieldEvaluator evaluator{field_context, &mask, allocator};
evaluator.add_with_destination(validator.validate_field_if_necessary(field),
GMutableSpan{type, buffer, domain_size});
evaluator.evaluate();

View File

@ -177,7 +177,7 @@ inline void *LocalAllocator::allocate(LocalAllocatorPool &pool)
BLI_assert(this->is_local());
#ifdef BLI_LOCAL_ALLOCATOR_USE_GUARDED
return MEM_mallocN_aligned(size, alignment, __func__);
return MEM_mallocN_aligned(pool.element_size, pool.alignment, __func__);
#endif
void *buffer;
@ -205,7 +205,6 @@ inline void LocalAllocator::deallocate(const void *buffer, LocalAllocatorPool &p
#ifdef BLI_LOCAL_ALLOCATOR_USE_GUARDED
MEM_freeN(const_cast<void *>(buffer));
UNUSED_VARS_NDEBUG(size, alignment);
return;
#endif

View File

@ -257,6 +257,11 @@ 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

@ -181,7 +181,8 @@ 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);
bke::try_capture_field_on_geometry(
component, *attribute_id, domain, field, &params.allocator());
}
}
else {
@ -192,7 +193,8 @@ 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);
bke::try_capture_field_on_geometry(
component, *attribute_id, domain, field, &params.allocator());
}
}
});

View File

@ -147,7 +147,8 @@ 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)) {
if (!bke::try_capture_field_on_geometry(
component, name, domain, field, &params.allocator())) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}
@ -160,7 +161,8 @@ 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)) {
if (!bke::try_capture_field_on_geometry(
component, name, domain, field, &params.allocator())) {
if (component.attribute_domain_size(domain) != 0) {
failure.store(true);
}