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
This commit is contained in:
@@ -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
|
||||
CommonVArrayInfo common_info() 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
|
||||
{
|
||||
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
|
||||
CommonVArrayInfo common_info() const override
|
||||
{
|
||||
return varray_.is_span();
|
||||
}
|
||||
|
||||
GSpan get_internal_span() 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
|
||||
CommonVArrayInfo common_info() 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
|
||||
{
|
||||
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;
|
||||
}
|
||||
const CommonVArrayInfo info = varray.common_info();
|
||||
if (info.type == CommonVArrayInfo::Type::Single) {
|
||||
*this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), info.data);
|
||||
return;
|
||||
}
|
||||
/* 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()));
|
||||
}
|
||||
if (varray.try_assign_GVArray(*this)) {
|
||||
return;
|
||||
}
|
||||
if (varray.is_single()) {
|
||||
T value = varray.get_internal_single();
|
||||
*this = GVArray::ForSingle(CPPType::get<T>(), varray.size(), &value);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
*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;
|
||||
}
|
||||
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.try_assign_GVMutableArray(*this)) {
|
||||
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);
|
||||
}
|
||||
*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);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,33 @@ namespace blender {
|
||||
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,46 +92,11 @@ 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
|
||||
virtual CommonVArrayInfo common_info() 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
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,17 +190,6 @@ template<typename T> class VArrayImpl {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
@@ -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
|
||||
CommonVArrayInfo GVArrayImpl_For_GSpan::common_info() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
GSpan GVArrayImpl_For_GSpan::get_internal_span() 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,19 +270,15 @@ 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
|
||||
{
|
||||
this->copy_value_to(r_value);
|
||||
}
|
||||
|
||||
void copy_value_to(void *dst) const
|
||||
{
|
||||
memcpy(dst, &buffer_, type_->size());
|
||||
}
|
||||
|
||||
CommonVArrayInfo common_info() const override
|
||||
{
|
||||
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
|
||||
CommonVArrayInfo common_info() const
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user