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.
7 changed files with 27 additions and 27 deletions
Showing only changes of commit 60612b84dc - Show all commits

View File

@ -2297,7 +2297,7 @@ static bool customdata_merge_internal(const CustomData *source,
if (src_layer.anonymous_id != nullptr) {
new_layer->anonymous_id = src_layer.anonymous_id;
new_layer->anonymous_id->cow().user_add();
new_layer->anonymous_id->cow().add_user();
}
}
@ -2401,7 +2401,7 @@ static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totel
const eCustomDataType type = eCustomDataType(layer.type);
const void *old_data = layer.data;
layer.data = copy_layer_data(type, old_data, totelem);
layer.cow->user_remove_and_delete_if_last();
layer.cow->remove_user_and_delete_if_last();
layer.cow = make_cow_for_array(type, layer.data, totelem);
}
}
@ -2425,7 +2425,7 @@ void CustomData_realloc(CustomData *data, const int old_size, const int new_size
}
/* Remove ownership of old array */
if (layer->cow) {
layer->cow->user_remove_and_delete_if_last();
layer->cow->remove_user_and_delete_if_last();
layer->cow = nullptr;
}
/* Take ownership of new array. */
@ -2473,7 +2473,7 @@ void CustomData_copy_without_data(const struct CustomData *source,
static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem)
{
if (layer->anonymous_id != nullptr) {
layer->anonymous_id->cow().user_remove_and_delete_if_last();
layer->anonymous_id->cow().remove_user_and_delete_if_last();
layer->anonymous_id = nullptr;
}
const eCustomDataType type = eCustomDataType(layer->type);
@ -2483,7 +2483,7 @@ static void customData_free_layer__internal(CustomDataLayer *layer, const int to
}
}
else {
layer->cow->user_remove_and_delete_if_last();
layer->cow->remove_user_and_delete_if_last();
}
}
@ -2866,7 +2866,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
new_layer.data = layer_data_to_assign;
new_layer.cow = cow_to_assign;
if (new_layer.cow) {
new_layer.cow->user_add();
new_layer.cow->add_user();
}
}
break;
@ -2998,7 +2998,7 @@ void *CustomData_add_layer_anonymous(CustomData *data,
return nullptr;
}
anonymous_id->cow().user_add();
anonymous_id->cow().add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
@ -3019,7 +3019,7 @@ const void *CustomData_add_layer_anonymous_with_existing_data(
if (layer == nullptr) {
return nullptr;
}
anonymous_id->cow().user_add();
anonymous_id->cow().add_user();
layer->anonymous_id = anonymous_id;
return layer->data;
}
@ -5257,7 +5257,7 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, const int
if (CustomData_verify_versions(data, i)) {
if (BLO_read_is_cow_data(reader, layer->data)) {
BLI_assert(layer->cow != nullptr);
layer->cow->user_add();
layer->cow->add_user();
continue;
}
BLO_read_data_address(reader, &layer->data);

View File

@ -188,7 +188,7 @@ void GeometrySet::remove_geometry_during_modify()
void GeometrySet::add(const GeometryComponent &component)
{
BLI_assert(!components_[component.type()]);
component.cow().user_add();
component.cow().add_user();
components_[component.type()] = const_cast<GeometryComponent *>(&component);
}

View File

@ -48,12 +48,12 @@ struct bCopyOnWrite : blender::NonCopyable, blender::NonMovable {
return !this->is_shared();
}
void user_add() const
void add_user() const
{
users_.fetch_add(1, std::memory_order_relaxed);
}
void user_remove_and_delete_if_last() const
void remove_user_and_delete_if_last() const
{
const int old_user_count = users_.fetch_sub(1, std::memory_order_relaxed);
BLI_assert(old_user_count >= 1);
@ -82,7 +82,7 @@ template<typename T> class COWUser {
COWUser(const COWUser &other) : data_(other.data_)
{
this->user_add(data_);
this->add_user(data_);
}
COWUser(COWUser &&other) : data_(other.data_)
@ -92,7 +92,7 @@ template<typename T> class COWUser {
~COWUser()
{
this->user_remove_and_delete_if_last(data_);
this->remove_user_and_delete_if_last(data_);
}
COWUser &operator=(const COWUser &other)
@ -101,9 +101,9 @@ template<typename T> class COWUser {
return *this;
}
this->user_remove_and_delete_if_last(data_);
this->remove_user_and_delete_if_last(data_);
data_ = other.data_;
this->user_add(data_);
this->add_user(data_);
return *this;
}
@ -113,7 +113,7 @@ template<typename T> class COWUser {
return *this;
}
this->user_remove_and_delete_if_last(data_);
this->remove_user_and_delete_if_last(data_);
data_ = other.data_;
other.data_ = nullptr;
return *this;
@ -167,7 +167,7 @@ template<typename T> class COWUser {
void reset()
{
this->user_remove_and_delete_if_last(data_);
this->remove_user_and_delete_if_last(data_);
data_ = nullptr;
}
@ -187,17 +187,17 @@ template<typename T> class COWUser {
}
private:
static void user_add(T *data)
static void add_user(T *data)
{
if (data != nullptr) {
data->cow().user_add();
data->cow().add_user();
}
}
static void user_remove_and_delete_if_last(T *data)
static void remove_user_and_delete_if_last(T *data)
{
if (data != nullptr) {
data->cow().user_remove_and_delete_if_last();
data->cow().remove_user_and_delete_if_last();
}
}
};

View File

@ -58,7 +58,7 @@ void BLO_memfile_free(MemFile *memfile)
MemFileCowStorage::~MemFileCowStorage()
{
for (auto item : this->map.items()) {
item.value->user_remove_and_delete_if_last();
item.value->remove_user_and_delete_if_last();
}
}

View File

@ -1698,7 +1698,7 @@ void BLO_write_cow(BlendWriter *writer, const void *data_ptr, const bCopyOnWrite
memfile.cow_storage = MEM_new<MemFileCowStorage>(__func__);
}
if (memfile.cow_storage->map.add(data_ptr, cow)) {
cow->user_add();
cow->add_user();
}
}

View File

@ -82,7 +82,7 @@ static void add_new_edges(Mesh &mesh,
}
else {
anonymous_ids.append(&id.anonymous_id());
id.anonymous_id().cow().user_add();
id.anonymous_id().cow().add_user();
}
}
Vector<bke::AttributeIDRef> local_edge_ids;

View File

@ -598,7 +598,7 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
case GEO_COMPONENT_TYPE_VOLUME: {
const VolumeComponent *volume_component = static_cast<const VolumeComponent *>(component);
if (!gather_info.r_tasks.first_volume) {
volume_component->cow().user_add();
volume_component->cow().add_user();
gather_info.r_tasks.first_volume = const_cast<VolumeComponent *>(volume_component);
}
break;
@ -607,7 +607,7 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
const GeometryComponentEditData *edit_component =
static_cast<const GeometryComponentEditData *>(component);
if (!gather_info.r_tasks.first_edit_data) {
edit_component->cow().user_add();
edit_component->cow().add_user();
gather_info.r_tasks.first_edit_data = edit_component;
}
break;