Blender V4.5
BLI_virtual_array.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
27
28#include <optional>
29
30#include "BLI_any.hh"
31#include "BLI_array.hh"
33#include "BLI_index_mask.hh"
34#include "BLI_span.hh"
35
36namespace blender {
37
39class GVArray;
40class GVMutableArray;
41
47 enum class Type : uint8_t {
48 /* Is not one of the common special types below. */
52 };
53
55
57 bool may_have_ownership = true;
58
63 const void *data;
64
65 CommonVArrayInfo() = default;
66 CommonVArrayInfo(const Type _type, const bool _may_have_ownership, const void *_data)
67 : type(_type), may_have_ownership(_may_have_ownership), data(_data)
68 {
69 }
70};
71
76template<typename T> class VArrayImpl {
77 protected:
83
84 public:
86 {
87 BLI_assert(size_ >= 0);
88 }
89
90 virtual ~VArrayImpl() = default;
91
92 int64_t size() const
93 {
94 return size_;
95 }
96
101 virtual T get(int64_t index) const = 0;
102
104 {
105 return {};
106 }
107
112 virtual void materialize(const IndexMask &mask, T *dst) const
113 {
114 mask.foreach_index([&](const int64_t i) { dst[i] = this->get(i); });
115 }
116
120 virtual void materialize_to_uninitialized(const IndexMask &mask, T *dst) const
121 {
122 mask.foreach_index([&](const int64_t i) { new (dst + i) T(this->get(i)); });
123 }
124
130 virtual void materialize_compressed(const IndexMask &mask, T *dst) const
131 {
132 mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = this->get(i); });
133 }
134
139 {
140 mask.foreach_index(
141 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(this->get(i)); });
142 }
143
150 virtual bool try_assign_GVArray(GVArray & /*varray*/) const
151 {
152 return false;
153 }
154};
155
157template<typename T> class VMutableArrayImpl : public VArrayImpl<T> {
158 public:
160
164 virtual void set(int64_t index, T value) = 0;
165
169 virtual void set_all(Span<T> src)
170 {
171 const CommonVArrayInfo info = this->common_info();
174 src.data(), this->size_, const_cast<T *>(static_cast<const T *>(info.data)));
175 }
176 else {
177 const int64_t size = this->size_;
178 for (int64_t i = 0; i < size; i++) {
179 this->set(i, src[i]);
180 }
181 }
182 }
183
187 virtual bool try_assign_GVMutableArray(GVMutableArray & /*varray*/) const
188 {
189 return false;
190 }
191};
192
197template<typename T> class VArrayImpl_For_Span : public VMutableArrayImpl<T> {
198 protected:
199 T *data_ = nullptr;
200
201 public:
206
207 protected:
209
210 T get(const int64_t index) const final
211 {
212 return data_[index];
213 }
214
215 void set(const int64_t index, T value) final
216 {
217 data_[index] = value;
218 }
219
221 {
223 }
224
225 void materialize(const IndexMask &mask, T *dst) const override
226 {
227 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { dst[i] = data_[i]; });
228 }
229
230 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
231 {
232 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { new (dst + i) T(data_[i]); });
233 }
234
235 void materialize_compressed(const IndexMask &mask, T *dst) const override
236 {
237 mask.foreach_index_optimized<int64_t>(
238 [&](const int64_t i, const int64_t pos) { dst[pos] = data_[i]; });
239 }
240
241 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
242 {
243 mask.foreach_index_optimized<int64_t>(
244 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(data_[i]); });
245 }
246};
247
252template<typename T> class VArrayImpl_For_Span_final final : public VArrayImpl_For_Span<T> {
253 public:
255
257 /* Cast const away, because the implementation for const and non const spans is shared. */
258 : VArrayImpl_For_Span<T>({const_cast<T *>(data.data()), data.size()})
259 {
260 }
261
262 private:
263 CommonVArrayInfo common_info() const final
264 {
265 return CommonVArrayInfo(CommonVArrayInfo::Type::Span, false, this->data_);
266 }
267};
268
269template<typename T>
271
278template<typename Container, typename T = typename Container::value_type>
280 private:
281 Container container_;
282
283 public:
284 VArrayImpl_For_ArrayContainer(Container container)
285 : VArrayImpl_For_Span<T>(int64_t(container.size())), container_(std::move(container))
286 {
287 this->data_ = const_cast<T *>(container_.data());
288 }
289};
290
296template<typename T> class VArrayImpl_For_Single final : public VArrayImpl<T> {
297 private:
298 T value_;
299
300 public:
302 : VArrayImpl<T>(size), value_(std::move(value))
303 {
304 }
305
306 protected:
307 T get(const int64_t /*index*/) const override
308 {
309 return value_;
310 }
311
313 {
315 }
316
317 void materialize(const IndexMask &mask, T *dst) const override
318 {
319 mask.foreach_index([&](const int64_t i) { dst[i] = value_; });
320 }
321
322 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
323 {
324 mask.foreach_index([&](const int64_t i) { new (dst + i) T(value_); });
325 }
326
327 void materialize_compressed(const IndexMask &mask, T *dst) const override
328 {
329 initialized_fill_n(dst, mask.size(), value_);
330 }
331
332 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
333 {
334 uninitialized_fill_n(dst, mask.size(), value_);
335 }
336};
337
338template<typename T>
340
345template<typename T, typename GetFunc> class VArrayImpl_For_Func final : public VArrayImpl<T> {
346 private:
347 GetFunc get_func_;
348
349 public:
350 VArrayImpl_For_Func(const int64_t size, GetFunc get_func)
351 : VArrayImpl<T>(size), get_func_(std::move(get_func))
352 {
353 }
354
355 private:
356 T get(const int64_t index) const override
357 {
358 return get_func_(index);
359 }
360
361 void materialize(const IndexMask &mask, T *dst) const override
362 {
363 mask.foreach_index([&](const int64_t i) { dst[i] = get_func_(i); });
364 }
365
366 void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
367 {
368 mask.foreach_index([&](const int64_t i) { new (dst + i) T(get_func_(i)); });
369 }
370
371 void materialize_compressed(const IndexMask &mask, T *dst) const override
372 {
373 mask.foreach_index([&](const int64_t i, const int64_t pos) { dst[pos] = get_func_(i); });
374 }
375
376 void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
377 {
378 mask.foreach_index(
379 [&](const int64_t i, const int64_t pos) { new (dst + pos) T(get_func_(i)); });
380 }
381};
382
386template<typename StructT,
387 typename ElemT,
388 ElemT (*GetFunc)(const StructT &),
389 void (*SetFunc)(StructT &, ElemT) = nullptr>
391 private:
392 StructT *data_;
393
394 public:
399
400 template<typename OtherStructT,
401 typename OtherElemT,
402 OtherElemT (*OtherGetFunc)(const OtherStructT &),
403 void (*OtherSetFunc)(OtherStructT &, OtherElemT)>
405
406 private:
407 ElemT get(const int64_t index) const override
408 {
409 return GetFunc(data_[index]);
410 }
411
412 void set(const int64_t index, ElemT value) override
413 {
414 SetFunc(data_[index], std::move(value));
415 }
416
417 void materialize(const IndexMask &mask, ElemT *dst) const override
418 {
419 mask.foreach_index_optimized<int64_t>([&](const int64_t i) { dst[i] = GetFunc(data_[i]); });
420 }
421
422 void materialize_to_uninitialized(const IndexMask &mask, ElemT *dst) const override
423 {
424 mask.foreach_index_optimized<int64_t>(
425 [&](const int64_t i) { new (dst + i) ElemT(GetFunc(data_[i])); });
426 }
427
428 void materialize_compressed(const IndexMask &mask, ElemT *dst) const override
429 {
430 mask.foreach_index_optimized<int64_t>(
431 [&](const int64_t i, const int64_t pos) { dst[pos] = GetFunc(data_[i]); });
432 }
433
434 void materialize_compressed_to_uninitialized(const IndexMask &mask, ElemT *dst) const override
435 {
436 mask.foreach_index_optimized<int64_t>(
437 [&](const int64_t i, const int64_t pos) { new (dst + pos) ElemT(GetFunc(data_[i])); });
438 }
439};
440
441template<typename StructT,
442 typename ElemT,
443 ElemT (*GetFunc)(const StructT &),
444 void (*SetFunc)(StructT &, ElemT)>
445inline constexpr bool
447
448namespace detail {
449
454template<typename T> struct VArrayAnyExtraInfo {
458 const VArrayImpl<T> *(*get_varray)(const void *buffer);
459
460 template<typename StorageT> static constexpr VArrayAnyExtraInfo get()
461 {
462 /* These are the only allowed types in the #Any. */
463 static_assert(
464 std::is_base_of_v<VArrayImpl<T>, StorageT> ||
465 is_same_any_v<StorageT, const VArrayImpl<T> *, std::shared_ptr<const VArrayImpl<T>>>);
466
467 /* Depending on how the virtual array implementation is stored in the #Any, a different
468 * #get_varray function is required. */
469 if constexpr (std::is_base_of_v<VArrayImpl<T>, StorageT>) {
470 return {[](const void *buffer) {
471 return static_cast<const VArrayImpl<T> *>((const StorageT *)buffer);
472 }};
473 }
474 else if constexpr (std::is_same_v<StorageT, const VArrayImpl<T> *>) {
475 return {[](const void *buffer) { return *(const StorageT *)buffer; }};
476 }
477 else if constexpr (std::is_same_v<StorageT, std::shared_ptr<const VArrayImpl<T>>>) {
478 return {[](const void *buffer) { return ((const StorageT *)buffer)->get(); }};
479 }
480 else {
482 return {};
483 }
484 }
485};
486
487} // namespace detail
488
496template<typename T> class VArrayCommon {
497 protected:
506
510 const VArrayImpl<T> *impl_ = nullptr;
519
520 VArrayCommon() = default;
521
524 {
525 impl_ = this->impl_from_storage();
526 }
527
529 VArrayCommon(VArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
530 {
531 impl_ = this->impl_from_storage();
532 other.storage_.reset();
533 other.impl_ = nullptr;
534 }
535
540 VArrayCommon(const VArrayImpl<T> *impl) : impl_(impl)
541 {
542 storage_ = impl_;
543 }
544
548 VArrayCommon(std::shared_ptr<const VArrayImpl<T>> impl) : impl_(impl.get())
549 {
550 if (impl) {
551 storage_ = std::move(impl);
552 }
553 }
554
558 template<typename ImplT, typename... Args> void emplace(Args &&...args)
559 {
560 /* Make sure we are actually constructing a #VArrayImpl. */
561 static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
562 if constexpr (std::is_copy_constructible_v<ImplT> && Storage::template is_inline_v<ImplT>) {
563 /* Only inline the implementation when it is copyable and when it fits into the inline
564 * buffer of the storage. */
565 impl_ = &storage_.template emplace<ImplT>(std::forward<Args>(args)...);
566 }
567 else {
568 /* If it can't be inlined, create a new #std::shared_ptr instead and store that in the
569 * storage. */
570 std::shared_ptr<const VArrayImpl<T>> ptr = std::make_shared<ImplT>(
571 std::forward<Args>(args)...);
572 impl_ = &*ptr;
573 storage_ = std::move(ptr);
574 }
575 }
576
578 void copy_from(const VArrayCommon &other)
579 {
580 if (this == &other) {
581 return;
582 }
583 storage_ = other.storage_;
584 impl_ = this->impl_from_storage();
585 }
586
588 void move_from(VArrayCommon &&other) noexcept
589 {
590 if (this == &other) {
591 return;
592 }
593 storage_ = std::move(other.storage_);
594 impl_ = this->impl_from_storage();
595 other.storage_.reset();
596 other.impl_ = nullptr;
597 }
598
602 {
603 if (!storage_.has_value()) {
604 return nullptr;
605 }
606 return storage_.extra_info().get_varray(storage_.get());
607 }
608
609 public:
611 operator bool() const
612 {
613 return impl_ != nullptr;
614 }
615
621 T operator[](const int64_t index) const
622 {
623 BLI_assert(*this);
624 BLI_assert(index >= 0);
625 BLI_assert(index < this->size());
626 return impl_->get(index);
627 }
628
633 T get(const int64_t index) const
634 {
635 return (*this)[index];
636 }
637
642 int64_t size() const
643 {
644 if (impl_ == nullptr) {
645 return 0;
646 }
647 return impl_->size();
648 }
649
652 T first() const
653 {
654 return (*this)[0];
655 }
656
659 T last(const int64_t n = 0) const
660 {
661 return (*this)[this->size() - 1 - n];
662 }
663
665 bool is_empty() const
666 {
667 return this->size() == 0;
668 }
669
671 {
672 return IndexRange(this->size());
673 }
674
676 {
677 BLI_assert(*this);
678 return impl_->common_info();
679 }
680
682 bool is_span() const
683 {
684 BLI_assert(*this);
685 const CommonVArrayInfo info = impl_->common_info();
686 return info.type == CommonVArrayInfo::Type::Span;
687 }
688
694 {
695 BLI_assert(this->is_span());
696 const CommonVArrayInfo info = impl_->common_info();
697 return Span<T>(static_cast<const T *>(info.data), this->size());
698 }
699
701 bool is_single() const
702 {
703 BLI_assert(*this);
704 const CommonVArrayInfo info = impl_->common_info();
706 }
707
713 {
714 BLI_assert(this->is_single());
715 const CommonVArrayInfo info = impl_->common_info();
716 return *static_cast<const T *>(info.data);
717 }
718
722 std::optional<T> get_if_single() const
723 {
724 const CommonVArrayInfo info = impl_->common_info();
726 return std::nullopt;
727 }
728 return *static_cast<const T *>(info.data);
729 }
730
732 void materialize(MutableSpan<T> r_span) const
733 {
734 this->materialize(IndexMask(this->size()), r_span);
735 }
736
738 void materialize(const IndexMask &mask, MutableSpan<T> r_span) const
739 {
740 BLI_assert(mask.min_array_size() <= this->size());
741 impl_->materialize(mask, r_span.data());
742 }
743
745 {
746 this->materialize_to_uninitialized(IndexMask(this->size()), r_span);
747 }
748
750 {
751 BLI_assert(mask.min_array_size() <= this->size());
752 impl_->materialize_to_uninitialized(mask, r_span.data());
753 }
754
757 {
758 impl_->materialize_compressed(mask, r_span.data());
759 }
760
762 {
763 impl_->materialize_compressed_to_uninitialized(mask, r_span.data());
764 }
765
767 bool try_assign_GVArray(GVArray &varray) const
768 {
769 return impl_->try_assign_GVArray(varray);
770 }
771
773 {
774 return impl_;
775 }
776};
777
778template<typename T> class VMutableArray;
779
787namespace varray_tag {
788struct span {};
789struct single_ref {};
790struct single {};
791} // namespace varray_tag
792
798template<typename T> class VArray : public VArrayCommon<T> {
799 friend VMutableArray<T>;
800
801 public:
802 VArray() = default;
803 VArray(const VArray &other) = default;
804 VArray(VArray &&other) noexcept = default;
805
806 VArray(const VArrayImpl<T> *impl) : VArrayCommon<T>(impl) {}
807
808 VArray(std::shared_ptr<const VArrayImpl<T>> impl) : VArrayCommon<T>(std::move(impl)) {}
809
811 {
812 this->template emplace<VArrayImpl_For_Span_final<T>>(span);
813 }
814
815 VArray(varray_tag::single /*tag*/, T value, const int64_t size)
816 {
817 this->template emplace<VArrayImpl_For_Single<T>>(std::move(value), size);
818 }
819
823 template<typename ImplT, typename... Args> static VArray For(Args &&...args)
824 {
825 static_assert(std::is_base_of_v<VArrayImpl<T>, ImplT>);
826 VArray varray;
827 varray.template emplace<ImplT>(std::forward<Args>(args)...);
828 return varray;
829 }
830
834 static VArray ForSingle(T value, const int64_t size)
835 {
836 return VArray(varray_tag::single{}, std::move(value), size);
837 }
838
843 static VArray ForSpan(Span<T> values)
844 {
845 return VArray(varray_tag::span{}, values);
846 }
847
852 template<typename GetFunc> static VArray ForFunc(const int64_t size, GetFunc get_func)
853 {
854 return VArray::For<VArrayImpl_For_Func<T, decltype(get_func)>>(size, std::move(get_func));
855 }
856
861 template<typename StructT, T (*GetFunc)(const StructT &)>
863 {
864 /* Cast const away, because the virtual array implementation for const and non const derived
865 * spans is shared. */
866 MutableSpan<StructT> span{const_cast<StructT *>(values.data()), values.size()};
868 }
869
875 template<typename ContainerT> static VArray ForContainer(ContainerT container)
876 {
877 return VArray::For<VArrayImpl_For_ArrayContainer<ContainerT>>(std::move(container));
878 }
879
880 VArray &operator=(const VArray &other)
881 {
882 this->copy_from(other);
883 return *this;
884 }
885
886 VArray &operator=(VArray &&other) noexcept
887 {
888 this->move_from(std::move(other));
889 return *this;
890 }
891};
892
896template<typename T> class VMutableArray : public VArrayCommon<T> {
897 public:
898 VMutableArray() = default;
899 VMutableArray(const VMutableArray &other) = default;
900 VMutableArray(VMutableArray &&other) noexcept = default;
901
903
904 VMutableArray(std::shared_ptr<const VMutableArrayImpl<T>> impl)
905 : VArrayCommon<T>(std::move(impl))
906 {
907 }
908
912 template<typename ImplT, typename... Args> static VMutableArray For(Args &&...args)
913 {
914 static_assert(std::is_base_of_v<VMutableArrayImpl<T>, ImplT>);
915 VMutableArray varray;
916 varray.template emplace<ImplT>(std::forward<Args>(args)...);
917 return varray;
918 }
919
927
932 template<typename StructT, T (*GetFunc)(const StructT &), void (*SetFunc)(StructT &, T)>
937
943 template<typename ContainerT> static VMutableArray ForContainer(ContainerT container)
944 {
946 }
947
949 operator VArray<T>() const &
950 {
951 VArray<T> varray;
952 varray.copy_from(*this);
953 return varray;
954 }
955
957 operator VArray<T>() && noexcept
958 {
959 VArray<T> varray;
960 varray.move_from(std::move(*this));
961 return varray;
962 }
963
965 {
966 this->copy_from(other);
967 return *this;
968 }
969
971 {
972 this->move_from(std::move(other));
973 return *this;
974 }
975
981 {
982 BLI_assert(this->is_span());
983 const CommonVArrayInfo info = this->get_impl()->common_info();
984 return MutableSpan<T>(const_cast<T *>(static_cast<const T *>(info.data)), this->size());
985 }
986
990 void set(const int64_t index, T value)
991 {
992 BLI_assert(index >= 0);
993 BLI_assert(index < this->size());
994 this->get_impl()->set(index, std::move(value));
995 }
996
1001 {
1002 BLI_assert(src.size() == this->size());
1003 this->get_impl()->set_all(src);
1004 }
1005
1008 {
1009 return this->get_impl()->try_assign_GVMutableArray(varray);
1010 }
1011
1012 private:
1014 VMutableArrayImpl<T> *get_impl() const
1015 {
1016 /* This cast is valid by the invariant that a #VMutableArray->impl_ is always a
1017 * #VMutableArrayImpl. */
1018 return (VMutableArrayImpl<T> *)this->impl_;
1019 }
1020};
1021
1022template<typename T> static constexpr bool is_VArray_v = false;
1023template<typename T> static constexpr bool is_VArray_v<VArray<T>> = true;
1024
1025template<typename T> static constexpr bool is_VMutableArray_v = false;
1026template<typename T> static constexpr bool is_VMutableArray_v<VMutableArray<T>> = true;
1027
1039template<typename T> class VArraySpan final : public Span<T> {
1040 private:
1041 VArray<T> varray_;
1042 Array<T> owned_data_;
1043
1044 public:
1045 VArraySpan() = default;
1046
1047 VArraySpan(const VArray<T> &varray) : VArraySpan(VArray<T>(varray)) {}
1048
1049 VArraySpan(VArray<T> &&varray) : Span<T>(), varray_(std::move(varray))
1050 {
1051 if (!varray_) {
1052 return;
1053 }
1054 this->size_ = varray_.size();
1055 const CommonVArrayInfo info = varray_.common_info();
1056 if (info.type == CommonVArrayInfo::Type::Span) {
1057 this->data_ = static_cast<const T *>(info.data);
1058 }
1059 else {
1060 owned_data_.~Array();
1061 new (&owned_data_) Array<T>(varray_.size(), NoInitialization{});
1062 varray_.materialize_to_uninitialized(owned_data_);
1063 this->data_ = owned_data_.data();
1064 }
1065 }
1066
1068 : varray_(std::move(other.varray_)), owned_data_(std::move(other.owned_data_))
1069 {
1070 if (!varray_) {
1071 return;
1072 }
1073 this->size_ = varray_.size();
1074 const CommonVArrayInfo info = varray_.common_info();
1075 if (info.type == CommonVArrayInfo::Type::Span) {
1076 this->data_ = static_cast<const T *>(info.data);
1077 }
1078 else {
1079 this->data_ = owned_data_.data();
1080 }
1081 other.data_ = nullptr;
1082 other.size_ = 0;
1083 }
1084
1086 {
1087 if (this == &other) {
1088 return *this;
1089 }
1090 std::destroy_at(this);
1091 new (this) VArraySpan(std::move(other));
1092 return *this;
1093 }
1094};
1095
1096namespace internal {
1097void print_mutable_varray_span_warning();
1098}
1099
1107template<typename T> class MutableVArraySpan final : public MutableSpan<T> {
1108 private:
1109 VMutableArray<T> varray_;
1110 Array<T> owned_data_;
1111 bool save_has_been_called_ = false;
1112 bool show_not_saved_warning_ = true;
1113
1114 public:
1116
1117 /* Create a span for any virtual array. This is cheap when the virtual array is a span itself. If
1118 * not, a new array has to be allocated as a wrapper for the underlying virtual array. */
1119 MutableVArraySpan(VMutableArray<T> varray, const bool copy_values_to_span = true)
1120 : MutableSpan<T>(), varray_(std::move(varray))
1121 {
1122 if (!varray_) {
1123 return;
1124 }
1125
1126 this->size_ = varray_.size();
1127 const CommonVArrayInfo info = varray_.common_info();
1128 if (info.type == CommonVArrayInfo::Type::Span) {
1129 this->data_ = const_cast<T *>(static_cast<const T *>(info.data));
1130 }
1131 else {
1132 if (copy_values_to_span) {
1133 owned_data_.~Array();
1134 new (&owned_data_) Array<T>(varray_.size(), NoInitialization{});
1135 varray_.materialize_to_uninitialized(owned_data_);
1136 }
1137 else {
1138 owned_data_.reinitialize(varray_.size());
1139 }
1140 this->data_ = owned_data_.data();
1141 }
1142 }
1143
1145 : varray_(std::move(other.varray_)),
1146 owned_data_(std::move(other.owned_data_)),
1147 show_not_saved_warning_(other.show_not_saved_warning_)
1148 {
1149 if (!varray_) {
1150 return;
1151 }
1152
1153 this->size_ = varray_.size();
1154 const CommonVArrayInfo info = varray_.common_info();
1155 if (info.type == CommonVArrayInfo::Type::Span) {
1156 this->data_ = static_cast<T *>(const_cast<void *>(info.data));
1157 }
1158 else {
1159 this->data_ = owned_data_.data();
1160 }
1161 other.data_ = nullptr;
1162 other.size_ = 0;
1163 }
1164
1166 {
1167 if (varray_) {
1168 if (show_not_saved_warning_) {
1169 if (!save_has_been_called_) {
1171 }
1172 }
1173 }
1174 }
1175
1177 {
1178 if (this == &other) {
1179 return *this;
1180 }
1181 std::destroy_at(this);
1182 new (this) MutableVArraySpan(std::move(other));
1183 return *this;
1184 }
1185
1187 {
1188 return varray_;
1189 }
1190
1191 /* Write back all values from a temporary allocated array to the underlying virtual array. */
1192 void save()
1193 {
1194 save_has_been_called_ = true;
1195 if (this->data_ != owned_data_.data()) {
1196 return;
1197 }
1198 varray_.set_all(owned_data_);
1199 }
1200
1202 {
1203 show_not_saved_warning_ = false;
1204 }
1205};
1206
1207template<typename T> class SingleAsSpan {
1208 private:
1209 T value_;
1210 int64_t size_;
1211
1212 public:
1213 SingleAsSpan(T value, int64_t size) : value_(std::move(value)), size_(size)
1214 {
1215 BLI_assert(size_ >= 0);
1216 }
1217
1218 SingleAsSpan(const VArray<T> &varray) : SingleAsSpan(varray.get_internal_single(), varray.size())
1219 {
1220 }
1221
1222 const T &operator[](const int64_t index) const
1223 {
1224 BLI_assert(index >= 0);
1225 BLI_assert(index < size_);
1226 UNUSED_VARS_NDEBUG(index);
1227 return value_;
1228 }
1229};
1230
1231template<typename T> class VArrayRef {
1232 private:
1233 const VArray<T> &ref_;
1234
1235 public:
1236 VArrayRef(const VArray<T> &ref) : ref_(ref) {}
1237
1238 T operator[](const int64_t index) const
1239 {
1240 return ref_[index];
1241 }
1242};
1243
1245template<typename T, bool UseSingle, bool UseSpan> struct VArrayDevirtualizer {
1247
1248 template<typename Fn> bool devirtualize(const Fn &fn) const
1249 {
1250 const CommonVArrayInfo info = this->varray.common_info();
1251 const int64_t size = this->varray.size();
1252 if constexpr (UseSingle) {
1254 return fn(SingleAsSpan<T>(*static_cast<const T *>(info.data), size));
1255 }
1256 }
1257 if constexpr (UseSpan) {
1258 if (info.type == CommonVArrayInfo::Type::Span) {
1259 return fn(Span<T>(static_cast<const T *>(info.data), size));
1260 }
1261 }
1262 return false;
1263 }
1264};
1265
1274template<typename T, typename Func>
1275inline void devirtualize_varray(const VArray<T> &varray, const Func &func, bool enable = true)
1276{
1277 if (enable) {
1279 std::make_tuple(VArrayDevirtualizer<T, true, true>{varray}), func))
1280 {
1281 return;
1282 }
1283 }
1284 func(VArrayRef<T>(varray));
1285}
1286
1292template<typename T1, typename T2, typename Func>
1293inline void devirtualize_varray2(const VArray<T1> &varray1,
1294 const VArray<T2> &varray2,
1295 const Func &func,
1296 bool enable = true)
1297{
1298 if (enable) {
1300 std::make_tuple(VArrayDevirtualizer<T1, true, true>{varray1},
1302 func))
1303 {
1304 return;
1305 }
1306 }
1307 func(VArrayRef<T1>(varray1), VArrayRef<T2>(varray2));
1308}
1309
1310} // namespace blender
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define final(a, b, c)
Definition BLI_hash.h:19
#define UNUSED_VARS_NDEBUG(...)
BMesh const char void * data
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr MutableSpan()=default
constexpr T * data() const
Definition BLI_span.hh:539
const VMutableArray< T > & varray() const
MutableVArraySpan & operator=(MutableVArraySpan &&other)
MutableVArraySpan(MutableVArraySpan &&other)
MutableVArraySpan(VMutableArray< T > varray, const bool copy_values_to_span=true)
SingleAsSpan(const VArray< T > &varray)
const T & operator[](const int64_t index) const
SingleAsSpan(T value, int64_t size)
constexpr const T * data() const
Definition BLI_span.hh:215
constexpr Span()=default
int64_t size_
Definition BLI_span.hh:86
constexpr int64_t size() const
Definition BLI_span.hh:252
std::optional< T > get_if_single() const
IndexRange index_range() const
VArrayCommon(std::shared_ptr< const VArrayImpl< T > > impl)
void materialize(MutableSpan< T > r_span) const
T operator[](const int64_t index) const
T last(const int64_t n=0) const
VArrayCommon(const VArrayImpl< T > *impl)
void copy_from(const VArrayCommon &other)
void materialize_compressed_to_uninitialized(const IndexMask &mask, MutableSpan< T > r_span) const
VArrayCommon(const VArrayCommon &other)
const VArrayImpl< T > * impl_from_storage() const
const VArrayImpl< T > * impl_
void materialize(const IndexMask &mask, MutableSpan< T > r_span) const
VArrayCommon(VArrayCommon &&other) noexcept
void move_from(VArrayCommon &&other) noexcept
T get(const int64_t index) const
void materialize_to_uninitialized(const IndexMask &mask, MutableSpan< T > r_span) const
const VArrayImpl< T > * get_implementation() const
bool try_assign_GVArray(GVArray &varray) const
void materialize_to_uninitialized(MutableSpan< T > r_span) const
void materialize_compressed(const IndexMask &mask, MutableSpan< T > r_span) const
CommonVArrayInfo common_info() const
Span< T > get_internal_span() const
void emplace(Args &&...args)
Any< blender::detail::VArrayAnyExtraInfo< T >, 24, 8 > Storage
VArrayImpl_For_DerivedSpan(const MutableSpan< StructT > data)
VArrayImpl_For_Func(const int64_t size, GetFunc get_func)
void materialize_compressed(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Single(T value, const int64_t size)
void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
CommonVArrayInfo common_info() const override
T get(const int64_t) const override
void materialize(const IndexMask &mask, T *dst) const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Span_final(const Span< T > data)
CommonVArrayInfo common_info() const override
void set(const int64_t index, T value) final
VArrayImpl_For_Span(const int64_t size)
void materialize_compressed(const IndexMask &mask, T *dst) const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const override
void materialize(const IndexMask &mask, T *dst) const override
T get(const int64_t index) const final
void materialize_to_uninitialized(const IndexMask &mask, T *dst) const override
VArrayImpl_For_Span(const MutableSpan< T > data)
virtual void materialize_compressed(const IndexMask &mask, T *dst) const
virtual bool try_assign_GVArray(GVArray &) const
virtual void materialize_compressed_to_uninitialized(const IndexMask &mask, T *dst) const
virtual void materialize_to_uninitialized(const IndexMask &mask, T *dst) const
virtual CommonVArrayInfo common_info() const
virtual void materialize(const IndexMask &mask, T *dst) const
virtual T get(int64_t index) const =0
VArrayImpl(const int64_t size)
virtual ~VArrayImpl()=default
VArrayRef(const VArray< T > &ref)
T operator[](const int64_t index) const
VArraySpan(VArray< T > &&varray)
VArraySpan(VArraySpan &&other)
VArraySpan(const VArray< T > &varray)
VArraySpan & operator=(VArraySpan &&other)
VArray(const VArrayImpl< T > *impl)
VArray(const VArray &other)=default
VArray(varray_tag::single, T value, const int64_t size)
static VArray ForDerivedSpan(Span< StructT > values)
VArray(VArray &&other) noexcept=default
VArray & operator=(const VArray &other)
static VArray ForContainer(ContainerT container)
VArray(varray_tag::span, Span< T > span)
VArray(std::shared_ptr< const VArrayImpl< T > > impl)
static VArray ForSingle(T value, const int64_t size)
static VArray For(Args &&...args)
static VArray ForSpan(Span< T > values)
VArray & operator=(VArray &&other) noexcept
static VArray ForFunc(const int64_t size, GetFunc get_func)
VArray()=default
virtual void set(int64_t index, T value)=0
virtual bool try_assign_GVMutableArray(GVMutableArray &) const
virtual void set_all(Span< T > src)
void set(const int64_t index, T value)
VMutableArray(std::shared_ptr< const VMutableArrayImpl< T > > impl)
static VMutableArray ForDerivedSpan(MutableSpan< StructT > values)
VMutableArray & operator=(const VMutableArray &other)
static VMutableArray ForContainer(ContainerT container)
static VMutableArray ForSpan(MutableSpan< T > values)
static VMutableArray For(Args &&...args)
bool try_assign_GVMutableArray(GVMutableArray &varray) const
VMutableArray & operator=(VMutableArray &&other) noexcept
VMutableArray(VMutableArray &&other) noexcept=default
VMutableArray(const VMutableArray &other)=default
MutableSpan< T > get_internal_span() const
VMutableArray(const VMutableArrayImpl< T > *impl)
void set_all(Span< T > src)
uint pos
#define this
#define public
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define T
void print_mutable_varray_span_warning()
constexpr bool is_same_any_v
void devirtualize_varray(const VArray< T > &varray, const Func &func, bool enable=true)
void devirtualize_varray2(const VArray< T1 > &varray1, const VArray< T2 > &varray2, const Func &func, bool enable=true)
static constexpr bool is_VArray_v
void initialized_fill_n(T *dst, int64_t n, const T &value)
bool call_with_devirtualized_parameters(const std::tuple< Devirtualizers... > &devis, const Fn &fn)
static constexpr bool is_VMutableArray_v
void uninitialized_fill_n(T *dst, int64_t n, const T &value)
void initialized_copy_n(const T *src, int64_t n, T *dst)
constexpr bool is_trivial_extended_v
CommonVArrayInfo(const Type _type, const bool _may_have_ownership, const void *_data)
bool devirtualize(const Fn &fn) const
static constexpr VArrayAnyExtraInfo get()
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4227