diff options
Diffstat (limited to 'source/blender/functions/intern/attributes_ref.cc')
-rw-r--r-- | source/blender/functions/intern/attributes_ref.cc | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/source/blender/functions/intern/attributes_ref.cc b/source/blender/functions/intern/attributes_ref.cc new file mode 100644 index 00000000000..9fbf492f934 --- /dev/null +++ b/source/blender/functions/intern/attributes_ref.cc @@ -0,0 +1,164 @@ +#include "FN_attributes_ref.h" + +namespace FN { + +AttributesInfoBuilder::~AttributesInfoBuilder() +{ + for (uint i = 0; i < m_defaults.size(); i++) { + m_types[i]->destruct(m_defaults[i]); + } +} + +void AttributesInfoBuilder::add(const AttributesInfoBuilder &other) +{ + for (uint i = 0; i < other.size(); i++) { + this->add(other.m_names[i], *other.m_types[i], other.m_defaults[i]); + } +} + +void AttributesInfoBuilder::add(const AttributesInfo &other) +{ + for (uint i = 0; i < other.size(); i++) { + this->add(other.name_of(i), other.type_of(i), other.default_of(i)); + } +} + +AttributesInfo::AttributesInfo(const AttributesInfoBuilder &builder) +{ + for (uint i = 0; i < builder.size(); i++) { + StringRef name = builder.names()[i]; + const CPPType &type = *builder.types()[i]; + const void *default_value = builder.defaults()[i]; + + m_index_by_name.add_new(name, i); + m_name_by_index.append(name); + m_type_by_index.append(&type); + + void *dst = m_allocator.allocate(type.size(), type.alignment()); + type.copy_to_uninitialized(default_value, dst); + m_defaults.append(dst); + } +} + +AttributesInfo::~AttributesInfo() +{ + for (uint i = 0; i < m_defaults.size(); i++) { + m_type_by_index[i]->destruct(m_defaults[i]); + } +} + +void MutableAttributesRef::destruct_and_reorder(IndexMask index_mask) +{ +#ifdef DEBUG + BLI_assert(index_mask.size() <= m_range.size()); + BLI_assert(index_mask.size() == 0 || index_mask.last() < m_range.size()); + for (uint i = 1; i < index_mask.size(); i++) { + BLI_assert(index_mask[i - 1] < index_mask[i]); + } +#endif + + for (uint attribute_index : m_info->indices()) { + GenericMutableArrayRef array = this->get(attribute_index); + const CPPType &type = m_info->type_of(attribute_index); + + array.destruct_indices(index_mask); + + for (uint i : index_mask.index_range()) { + uint last_index = m_range.size() - 1 - i; + uint index_to_remove = index_mask[index_mask.size() - 1 - i]; + if (index_to_remove == last_index) { + /* Do nothing. It has been destructed before. */ + } + else { + /* Relocate last undestructed value. */ + type.relocate_to_uninitialized(array[last_index], array[index_to_remove]); + } + } + } +} + +void MutableAttributesRef::RelocateUninitialized(MutableAttributesRef from, + MutableAttributesRef to) +{ + BLI::assert_same_size(from, to); + BLI_assert(&from.info() == &to.info()); + + for (uint attribute_index : from.info().indices()) { + GenericMutableArrayRef from_array = from.get(attribute_index); + GenericMutableArrayRef to_array = to.get(attribute_index); + + GenericMutableArrayRef::RelocateUninitialized(from_array, to_array); + } +} + +AttributesRefGroup::AttributesRefGroup(const AttributesInfo &info, + Vector<ArrayRef<void *>> buffers, + Vector<IndexRange> ranges) + : m_info(&info), m_buffers(std::move(buffers)), m_ranges(std::move(ranges)) +{ + m_total_size = 0; + for (IndexRange range : m_ranges) { + m_total_size += range.size(); + } +} + +static Array<int> map_attribute_indices(const AttributesInfo &from_info, + const AttributesInfo &to_info) +{ + Array<int> mapping = Array<int>(from_info.size()); + + for (uint from_index : from_info.indices()) { + StringRef name = from_info.name_of(from_index); + const CPPType &type = from_info.type_of(from_index); + + int to_index = to_info.try_index_of(name, type); + mapping[from_index] = to_index; + } + + return mapping; +} + +AttributesInfoDiff::AttributesInfoDiff(const AttributesInfo &old_info, + const AttributesInfo &new_info) + : m_old_info(&old_info), m_new_info(&new_info) +{ + m_old_to_new_mapping = map_attribute_indices(old_info, new_info); + m_new_to_old_mapping = map_attribute_indices(new_info, old_info); +} + +void AttributesInfoDiff::update(uint capacity, + uint used_size, + ArrayRef<void *> old_buffers, + MutableArrayRef<void *> new_buffers) const +{ + BLI::assert_same_size(old_buffers, *m_old_info); + BLI::assert_same_size(new_buffers, *m_new_info); + + for (uint new_index : m_new_info->indices()) { + int old_index = m_new_to_old_mapping[new_index]; + const CPPType &type = m_new_info->type_of(new_index); + + if (old_index == -1) { + void *new_buffer = MEM_mallocN_aligned(capacity * type.size(), type.alignment(), __func__); + + GenericMutableArrayRef{type, new_buffer, used_size}.fill__uninitialized( + m_new_info->default_of(new_index)); + + new_buffers[new_index] = new_buffer; + } + else { + new_buffers[new_index] = old_buffers[old_index]; + } + }; + + for (uint old_index : m_old_info->indices()) { + int new_index = m_old_to_new_mapping[old_index]; + void *old_buffer = old_buffers[old_index]; + + if (new_index == -1 && old_buffer != nullptr) { + MEM_freeN(old_buffer); + } + } +} + +} // namespace FN |