Blender V4.5
generic_virtual_array.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <iostream>
10
12
13namespace blender {
14
15/* -------------------------------------------------------------------- */
18
19void GVArrayImpl::materialize(const IndexMask &mask, void *dst) const
20{
21 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
22 void *elem_dst = POINTER_OFFSET(dst, type_->size * i);
23 this->get(i, elem_dst);
24 });
25}
26
28{
29 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
30 void *elem_dst = POINTER_OFFSET(dst, type_->size * i);
31 this->get_to_uninitialized(i, elem_dst);
32 });
33}
34
36{
37 mask.foreach_index_optimized<int64_t>([&](const int64_t i, const int64_t pos) {
38 void *elem_dst = POINTER_OFFSET(dst, type_->size * pos);
39 this->get(i, elem_dst);
40 });
41}
42
44{
45 mask.foreach_index_optimized<int64_t>([&](const int64_t i, const int64_t pos) {
46 void *elem_dst = POINTER_OFFSET(dst, type_->size * pos);
47 this->get_to_uninitialized(i, elem_dst);
48 });
49}
50
51void GVArrayImpl::get(const int64_t index, void *r_value) const
52{
53 type_->destruct(r_value);
54 this->get_to_uninitialized(index, r_value);
55}
56
58{
59 return {};
60}
61
62bool GVArrayImpl::try_assign_VArray(void * /*varray*/) const
63{
64 return false;
65}
66
68
69/* -------------------------------------------------------------------- */
72
73void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
74{
76 type_->copy_construct(value, buffer);
77 this->set_by_move(index, buffer);
78 type_->destruct(buffer);
79}
80
81void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
82{
83 this->set_by_move(index, value);
84 type_->destruct(value);
85}
86
87void GVMutableArrayImpl::set_all(const void *src)
88{
89 const CommonVArrayInfo info = this->common_info();
91 type_->copy_assign_n(src, const_cast<void *>(info.data), size_);
92 }
93 else {
94 for (int64_t i : IndexRange(size_)) {
95 this->set_by_copy(i, POINTER_OFFSET(src, type_->size * i));
96 }
97 }
98}
99
100void GVMutableArray::fill(const void *value)
101{
102 const CommonVArrayInfo info = this->common_info();
104 this->type().fill_assign_n(value, const_cast<void *>(info.data), this->size());
105 }
106 else {
107 for (int64_t i : IndexRange(this->size())) {
108 this->set_by_copy(i, value);
109 }
110 }
111}
112
114{
115 return false;
116}
117
119
120/* -------------------------------------------------------------------- */
123
124void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
125{
126 type_->copy_assign(POINTER_OFFSET(data_, element_size_ * index), r_value);
127}
128
129void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
130{
131 type_->copy_construct(POINTER_OFFSET(data_, element_size_ * index), r_value);
132}
133
134void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value)
135{
136 type_->copy_assign(value, POINTER_OFFSET(data_, element_size_ * index));
137}
138
139void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value)
140{
141 type_->move_construct(value, POINTER_OFFSET(data_, element_size_ * index));
142}
143
145{
146 type_->relocate_assign(value, POINTER_OFFSET(data_, element_size_ * index));
147}
148
153
155{
156 type_->copy_assign_indices(data_, dst, mask);
157}
158
160{
161 type_->copy_construct_indices(data_, dst, mask);
162}
163
165{
166 type_->copy_assign_compressed(data_, dst, mask);
167}
168
170 void *dst) const
171{
172 type_->copy_construct_compressed(data_, dst, mask);
173}
174
176
177/* -------------------------------------------------------------------- */
180
181/* Generic virtual array where each element has the same value. The value is not owned. */
182
183void GVArrayImpl_For_SingleValueRef::get(const int64_t /*index*/, void *r_value) const
184{
185 type_->copy_assign(value_, r_value);
186}
188 void *r_value) const
189{
190 type_->copy_construct(value_, r_value);
191}
192
197
199{
200 type_->fill_assign_indices(value_, dst, mask);
201}
202
204 void *dst) const
205{
206 type_->fill_construct_indices(value_, dst, mask);
207}
208
210{
211 type_->fill_assign_n(value_, dst, mask.size());
212}
213
215 void *dst) const
216{
217 type_->fill_construct_n(value_, dst, mask.size());
218}
219
221
222/* -------------------------------------------------------------------- */
225
226/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
229 NonMovable {
230 public:
231 GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
233 {
234 value_ = MEM_mallocN_aligned(type.size, type.alignment, __func__);
235 type.copy_construct(value, (void *)value_);
236 }
237
239 {
240 type_->destruct(const_cast<void *>(value_));
241 MEM_freeN(const_cast<void *>(value_));
242 }
243};
244
246
247/* -------------------------------------------------------------------- */
250
255template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public GVArrayImpl {
256 private:
258
259 public:
261 const int64_t size,
262 const void *value)
264 {
265 BLI_assert(type.is_trivial);
266 BLI_assert(type.alignment <= 8);
267 BLI_assert(type.size <= BufferSize);
268 type.copy_construct(value, &buffer_);
269 }
270
271 private:
272 void get(const int64_t index, void *r_value) const final
273 {
274 this->get_to_uninitialized(index, r_value);
275 }
276 void get_to_uninitialized(const int64_t /*index*/, void *r_value) const final
277 {
278 memcpy(r_value, &buffer_, type_->size);
279 }
280
281 void materialize(const IndexMask &mask, void *dst) const final
282 {
283 this->materialize_to_uninitialized(mask, dst);
284 }
285 void materialize_to_uninitialized(const IndexMask &mask, void *dst) const final
286 {
287 type_->fill_construct_indices(buffer_, dst, mask);
288 }
289 void materialize_compressed(const IndexMask &mask, void *dst) const final
290 {
291 this->materialize_compressed_to_uninitialized(mask, dst);
292 }
293 void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const final
294 {
295 type_->fill_construct_n(buffer_, dst, mask.size());
296 }
297
298 CommonVArrayInfo common_info() const final
299 {
300 return CommonVArrayInfo{CommonVArrayInfo::Type::Single, true, &buffer_};
301 }
302};
303
305
306/* -------------------------------------------------------------------- */
309
310GVArraySpan::GVArraySpan() = default;
311
313 : GSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray))
314{
315 if (!varray_) {
316 return;
317 }
318
319 size_ = varray_.size();
320 const CommonVArrayInfo info = varray_.common_info();
322 data_ = info.data;
323 }
324 else {
325 owned_data_ = MEM_mallocN_aligned(type_->size * size_, type_->alignment, __func__);
326 varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
327 data_ = owned_data_;
328 }
329}
330
332 : GSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_)
333{
334 if (!varray_) {
335 return;
336 }
337
338 size_ = varray_.size();
339 const CommonVArrayInfo info = varray_.common_info();
341 data_ = info.data;
342 }
343 else {
344 data_ = owned_data_;
345 }
346 other.owned_data_ = nullptr;
347 other.data_ = nullptr;
348 other.size_ = 0;
349}
350
352{
353 if (owned_data_ != nullptr) {
354 type_->destruct_n(owned_data_, size_);
355 MEM_freeN(owned_data_);
356 }
357}
358
360{
361 if (this == &other) {
362 return *this;
363 }
364 std::destroy_at(this);
365 new (this) GVArraySpan(std::move(other));
366 return *this;
367}
368
370
371/* -------------------------------------------------------------------- */
374
376
378 : GMutableSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray))
379{
380 if (!varray_) {
381 return;
382 }
383 size_ = varray_.size();
384 const CommonVArrayInfo info = varray_.common_info();
386 data_ = const_cast<void *>(info.data);
387 }
388 else {
389 owned_data_ = MEM_mallocN_aligned(type_->size * size_, type_->alignment, __func__);
390 if (copy_values_to_span) {
391 varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
392 }
393 else {
394 type_->default_construct_n(owned_data_, size_);
395 }
396 data_ = owned_data_;
397 }
398}
399
401 : GMutableSpan(other.type_ptr()),
402 varray_(std::move(other.varray_)),
403 owned_data_(other.owned_data_),
404 show_not_saved_warning_(other.show_not_saved_warning_)
405{
406 if (!varray_) {
407 return;
408 }
409 size_ = varray_.size();
410 const CommonVArrayInfo info = varray_.common_info();
412 data_ = const_cast<void *>(info.data);
413 }
414 else {
415 data_ = owned_data_;
416 }
417 other.owned_data_ = nullptr;
418 other.data_ = nullptr;
419 other.size_ = 0;
420}
421
423{
424 if (varray_) {
425 if (show_not_saved_warning_) {
426 if (!save_has_been_called_) {
427 std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n";
428 }
429 }
430 }
431 if (owned_data_ != nullptr) {
432 type_->destruct_n(owned_data_, size_);
433 MEM_freeN(owned_data_);
434 }
435}
436
438{
439 if (this == &other) {
440 return *this;
441 }
442 std::destroy_at(this);
443 new (this) GMutableVArraySpan(std::move(other));
444 return *this;
445}
446
448{
449 save_has_been_called_ = true;
450 if (data_ != owned_data_) {
451 return;
452 }
453 varray_.set_all(owned_data_);
454}
455
457{
458 show_not_saved_warning_ = false;
459}
460
462{
463 return varray_;
464}
465
467
468/* -------------------------------------------------------------------- */
471
473 protected:
477
478 public:
480 : GVArrayImpl(varray.type(), slice.size()),
481 varray_(std::move(varray)),
482 offset_(slice.start()),
483 slice_(slice)
484 {
485 BLI_assert(slice.one_after_last() <= varray_.size());
486 }
487
488 void get(const int64_t index, void *r_value) const override
489 {
490 varray_.get(index + offset_, r_value);
491 }
492
493 void get_to_uninitialized(const int64_t index, void *r_value) const override
494 {
495 varray_.get_to_uninitialized(index + offset_, r_value);
496 }
497
499 {
500 const CommonVArrayInfo internal_info = varray_.common_info();
501 switch (internal_info.type) {
503 return {};
504 }
507 internal_info.may_have_ownership,
508 POINTER_OFFSET(internal_info.data, type_->size * offset_));
509 }
511 return internal_info;
512 }
513 }
515 return {};
516 }
517
518 void materialize(const IndexMask &mask, void *dst) const final
519 {
520 IndexMaskMemory memory;
521 const IndexMask shifted_mask = mask.shift(offset_, memory);
522 void *shifted_dst = POINTER_OFFSET(dst, -offset_ * type_->size);
523 varray_.materialize(shifted_mask, shifted_dst);
524 }
525 void materialize_to_uninitialized(const IndexMask &mask, void *dst) const final
526 {
527 IndexMaskMemory memory;
528 const IndexMask shifted_mask = mask.shift(offset_, memory);
529 void *shifted_dst = POINTER_OFFSET(dst, -offset_ * type_->size);
530 varray_.materialize_to_uninitialized(shifted_mask, shifted_dst);
531 }
532 void materialize_compressed(const IndexMask &mask, void *dst) const final
533 {
534 IndexMaskMemory memory;
535 const IndexMask shifted_mask = mask.shift(offset_, memory);
536 varray_.materialize_compressed(shifted_mask, dst);
537 }
538 void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const override
539 {
540 IndexMaskMemory memory;
541 const IndexMask shifted_mask = mask.shift(offset_, memory);
542 varray_.materialize_compressed_to_uninitialized(shifted_mask, dst);
543 }
544};
545
547
548/* -------------------------------------------------------------------- */
551
556
557GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
558{
559 impl_ = this->impl_from_storage();
560 other.storage_.reset();
561 other.impl_ = nullptr;
562}
563
565{
566 storage_ = impl_;
567}
568
569GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
570{
571 if (impl) {
572 storage_ = std::move(impl);
573 }
574}
575
577
578void GVArrayCommon::materialize(void *dst) const
579{
580 this->materialize(IndexMask(impl_->size()), dst);
581}
582
583void GVArrayCommon::materialize(const IndexMask &mask, void *dst) const
584{
585 impl_->materialize(mask, dst);
586}
587
589{
590 this->materialize_to_uninitialized(IndexMask(impl_->size()), dst);
591}
592
594{
595 BLI_assert(mask.min_array_size() <= impl_->size());
596 impl_->materialize_to_uninitialized(mask, dst);
597}
598
600{
601 impl_->materialize_compressed(mask, dst);
602}
603
605{
606 impl_->materialize_compressed_to_uninitialized(mask, dst);
607}
608
610{
611 if (this == &other) {
612 return;
613 }
614 storage_ = other.storage_;
615 impl_ = this->impl_from_storage();
616}
617
619{
620 if (this == &other) {
621 return;
622 }
623 storage_ = std::move(other.storage_);
624 impl_ = this->impl_from_storage();
625 other.storage_.reset();
626 other.impl_ = nullptr;
627}
628
630{
631 const CommonVArrayInfo info = impl_->common_info();
632 return info.type == CommonVArrayInfo::Type::Span;
633}
634
636{
637 BLI_assert(this->is_span());
638 const CommonVArrayInfo info = impl_->common_info();
639 return GSpan(this->type(), info.data, this->size());
640}
641
643{
644 const CommonVArrayInfo info = impl_->common_info();
646}
647
648void GVArrayCommon::get_internal_single(void *r_value) const
649{
650 BLI_assert(this->is_single());
651 const CommonVArrayInfo info = impl_->common_info();
652 this->type().copy_assign(info.data, r_value);
653}
654
656{
657 impl_->type().default_construct(r_value);
658 this->get_internal_single(r_value);
659}
660
662{
663 if (!storage_.has_value()) {
664 return nullptr;
665 }
666 return storage_.extra_info().get_varray(storage_.get());
667}
668
670{
671 return IndexRange(this->size());
672}
673
675
676/* -------------------------------------------------------------------- */
679
680GVArray::GVArray(const GVArray &other) = default;
681
682GVArray::GVArray(GVArray &&other) noexcept = default;
683
685
686GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl)) {}
687
688GVArray::GVArray(varray_tag::single /*tag*/, const CPPType &type, int64_t size, const void *value)
689{
690 if (type.is_trivial && type.size <= 16 && type.alignment <= 8) {
692 }
693 else {
694 this->emplace<GVArrayImpl_For_SingleValue>(type, size, value);
695 }
696}
697
698GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
699{
700 return GVArray(varray_tag::single{}, type, size, value);
701}
702
703GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
704{
705 return GVArray(varray_tag::single_ref{}, type, size, value);
706}
707
709{
710 return GVArray::ForSingleRef(type, size, type.default_value());
711}
712
714{
715 return GVArray(varray_tag::span{}, span);
716}
717
719 protected:
721
722 public:
724 : GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array))
725 {
726 }
727};
728
733
738
740{
741 const CommonVArrayInfo info = this->common_info();
743 return GVArray::ForSingle(this->type(), slice.size(), info.data);
744 }
745 /* Need to check for ownership, because otherwise the referenced data can be destructed when
746 * #this is destructed. */
748 return GVArray::ForSpan(GSpan(this->type(), info.data, this->size()).slice(slice));
749 }
751}
752
754{
755 this->copy_from(other);
756 return *this;
757}
758
760{
761 this->move_from(std::move(other));
762 return *this;
763}
764
766
767/* -------------------------------------------------------------------- */
770
771GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
772GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
773
775
776GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
777 : GVArrayCommon(std::move(impl))
778{
779}
780
785
786GVMutableArray::operator GVArray() const &
787{
788 GVArray varray;
789 varray.copy_from(*this);
790 return varray;
791}
792
793GVMutableArray::operator GVArray() && noexcept
794{
795 GVArray varray;
796 varray.move_from(std::move(*this));
797 return varray;
798}
799
801{
802 this->copy_from(other);
803 return *this;
804}
805
807{
808 this->move_from(std::move(other));
809 return *this;
810}
811
813{
814 return this->get_impl();
815}
816
817void GVMutableArray::set_all(const void *src)
818{
819 this->get_impl()->set_all(src);
820}
821
823{
824 BLI_assert(this->is_span());
825 const CommonVArrayInfo info = impl_->common_info();
826 return GMutableSpan(this->type(), const_cast<void *>(info.data), this->size());
827}
828
830
832{
834}
835
837{
838 return CommonVArrayInfo(CommonVArrayInfo::Type::Single, false, value_);
839}
840
841} // namespace blender
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define final(a, b, c)
Definition BLI_hash.h:19
#define POINTER_OFFSET(v, ofs)
long long int int64_t
void fill_assign_n(const void *value, void *dst, int64_t n) const
void copy_assign(const void *src, void *dst) const
const CPPType * type_ptr() const
const CPPType & type() const
const GVMutableArray & varray() const
GMutableVArraySpan & operator=(GMutableVArraySpan &&other)
const CPPType * type_ptr() const
const CPPType & type() const
GSpan slice(const int64_t start, int64_t size) const
GSpan()=default
const CPPType * type_
CommonVArrayInfo common_info() const
void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const
const GVArrayImpl * impl_from_storage() const
void copy_from(const GVArrayCommon &other)
void move_from(GVArrayCommon &&other) noexcept
void materialize(void *dst) const
void get_internal_single_to_uninitialized(void *r_value) const
void materialize_to_uninitialized(void *dst) const
void get(int64_t index, void *r_value) const
void materialize_compressed(const IndexMask &mask, void *dst) const
void get_internal_single(void *r_value) const
CommonVArrayInfo common_info() const override
void set_by_move(int64_t index, void *value) override
void get_to_uninitialized(int64_t index, void *r_value) const override
void materialize_compressed(const IndexMask &mask, void *dst) const override
void materialize_to_uninitialized(const IndexMask &mask, void *dst) const override
void set_by_relocate(int64_t index, void *value) override
void materialize(const IndexMask &mask, void *dst) const override
GVArrayImpl_For_GSpan(const GMutableSpan span)
void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const override
void get(int64_t index, void *r_value) const override
void set_by_copy(int64_t index, const void *value) override
void get(const int64_t index, void *r_value) const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const override
void materialize_compressed(const IndexMask &mask, void *dst) const override
void materialize_to_uninitialized(const IndexMask &mask, void *dst) const override
void materialize(const IndexMask &mask, void *dst) const override
void get_to_uninitialized(const int64_t index, void *r_value) const override
CommonVArrayInfo common_info() const override
GVArrayImpl_For_SingleValueRef(const CPPType &type, const int64_t size, const void *value)
GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
CommonVArrayInfo common_info() const override
void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const override
void materialize(const IndexMask &mask, void *dst) const final
void materialize_compressed(const IndexMask &mask, void *dst) const final
void get(const int64_t index, void *r_value) const override
void materialize_to_uninitialized(const IndexMask &mask, void *dst) const final
GVArrayImpl_For_SlicedGVArray(GVArray varray, const IndexRange slice)
void get_to_uninitialized(const int64_t index, void *r_value) const override
GVArrayImpl_For_SmallTrivialSingleValue(const CPPType &type, const int64_t size, const void *value)
virtual void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const
virtual void materialize(const IndexMask &mask, void *dst) const
virtual void get_to_uninitialized(int64_t index, void *r_value) const =0
virtual void materialize_compressed(const IndexMask &mask, void *dst) const
virtual void get(int64_t index, void *r_value) const
virtual bool try_assign_VArray(void *varray) const
GVArrayImpl(const CPPType &type, int64_t size)
virtual CommonVArrayInfo common_info() const
const CPPType & type() const
virtual void materialize_to_uninitialized(const IndexMask &mask, void *dst) const
GVArraySpan & operator=(GVArraySpan &&other)
GVArray slice(IndexRange slice) const
static GVArray ForEmpty(const CPPType &type)
static GVArray ForGArray(GArray<> array)
GVArray()=default
static GVArray ForSingleDefault(const CPPType &type, int64_t size)
GVArray & operator=(const GVArray &other)
static GVArray For(Args &&...args)
static GVArray ForSingleRef(const CPPType &type, int64_t size, const void *value)
static GVArray ForSpan(GSpan span)
static GVArray ForSingle(const CPPType &type, int64_t size, const void *value)
virtual bool try_assign_VMutableArray(void *varray) const
virtual void set_all(const void *src)
virtual void set_by_copy(int64_t index, const void *value)
virtual void set_by_relocate(int64_t index, void *value)
virtual void set_by_move(int64_t index, void *value)=0
void set_all(const void *src)
void set_by_copy(int64_t index, const void *value)
GVMutableArrayImpl * get_implementation() const
GMutableSpan get_internal_span() const
GVMutableArray & operator=(const GVMutableArray &other)
void fill(const void *value)
static GVMutableArray ForSpan(GMutableSpan span)
static GVMutableArray For(Args &&...args)
constexpr int64_t one_after_last() const
constexpr int64_t size() const
NonCopyable(const NonCopyable &other)=delete
NonMovable(NonMovable &&other)=delete
uint pos
#define this
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:138
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
i
Definition text_draw.cc:230