diff options
author | Jacques Lucke <jacques@blender.org> | 2022-06-25 18:28:49 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2022-06-25 18:28:49 +0300 |
commit | 2a8afc142f72785a5ef27f5d8cc2a7d21799be4b (patch) | |
tree | 53329127801e6d8315fbd40d99e9ce4f92615b43 | |
parent | 9a0a4b0c0d452d8d4e7c1cfe211b140c58179c7f (diff) |
BLI: improve check for common virtual array implementations
This reduces the amount of code, and improves performance a bit by
doing more with less virtual method calls.
Differential Revision: https://developer.blender.org/D15293
-rw-r--r-- | source/blender/blenlib/BLI_generic_virtual_array.hh | 210 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_virtual_array.hh | 221 | ||||
-rw-r--r-- | source/blender/blenlib/intern/generic_virtual_array.cc | 150 |
3 files changed, 209 insertions, 372 deletions
diff --git a/source/blender/blenlib/BLI_generic_virtual_array.hh b/source/blender/blenlib/BLI_generic_virtual_array.hh index 985d914f4a4..b4bd337805f 100644 --- a/source/blender/blenlib/BLI_generic_virtual_array.hh +++ b/source/blender/blenlib/BLI_generic_virtual_array.hh @@ -42,11 +42,7 @@ class GVArrayImpl { virtual void get(int64_t index, void *r_value) const; virtual void get_to_uninitialized(int64_t index, void *r_value) const = 0; - virtual bool is_span() const; - virtual GSpan get_internal_span() const; - - virtual bool is_single() const; - virtual void get_internal_single(void *UNUSED(r_value)) const; + virtual CommonVArrayInfo common_info() const; virtual void materialize(const IndexMask mask, void *dst) const; virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const; @@ -55,7 +51,6 @@ class GVArrayImpl { virtual void materialize_compressed_to_uninitialized(IndexMask mask, void *dst) const; virtual bool try_assign_VArray(void *varray) const; - virtual bool may_have_ownership() const; }; /* A generic version of #VMutableArrayImpl. */ @@ -141,6 +136,8 @@ class GVArrayCommon { void materialize_compressed(IndexMask mask, void *dst) const; void materialize_compressed_to_uninitialized(IndexMask mask, void *dst) const; + CommonVArrayInfo common_info() const; + /** * Returns true when the virtual array is stored as a span internally. */ @@ -275,7 +272,7 @@ class GVArray_GSpan : public GSpan { }; /* A generic version of VMutableArray_Span. */ -class GVMutableArray_GSpan : public GMutableSpan { +class GVMutableArray_GSpan : public GMutableSpan, NonCopyable, NonMovable { private: GVMutableArray varray_; void *owned_data_ = nullptr; @@ -318,26 +315,6 @@ template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl { new (r_value) T(varray_[index]); } - bool is_span() const override - { - return varray_.is_span(); - } - - GSpan get_internal_span() const override - { - return GSpan(varray_.get_internal_span()); - } - - bool is_single() const override - { - return varray_.is_single(); - } - - void get_internal_single(void *r_value) const override - { - *(T *)r_value = varray_.get_internal_single(); - } - void materialize(const IndexMask mask, void *dst) const override { varray_.materialize(mask, MutableSpan((T *)dst, mask.min_array_size())); @@ -364,9 +341,9 @@ template<typename T> class GVArrayImpl_For_VArray : public GVArrayImpl { return true; } - bool may_have_ownership() const override + CommonVArrayInfo common_info() const override { - return varray_.may_have_ownership(); + return varray_.common_info(); } }; @@ -390,26 +367,9 @@ template<typename T> class VArrayImpl_For_GVArray : public VArrayImpl<T> { return value; } - bool is_span() const override - { - return varray_.is_span(); - } - - Span<T> get_internal_span() const override + CommonVArrayInfo common_info() const override { - return varray_.get_internal_span().template typed<T>(); - } - - bool is_single() const override - { - return varray_.is_single(); - } - - T get_internal_single() const override - { - T value; - varray_.get_internal_single(&value); - return value; + return varray_.common_info(); } bool try_assign_GVArray(GVArray &varray) const override @@ -418,11 +378,6 @@ template<typename T> class VArrayImpl_For_GVArray : public VArrayImpl<T> { return true; } - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } - void materialize(IndexMask mask, MutableSpan<T> r_span) const override { varray_.materialize(mask, r_span.data()); @@ -467,25 +422,9 @@ template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutab new (r_value) T(varray_[index]); } - bool is_span() const override - { - return varray_.is_span(); - } - - GSpan get_internal_span() const override + CommonVArrayInfo common_info() const override { - Span<T> span = varray_.get_internal_span(); - return span; - } - - bool is_single() const override - { - return varray_.is_single(); - } - - void get_internal_single(void *r_value) const override - { - *(T *)r_value = varray_.get_internal_single(); + return varray_.common_info(); } void set_by_copy(const int64_t index, const void *value) override @@ -543,11 +482,6 @@ template<typename T> class GVMutableArrayImpl_For_VMutableArray : public GVMutab *(VMutableArray<T> *)varray = varray_; return true; } - - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } }; /* Used to convert an generic mutable virtual array into a typed one. */ @@ -576,26 +510,9 @@ template<typename T> class VMutableArrayImpl_For_GVMutableArray : public VMutabl varray_.set_by_relocate(index, &value); } - bool is_span() const override - { - return varray_.is_span(); - } - - Span<T> get_internal_span() const override - { - return varray_.get_internal_span().template typed<T>(); - } - - bool is_single() const override + CommonVArrayInfo common_info() const override { - return varray_.is_single(); - } - - T get_internal_single() const override - { - T value; - varray_.get_internal_single(&value); - return value; + return varray_.common_info(); } bool try_assign_GVArray(GVArray &varray) const override @@ -610,11 +527,6 @@ template<typename T> class VMutableArrayImpl_For_GVMutableArray : public VMutabl return true; } - bool may_have_ownership() const override - { - return varray_.may_have_ownership(); - } - void materialize(IndexMask mask, MutableSpan<T> r_span) const override { varray_.materialize(mask, r_span.data()); @@ -670,8 +582,7 @@ class GVArrayImpl_For_GSpan : public GVMutableArrayImpl { void set_by_move(int64_t index, void *value) override; void set_by_relocate(int64_t index, void *value) override; - bool is_span() const override; - GSpan get_internal_span() const override; + CommonVArrayInfo common_info() const override; virtual void materialize(const IndexMask mask, void *dst) const override; virtual void materialize_to_uninitialized(const IndexMask mask, void *dst) const override; @@ -686,10 +597,7 @@ class GVArrayImpl_For_GSpan_final final : public GVArrayImpl_For_GSpan { using GVArrayImpl_For_GSpan::GVArrayImpl_For_GSpan; private: - bool may_have_ownership() const override - { - return false; - } + CommonVArrayInfo common_info() const override; }; /** \} */ @@ -715,10 +623,7 @@ class GVArrayImpl_For_SingleValueRef : public GVArrayImpl { void get(const int64_t index, void *r_value) const override; void get_to_uninitialized(const int64_t index, void *r_value) const override; - bool is_span() const override; - GSpan get_internal_span() const override; - bool is_single() const override; - void get_internal_single(void *r_value) const override; + CommonVArrayInfo common_info() const override; void materialize(const IndexMask mask, void *dst) const override; void materialize_to_uninitialized(const IndexMask mask, void *dst) const override; void materialize_compressed(const IndexMask mask, void *dst) const override; @@ -730,10 +635,7 @@ class GVArrayImpl_For_SingleValueRef_final final : public GVArrayImpl_For_Single using GVArrayImpl_For_SingleValueRef::GVArrayImpl_For_SingleValueRef; private: - bool may_have_ownership() const override - { - return false; - } + CommonVArrayInfo common_info() const override; }; /** \} */ @@ -859,6 +761,11 @@ inline GVArrayCommon::operator bool() const return impl_ != nullptr; } +inline CommonVArrayInfo GVArrayCommon::common_info() const +{ + return impl_->common_info(); +} + inline int64_t GVArrayCommon::size() const { if (impl_ == nullptr) { @@ -931,25 +838,20 @@ template<typename T> inline GVArray::GVArray(const VArray<T> &varray) if (!varray) { return; } - if (varray.try_assign_GVArray(*this)) { + const CommonVArrayInfo info = varray.common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + *this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), info.data); return; } - if (varray.is_single()) { - T value = varray.get_internal_single(); - *this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), &value); + /* 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) { + *this = GVArray::ForSpan(GSpan(CPPType::get<T>(), info.data, varray.size())); } - /* Need to check this before the span special case, because otherwise we might loose - * ownership to the referenced data when #varray goes out of scope. */ - else if (varray.may_have_ownership()) { - *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); - } - else if (varray.is_span()) { - Span<T> data = varray.get_internal_span(); - *this = GVArray::ForSpan(data); - } - else { - *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); + if (varray.try_assign_GVArray(*this)) { + return; } + *this = GVArray::For<GVArrayImpl_For_VArray<T>>(varray); } template<typename T> inline VArray<T> GVArray::typed() const @@ -958,22 +860,19 @@ template<typename T> inline VArray<T> GVArray::typed() const return {}; } BLI_assert(impl_->type().is<T>()); + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Single) { + return VArray<T>::ForSingle(*static_cast<const T *>(info.data), this->size()); + } + /* 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 VArray<T>::ForSpan(Span<T>(static_cast<const T *>(info.data), this->size())); + } VArray<T> varray; if (this->try_assign_VArray(varray)) { return varray; } - if (this->is_single()) { - T value; - this->get_internal_single(&value); - return VArray<T>::ForSingle(value, this->size()); - } - if (this->may_have_ownership()) { - return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); - } - if (this->is_span()) { - const Span<T> span = this->get_internal_span().typed<T>(); - return VArray<T>::ForSpan(span); - } return VArray<T>::template For<VArrayImpl_For_GVArray<T>>(*this); } @@ -997,19 +896,16 @@ template<typename T> inline GVMutableArray::GVMutableArray(const VMutableArray<T if (!varray) { return; } - if (varray.try_assign_GVMutableArray(*this)) { + const CommonVArrayInfo info = varray.common_info(); + if (info.type == CommonVArrayInfo::Type::Span && !info.may_have_ownership) { + *this = GVMutableArray::ForSpan( + GMutableSpan(CPPType::get<T>(), const_cast<void *>(info.data), varray.size())); return; } - if (varray.may_have_ownership()) { - *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray); - } - else if (varray.is_span()) { - MutableSpan<T> data = varray.get_internal_span(); - *this = GVMutableArray::ForSpan(data); - } - else { - *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray); + if (varray.try_assign_GVMutableArray(*this)) { + return; } + *this = GVMutableArray::For<GVMutableArrayImpl_For_VMutableArray<T>>(varray); } template<typename T> inline VMutableArray<T> GVMutableArray::typed() const @@ -1018,17 +914,15 @@ template<typename T> inline VMutableArray<T> GVMutableArray::typed() const return {}; } BLI_assert(this->type().is<T>()); + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Span && !info.may_have_ownership) { + return VMutableArray<T>::ForSpan( + MutableSpan<T>(const_cast<T *>(static_cast<const T *>(info.data)), this->size())); + } VMutableArray<T> varray; if (this->try_assign_VMutableArray(varray)) { return varray; } - if (this->may_have_ownership()) { - return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this); - } - if (this->is_span()) { - const MutableSpan<T> span = this->get_internal_span().typed<T>(); - return VMutableArray<T>::ForSpan(span); - } return VMutableArray<T>::template For<VMutableArrayImpl_For_GVMutableArray<T>>(*this); } diff --git a/source/blender/blenlib/BLI_virtual_array.hh b/source/blender/blenlib/BLI_virtual_array.hh index 8f228ea188e..e34eac1a006 100644 --- a/source/blender/blenlib/BLI_virtual_array.hh +++ b/source/blender/blenlib/BLI_virtual_array.hh @@ -35,6 +35,33 @@ class GVArray; class GVMutableArray; /** + * Is used to quickly check if a varray is a span or single value. This struct also allows + * retrieving multiple pieces of data with a single virtual method call. + */ +struct CommonVArrayInfo { + enum class Type : uint8_t { + /* Is not one of the common special types below. */ + Any, + Span, + Single, + }; + + Type type = Type::Any; + + /** True when the #data becomes a dangling pointer when the virtual array is destructed. */ + bool may_have_ownership = true; + + /** Points either to nothing, a single value or array of values, depending on #type. */ + const void *data; + + CommonVArrayInfo() = default; + CommonVArrayInfo(const Type _type, const bool _may_have_ownership, const void *_data) + : type(_type), may_have_ownership(_may_have_ownership), data(_data) + { + } +}; + +/** * Implements the specifics of how the elements of a virtual array are accessed. It contains a * bunch of virtual methods that are wrapped by #VArray. */ @@ -65,47 +92,12 @@ template<typename T> class VArrayImpl { */ virtual T get(int64_t index) const = 0; - /** - * Return true when the virtual array is a plain array internally. - */ - virtual bool is_span() const - { - return false; - } - - /** - * Return the span of the virtual array. - * This invokes undefined behavior when #is_span returned false. - */ - virtual Span<T> get_internal_span() const + virtual CommonVArrayInfo common_info() const { - /* Provide a default implementation, so that subclasses don't have to provide it. This method - * should never be called because #is_span returns false by default. */ - BLI_assert_unreachable(); return {}; } /** - * Return true when the virtual array has the same value at every index. - */ - virtual bool is_single() const - { - return false; - } - - /** - * Return the value that is used at every index. - * This invokes undefined behavior when #is_single returned false. - */ - virtual T get_internal_single() const - { - /* Provide a default implementation, so that subclasses don't have to provide it. This method - * should never be called because #is_single returns false by default. */ - BLI_assert_unreachable(); - return T(); - } - - /** * Copy values from the virtual array into the provided span. The index of the value in the * virtual array is the same as the index in the span. */ @@ -113,16 +105,22 @@ template<typename T> class VArrayImpl { { T *dst = r_span.data(); /* Optimize for a few different common cases. */ - if (this->is_span()) { - const T *src = this->get_internal_span().data(); - mask.foreach_index([&](const int64_t i) { dst[i] = src[i]; }); - } - else if (this->is_single()) { - const T single = this->get_internal_single(); - mask.foreach_index([&](const int64_t i) { dst[i] = single; }); - } - else { - mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + const CommonVArrayInfo info = this->common_info(); + switch (info.type) { + case CommonVArrayInfo::Type::Any: { + mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); }); + break; + } + case CommonVArrayInfo::Type::Span: { + const T *src = static_cast<const T *>(info.data); + mask.foreach_index([&](const int64_t i) { dst[i] = src[i]; }); + break; + } + case CommonVArrayInfo::Type::Single: { + const T single = *static_cast<const T *>(info.data); + mask.foreach_index([&](const int64_t i) { dst[i] = single; }); + break; + } } } @@ -133,16 +131,22 @@ template<typename T> class VArrayImpl { { T *dst = r_span.data(); /* Optimize for a few different common cases. */ - if (this->is_span()) { - const T *src = this->get_internal_span().data(); - mask.foreach_index([&](const int64_t i) { new (dst + i) T(src[i]); }); - } - else if (this->is_single()) { - const T single = this->get_internal_single(); - mask.foreach_index([&](const int64_t i) { new (dst + i) T(single); }); - } - else { - mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); }); + const CommonVArrayInfo info = this->common_info(); + switch (info.type) { + case CommonVArrayInfo::Type::Any: { + mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); }); + break; + } + case CommonVArrayInfo::Type::Span: { + const T *src = static_cast<const T *>(info.data); + mask.foreach_index([&](const int64_t i) { new (dst + i) T(src[i]); }); + break; + } + case CommonVArrayInfo::Type::Single: { + const T single = *static_cast<const T *>(info.data); + mask.foreach_index([&](const int64_t i) { new (dst + i) T(single); }); + break; + } } } @@ -187,17 +191,6 @@ template<typename T> class VArrayImpl { } /** - * Return true when this virtual array may own any of the memory it references. This can be used - * for optimization purposes when converting or copying the virtual array. - */ - virtual bool may_have_ownership() const - { - /* Use true by default to be on the safe side. Subclasses that know for sure that they don't - * own anything can overwrite this with false. */ - return true; - } - - /** * Return true when the other virtual array should be considered to be the same, e.g. because it * shares the same underlying memory. */ @@ -222,10 +215,10 @@ template<typename T> class VMutableArrayImpl : public VArrayImpl<T> { */ virtual void set_all(Span<T> src) { - if (this->is_span()) { - const Span<T> const_span = this->get_internal_span(); - const MutableSpan<T> span{(T *)const_span.data(), const_span.size()}; - initialized_copy_n(src.data(), this->size_, span.data()); + const CommonVArrayInfo info = this->common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + initialized_copy_n( + src.data(), this->size_, const_cast<T *>(static_cast<const T *>(info.data))); } else { const int64_t size = this->size_; @@ -273,14 +266,9 @@ template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> { data_[index] = value; } - bool is_span() const override + CommonVArrayInfo common_info() const override { - return true; - } - - Span<T> get_internal_span() const override - { - return Span<T>(data_, this->size_); + return CommonVArrayInfo(CommonVArrayInfo::Type::Span, true, data_); } bool is_same(const VArrayImpl<T> &other) const final @@ -288,11 +276,11 @@ template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> { if (other.size() != this->size_) { return false; } - if (!other.is_span()) { + const CommonVArrayInfo other_info = other.common_info(); + if (other_info.type != CommonVArrayInfo::Type::Span) { return false; } - const Span<T> other_span = other.get_internal_span(); - return data_ == other_span.data(); + return data_ == static_cast<const T *>(other_info.data); } void materialize_compressed(IndexMask mask, MutableSpan<T> r_span) const override @@ -325,9 +313,9 @@ template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_F using VArrayImpl_For_Span<T>::VArrayImpl_For_Span; private: - bool may_have_ownership() const override + CommonVArrayInfo common_info() const final { - return false; + return CommonVArrayInfo(CommonVArrayInfo::Type::Span, false, this->data_); } }; @@ -371,24 +359,9 @@ template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> { return value_; } - bool is_span() const override + CommonVArrayInfo common_info() const override { - return this->size_ == 1; - } - - Span<T> get_internal_span() const override - { - return Span<T>(&value_, 1); - } - - bool is_single() const override - { - return true; - } - - T get_internal_single() const override - { - return value_; + return CommonVArrayInfo(CommonVArrayInfo::Type::Single, true, &value_); } void materialize_compressed(IndexMask mask, MutableSpan<T> r_span) const override @@ -531,11 +504,6 @@ class VArrayImpl_For_DerivedSpan final : public VMutableArrayImpl<ElemT> { }); } - bool may_have_ownership() const override - { - return false; - } - bool is_same(const VArrayImpl<ElemT> &other) const override { if (other.size() != this->size_) { @@ -768,11 +736,18 @@ template<typename T> class VArrayCommon { return IndexRange(this->size()); } + CommonVArrayInfo common_info() const + { + BLI_assert(*this); + return impl_->common_info(); + } + /** Return true when the virtual array is stored as a span internally. */ bool is_span() const { BLI_assert(*this); - return impl_->is_span(); + const CommonVArrayInfo info = impl_->common_info(); + return info.type == CommonVArrayInfo::Type::Span; } /** @@ -782,14 +757,16 @@ template<typename T> class VArrayCommon { Span<T> get_internal_span() const { BLI_assert(this->is_span()); - return impl_->get_internal_span(); + const CommonVArrayInfo info = impl_->common_info(); + return Span<T>(static_cast<const T *>(info.data), this->size()); } /** Return true when the virtual array returns the same value for every index. */ bool is_single() const { BLI_assert(*this); - return impl_->is_single(); + const CommonVArrayInfo info = impl_->common_info(); + return info.type == CommonVArrayInfo::Type::Single; } /** @@ -799,7 +776,8 @@ template<typename T> class VArrayCommon { T get_internal_single() const { BLI_assert(this->is_single()); - return impl_->get_internal_single(); + const CommonVArrayInfo info = impl_->common_info(); + return *static_cast<const T *>(info.data); } /** @@ -861,12 +839,6 @@ template<typename T> class VArrayCommon { { return impl_->try_assign_GVArray(varray); } - - /** See #GVArrayImpl::may_have_ownership. */ - bool may_have_ownership() const - { - return impl_->may_have_ownership(); - } }; template<typename T> class VMutableArray; @@ -1076,8 +1048,8 @@ template<typename T> class VMutableArray : public VArrayCommon<T> { MutableSpan<T> get_internal_span() const { BLI_assert(this->is_span()); - const Span<T> span = this->impl_->get_internal_span(); - return MutableSpan<T>(const_cast<T *>(span.data()), span.size()); + const CommonVArrayInfo info = this->get_impl()->common_info(); + return MutableSpan<T>(const_cast<T *>(static_cast<const T *>(info.data)), this->size()); } /** @@ -1143,8 +1115,9 @@ template<typename T> class VArray_Span final : public Span<T> { VArray_Span(VArray<T> varray) : Span<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); - if (varray_.is_span()) { - this->data_ = varray_.get_internal_span().data(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + this->data_ = static_cast<const T *>(info.data); } else { owned_data_.~Array(); @@ -1158,8 +1131,9 @@ template<typename T> class VArray_Span final : public Span<T> { : varray_(std::move(other.varray_)), owned_data_(std::move(other.owned_data_)) { this->size_ = varray_.size(); - if (varray_.is_span()) { - this->data_ = varray_.get_internal_span().data(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + this->data_ = static_cast<const T *>(info.data); } else { this->data_ = owned_data_.data(); @@ -1200,8 +1174,9 @@ template<typename T> class VMutableArray_Span final : public MutableSpan<T> { : MutableSpan<T>(), varray_(std::move(varray)) { this->size_ = varray_.size(); - if (varray_.is_span()) { - this->data_ = varray_.get_internal_span().data(); + const CommonVArrayInfo info = varray_.common_info(); + if (info.type == CommonVArrayInfo::Type::Span) { + this->data_ = const_cast<T *>(static_cast<const T *>(info.data)); } else { if (copy_values_to_span) { diff --git a/source/blender/blenlib/intern/generic_virtual_array.cc b/source/blender/blenlib/intern/generic_virtual_array.cc index a6fbf4bff5b..9287a1016f5 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 +CommonVArrayInfo GVArrayImpl_For_SingleValueRef::common_info() const { - return size_ == 1; -} -GSpan GVArrayImpl_For_SingleValueRef::get_internal_span() const -{ - return GSpan{*type_, value_, 1}; -} - -bool GVArrayImpl_For_SingleValueRef::is_single() 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,18 +270,14 @@ 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_}; } }; @@ -335,8 +290,9 @@ template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public GVArray_GSpan::GVArray_GSpan(GVArray varray) : GSpan(varray.type()), varray_(std::move(varray)) { 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__); @@ -363,8 +319,9 @@ GVMutableArray_GSpan::GVMutableArray_GSpan(GVMutableArray varray, const bool cop : GMutableSpan(varray.type()), varray_(std::move(varray)) { 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__); @@ -437,22 +394,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 { - 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 +494,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 +516,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 @@ -752,10 +710,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 |