diff options
author | Peter Kim <pk15950@gmail.com> | 2022-09-08 07:00:12 +0300 |
---|---|---|
committer | Peter Kim <pk15950@gmail.com> | 2022-09-08 07:00:12 +0300 |
commit | 00dcfdf916c69672210b006e62d966f1bc2fbeb7 (patch) | |
tree | 0cbb1b91fe26c750197126085b74224a795a103c /source/blender/blenlib/intern/generic_virtual_array.cc | |
parent | a39532670f6b668da7be5810fb1f844b82feeba3 (diff) | |
parent | d5934974219135102f364f57c45a8b1465e2b8d9 (diff) |
Merge branch 'master' into xr-devxr-dev
Diffstat (limited to 'source/blender/blenlib/intern/generic_virtual_array.cc')
-rw-r--r-- | source/blender/blenlib/intern/generic_virtual_array.cc | 264 |
1 files changed, 161 insertions, 103 deletions
diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index a6fbf4bff5b..f66b1e14fc6 100644 --- a/source/blender/blenlib/intern/generic_virtual_array.cc +++ b/source/blender/blenlib/intern/generic_virtual_array.cc @@ -46,25 +46,9 @@ void GVArrayImpl::get(const int64_t index, void *r_value) const this->get_to_uninitialized(index, r_value); } -bool GVArrayImpl::is_span() const +CommonVArrayInfo GVArrayImpl::common_info() const { - return false; -} - -GSpan GVArrayImpl::get_internal_span() const -{ - BLI_assert(false); - return GSpan(*type_); -} - -bool GVArrayImpl::is_single() const -{ - return false; -} - -void GVArrayImpl::get_internal_single(void *UNUSED(r_value)) const -{ - BLI_assert(false); + return {}; } bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const @@ -72,13 +56,6 @@ bool GVArrayImpl::try_assign_VArray(void *UNUSED(varray)) const return false; } -bool GVArrayImpl::may_have_ownership() const -{ - /* Use true as default to avoid accidentally creating subclasses that have this set to false but - * actually own data. Subclasses should set the to false instead. */ - return true; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -101,9 +78,9 @@ void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value) void GVMutableArrayImpl::set_all(const void *src) { - if (this->is_span()) { - const GSpan span = this->get_internal_span(); - type_->copy_assign_n(src, const_cast<void *>(span.data()), size_); + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + type_->copy_assign_n(src, const_cast<void *>(info.data), size_); } else { for (int64_t i : IndexRange(size_)) { @@ -114,9 +91,9 @@ void GVMutableArrayImpl::set_all(const void *src) void GVMutableArray::fill(const void *value) { - if (this->is_span()) { - const GSpan span = this->get_internal_span(); - this->type().fill_assign_n(value, const_cast<void *>(span.data()), this->size()); + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + this->type().fill_assign_n(value, const_cast<void *>(info.data), this->size()); } else { for (int64_t i : IndexRange(this->size())) { @@ -161,14 +138,9 @@ void GVArrayImpl_For_GSpan::set_by_relocate(const int64_t index, void *value) type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index)); } -bool GVArrayImpl_For_GSpan::is_span() const -{ - return true; -} - -GSpan GVArrayImpl_For_GSpan::get_internal_span() const +CommonVArrayInfo GVArrayImpl_For_GSpan::common_info() const { - return GSpan(*type_, data_, size_); + return CommonVArrayInfo{CommonVArrayInfo::Type::Span, true, data_}; } void GVArrayImpl_For_GSpan::materialize(const IndexMask mask, void *dst) const @@ -210,22 +182,9 @@ void GVArrayImpl_For_SingleValueRef::get_to_uninitialized(const int64_t UNUSED(i type_->copy_construct(value_, r_value); } -bool GVArrayImpl_For_SingleValueRef::is_span() const -{ - return size_ == 1; -} -GSpan GVArrayImpl_For_SingleValueRef::get_internal_span() const -{ - return GSpan{*type_, value_, 1}; -} - -bool GVArrayImpl_For_SingleValueRef::is_single() const +CommonVArrayInfo GVArrayImpl_For_SingleValueRef::common_info() const { - return true; -} -void GVArrayImpl_For_SingleValueRef::get_internal_single(void *r_value) const -{ - type_->copy_assign(value_, r_value); + return CommonVArrayInfo{CommonVArrayInfo::Type::Single, true, value_}; } void GVArrayImpl_For_SingleValueRef::materialize(const IndexMask mask, void *dst) const @@ -311,32 +270,36 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public this->copy_value_to(r_value); } - bool is_single() const override - { - return true; - } - void get_internal_single(void *r_value) const override + void copy_value_to(void *dst) const { - this->copy_value_to(r_value); + memcpy(dst, &buffer_, type_->size()); } - void copy_value_to(void *dst) const + CommonVArrayInfo common_info() const override { - memcpy(dst, &buffer_, type_->size()); + return CommonVArrayInfo{CommonVArrayInfo::Type::Single, true, &buffer_}; } }; /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVArray_GSpan +/** \name #GVArraySpan * \{ */ -GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) +GVArraySpan::GVArraySpan() = default; + +GVArraySpan::GVArraySpan(GVArray varray) + : GSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } + size_ = varray_.size(); - if (varray_.is_span()) { - data_ = varray_.get_internal_span().data(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = info.data; } else { owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); @@ -345,7 +308,27 @@ GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std } } -GVArray_GSpan::~GVArray_GSpan() +GVArraySpan::GVArraySpan(GVArraySpan &&other) + : GSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_) +{ + if (!varray_) { + return; + } + + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = info.data; + } + else { + data_ = owned_data_; + } + other.owned_data_ = nullptr; + other.data_ = nullptr; + other.size_ = 0; +} + +GVArraySpan::~GVArraySpan() { if (owned_data_ != nullptr) { type_->destruct_n(owned_data_, size_); @@ -353,18 +336,34 @@ GVArray_GSpan::~GVArray_GSpan() } } +GVArraySpan &GVArraySpan::operator=(GVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GVArraySpan(std::move(other)); + return *this; +} + /** \} */ /* -------------------------------------------------------------------- */ -/** \name #GVMutableArray_GSpan +/** \name #GMutableVArraySpan * \{ */ -GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool copy_values_to_span) - : GMutableSpan(varray.type()), varray_(std::move(varray)) +GMutableVArraySpan::GMutableVArraySpan() = default; + +GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_values_to_span) + : GMutableSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray)) { + if (!varray_) { + return; + } size_ = varray_.size(); - if (varray_.is_span()) { - data_ = varray_.get_internal_span().data(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = const_cast<void *>(info.data); } else { owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__); @@ -378,11 +377,35 @@ GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool cop } } -GVMutableArray_GSpan::~GVMutableArray_GSpan() +GMutableVArraySpan::GMutableVArraySpan(GMutableVArraySpan &&other) + : GMutableSpan(other.type_ptr()), + varray_(std::move(other.varray_)), + owned_data_(other.owned_data_), + show_not_saved_warning_(other.show_not_saved_warning_) { - if (show_not_saved_warning_) { - if (!save_has_been_called_) { - std::cout << "Warning: Call `apply()` to make sure that changes persist in all cases.\n"; + if (!varray_) { + return; + } + size_ = varray_.size(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + data_ = const_cast<void *>(info.data); + } + else { + data_ = owned_data_; + } + other.owned_data_ = nullptr; + other.data_ = nullptr; + other.size_ = 0; +} + +GMutableVArraySpan::~GMutableVArraySpan() +{ + if (varray_) { + if (show_not_saved_warning_) { + if (!save_has_been_called_) { + std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n"; + } } } if (owned_data_ != nullptr) { @@ -391,7 +414,17 @@ GVMutableArray_GSpan::~GVMutableArray_GSpan() } } -void GVMutableArray_GSpan::save() +GMutableVArraySpan &GMutableVArraySpan::operator=(GMutableVArraySpan &&other) +{ + if (this == &other) { + return *this; + } + std::destroy_at(this); + new (this) GMutableVArraySpan(std::move(other)); + return *this; +} + +void GMutableVArraySpan::save() { save_has_been_called_ = true; if (data_ != owned_data_) { @@ -400,11 +433,16 @@ void GVMutableArray_GSpan::save() varray_.set_all(owned_data_); } -void GVMutableArray_GSpan::disable_not_applied_warning() +void GMutableVArraySpan::disable_not_applied_warning() { show_not_saved_warning_ = false; } +const GVMutableArray &GMutableVArraySpan::varray() const +{ + return varray_; +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -437,22 +475,24 @@ class GVArrayImpl_For_SlicedGVArray : public GVArrayImpl { varray_.get_to_uninitialized(index + offset_, r_value); } - bool is_span() const override - { - return varray_.is_span(); - } - GSpan get_internal_span() const override - { - return varray_.get_internal_span().slice(slice_); - } - - bool is_single() const override - { - return varray_.is_single(); - } - void get_internal_single(void *r_value) const override + CommonVArrayInfo common_info() const override { - varray_.get_internal_single(r_value); + const CommonVArrayInfo internal_info = varray_.common_info(); + switch (internal_info.type) { + case CommonVArrayInfo::Type::Any: { + return {}; + } + case CommonVArrayInfo::Type::Span: { + return CommonVArrayInfo(CommonVArrayInfo::Type::Span, + internal_info.may_have_ownership, + POINTER_OFFSET(internal_info.data, type_->size() * offset_)); + } + case CommonVArrayInfo::Type::Single: { + return internal_info; + } + } + BLI_assert_unreachable(); + return {}; } void materialize_compressed_to_uninitialized(const IndexMask mask, void *dst) const override @@ -535,11 +575,6 @@ void GVArrayCommon::materialize_compressed_to_uninitialized(IndexMask mask, void impl_->materialize_compressed_to_uninitialized(mask, dst); } -bool GVArrayCommon::may_have_ownership() const -{ - return impl_->may_have_ownership(); -} - void GVArrayCommon::copy_from(const GVArrayCommon &other) { if (this == &other) { @@ -562,24 +597,28 @@ void GVArrayCommon::move_from(GVArrayCommon &&other) noexcept bool GVArrayCommon::is_span() const { - return impl_->is_span(); + const CommonVArrayInfo info = impl_->common_info(); + return info.type == CommonVArrayInfo::Type::Span; } GSpan GVArrayCommon::get_internal_span() const { BLI_assert(this->is_span()); - return impl_->get_internal_span(); + const CommonVArrayInfo info = impl_->common_info(); + return GSpan(this->type(), info.data, this->size()); } bool GVArrayCommon::is_single() const { - return impl_->is_single(); + const CommonVArrayInfo info = impl_->common_info(); + return info.type == CommonVArrayInfo::Type::Single; } void GVArrayCommon::get_internal_single(void *r_value) const { BLI_assert(this->is_single()); - impl_->get_internal_single(r_value); + const CommonVArrayInfo info = impl_->common_info(); + this->type().copy_assign(info.data, r_value); } void GVArrayCommon::get_internal_single_to_uninitialized(void *r_value) const @@ -675,6 +714,15 @@ GVArray GVArray::ForEmpty(const CPPType &type) GVArray GVArray::slice(IndexRange slice) const { + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + return GVArray::ForSingle(this->type(), slice.size(), info.data); + } + /* Need to check for ownership, because otherwise the referenced data can be destructed when + * #this is destructed. */ + if (info.type == CommonVArrayInfo::Type::Span && !info.may_have_ownership) { + return GVArray::ForSpan(GSpan(this->type(), info.data, this->size()).slice(slice)); + } return GVArray::For<GVArrayImpl_For_SlicedGVArray>(*this, slice); } @@ -752,10 +800,20 @@ void GVMutableArray::set_all(const void *src) GMutableSpan GVMutableArray::get_internal_span() const { BLI_assert(this->is_span()); - const GSpan span = impl_->get_internal_span(); - return GMutableSpan(span.type(), const_cast<void *>(span.data()), span.size()); + const CommonVArrayInfo info = impl_->common_info(); + return GMutableSpan(this->type(), const_cast<void *>(info.data), this->size()); } /** \} */ +CommonVArrayInfo GVArrayImpl_For_GSpan_final::common_info() const +{ + return CommonVArrayInfo(CommonVArrayInfo::Type::Span, false, data_); +} + +CommonVArrayInfo GVArrayImpl_For_SingleValueRef_final::common_info() const +{ + return CommonVArrayInfo(CommonVArrayInfo::Type::Single, false, value_); +} + } // namespace blender |