WIP: use generic copy-on-write system to avoid unnecessary data copies #104470

Closed
Jacques Lucke wants to merge 50 commits from JacquesLucke/blender:temp-copy-on-write-customdata into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 48 additions and 23 deletions
Showing only changes of commit c4c9a43072 - Show all commits

View File

@ -812,7 +812,6 @@ class CustomDataAttributes {
std::optional<blender::GMutableSpan> get_for_write(const AttributeIDRef &attribute_id);
bool create(const AttributeIDRef &attribute_id, eCustomDataType data_type);
bool create_by_move(const AttributeIDRef &attribute_id, eCustomDataType data_type, void *buffer);
bool remove(const AttributeIDRef &attribute_id);
bool foreach_attribute(const AttributeForeachCallback callback, eAttrDomain domain) const;

View File

@ -277,6 +277,13 @@ void *CustomData_add_layer_anonymous(struct CustomData *data,
CustomDataLayerSource *layer_source,
int totelem,
const AnonymousAttributeIDHandle *anonymous_id);
const void *CustomData_add_layer_anonymous_with_existing_data(
struct CustomData *data,
int type,
const AnonymousAttributeIDHandle *anonymous_id,
int totelem,
void *layer_data,
const struct bCopyOnWrite *cow);
/**
* Frees the active or first data layer with the give type.

View File

@ -219,7 +219,6 @@ static bool add_builtin_type_custom_data_layer_from_init(CustomData &custom_data
static void *add_generic_custom_data_layer(CustomData &custom_data,
const eCustomDataType data_type,
const eCDAllocType alloctype,
CustomDataLayerSource *layer_source,
const int domain_num,
const AttributeIDRef &attribute_id)
{
@ -227,11 +226,30 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, layer_source, domain_num, attribute_name_c);
&custom_data, data_type, alloctype, nullptr, domain_num, attribute_name_c);
}
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous(
&custom_data, data_type, alloctype, layer_source, domain_num, &anonymous_id);
&custom_data, data_type, alloctype, nullptr, domain_num, &anonymous_id);
}
static const void *add_generic_custom_data_layer_with_existing_data(
CustomData &custom_data,
const eCustomDataType data_type,
const AttributeIDRef &attribute_id,
const int domain_size,
void *layer_data,
const bCopyOnWrite *cow)
{
if (attribute_id.is_anonymous()) {
const AnonymousAttributeID &anonymous_id = attribute_id.anonymous_id();
return CustomData_add_layer_anonymous_with_existing_data(
&custom_data, data_type, &anonymous_id, domain_size, layer_data, cow);
}
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named_with_existing_data(
&custom_data, data_type, attribute_name_c, domain_size, layer_data, cow);
}
static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attribute_id,
@ -244,17 +262,17 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
switch (initializer.type) {
case AttributeInit::Type::Construct: {
add_generic_custom_data_layer(
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
break;
}
case AttributeInit::Type::DefaultValue: {
add_generic_custom_data_layer(
custom_data, data_type, CD_SET_DEFAULT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_SET_DEFAULT, domain_num, attribute_id);
break;
}
case AttributeInit::Type::VArray: {
void *data = add_generic_custom_data_layer(
custom_data, data_type, CD_CONSTRUCT, nullptr, domain_num, attribute_id);
custom_data, data_type, CD_CONSTRUCT, domain_num, attribute_id);
if (data != nullptr) {
const GVArray &varray = static_cast<const AttributeInitVArray &>(initializer).varray;
varray.materialize_to_uninitialized(varray.index_range(), data);
@ -262,10 +280,9 @@ static bool add_custom_data_layer_from_attribute_init(const AttributeIDRef &attr
break;
}
case AttributeInit::Type::MoveArray: {
CustomDataLayerSource layer_source{};
layer_source.data = static_cast<const AttributeInitMoveArray &>(initializer).data;
add_generic_custom_data_layer(
custom_data, data_type, CD_ASSIGN, &layer_source, domain_num, attribute_id);
void *data = static_cast<const AttributeInitMoveArray &>(initializer).data;
add_generic_custom_data_layer_with_existing_data(
custom_data, data_type, attribute_id, domain_num, data, nullptr);
break;
}
}
@ -637,18 +654,7 @@ bool CustomDataAttributes::create(const AttributeIDRef &attribute_id,
const eCustomDataType data_type)
{
void *result = add_generic_custom_data_layer(
data, data_type, CD_SET_DEFAULT, nullptr, size_, attribute_id);
return result != nullptr;
}
bool CustomDataAttributes::create_by_move(const AttributeIDRef &attribute_id,
const eCustomDataType data_type,
void *buffer)
{
CustomDataLayerSource layer_source{};
layer_source.data = buffer;
void *result = add_generic_custom_data_layer(
data, data_type, CD_ASSIGN, &layer_source, size_, attribute_id);
data, data_type, CD_SET_DEFAULT, size_, attribute_id);
return result != nullptr;
}

View File

@ -2928,6 +2928,19 @@ void *CustomData_add_layer_anonymous(CustomData *data,
return layer->data;
}
const void *CustomData_add_layer_anonymous_with_existing_data(
CustomData *data,
const int type,
const AnonymousAttributeIDHandle *anonymous_id,
const int totelem,
void *layer_data,
const bCopyOnWrite *cow)
{
CustomDataLayerSource layer_source{layer_data, cow};
return CustomData_add_layer_anonymous(
data, type, CD_ASSIGN, &layer_source, totelem, anonymous_id);
}
bool CustomData_free_layer(CustomData *data, const int type, const int totelem, const int index)
{
const int index_first = CustomData_get_layer_index(data, type);