Blender V4.3
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
5#include <iostream>
6
8
9namespace blender {
10
11/* -------------------------------------------------------------------- */
15void GVArrayImpl::materialize(const IndexMask &mask, void *dst) const
16{
17 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
18 void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
19 this->get(i, elem_dst);
20 });
21}
22
23void GVArrayImpl::materialize_to_uninitialized(const IndexMask &mask, void *dst) const
24{
25 mask.foreach_index_optimized<int64_t>([&](const int64_t i) {
26 void *elem_dst = POINTER_OFFSET(dst, type_->size() * i);
27 this->get_to_uninitialized(i, elem_dst);
28 });
29}
30
31void GVArrayImpl::materialize_compressed(const IndexMask &mask, void *dst) const
32{
33 mask.foreach_index_optimized<int64_t>([&](const int64_t i, const int64_t pos) {
34 void *elem_dst = POINTER_OFFSET(dst, type_->size() * pos);
35 this->get(i, elem_dst);
36 });
37}
38
40{
41 mask.foreach_index_optimized<int64_t>([&](const int64_t i, const int64_t pos) {
42 void *elem_dst = POINTER_OFFSET(dst, type_->size() * pos);
43 this->get_to_uninitialized(i, elem_dst);
44 });
45}
46
47void GVArrayImpl::get(const int64_t index, void *r_value) const
48{
49 type_->destruct(r_value);
50 this->get_to_uninitialized(index, r_value);
51}
52
54{
55 return {};
56}
57
58bool GVArrayImpl::try_assign_VArray(void * /*varray*/) const
59{
60 return false;
61}
62
65/* -------------------------------------------------------------------- */
69void GVMutableArrayImpl::set_by_copy(const int64_t index, const void *value)
70{
72 type_->copy_construct(value, buffer);
73 this->set_by_move(index, buffer);
74 type_->destruct(buffer);
75}
76
77void GVMutableArrayImpl::set_by_relocate(const int64_t index, void *value)
78{
79 this->set_by_move(index, value);
80 type_->destruct(value);
81}
82
83void GVMutableArrayImpl::set_all(const void *src)
84{
85 const CommonVArrayInfo info = this->common_info();
87 type_->copy_assign_n(src, const_cast<void *>(info.data), size_);
88 }
89 else {
90 for (int64_t i : IndexRange(size_)) {
91 this->set_by_copy(i, POINTER_OFFSET(src, type_->size() * i));
92 }
93 }
94}
95
96void GVMutableArray::fill(const void *value)
97{
98 const CommonVArrayInfo info = this->common_info();
100 this->type().fill_assign_n(value, const_cast<void *>(info.data), this->size());
101 }
102 else {
103 for (int64_t i : IndexRange(this->size())) {
104 this->set_by_copy(i, value);
105 }
106 }
107}
108
110{
111 return false;
112}
113
116/* -------------------------------------------------------------------- */
120void GVArrayImpl_For_GSpan::get(const int64_t index, void *r_value) const
121{
123}
124
125void GVArrayImpl_For_GSpan::get_to_uninitialized(const int64_t index, void *r_value) const
126{
128}
129
130void GVArrayImpl_For_GSpan::set_by_copy(const int64_t index, const void *value)
131{
133}
134
135void GVArrayImpl_For_GSpan::set_by_move(const int64_t index, void *value)
136{
138}
139
141{
143}
144
149
150void GVArrayImpl_For_GSpan::materialize(const IndexMask &mask, void *dst) const
151{
152 type_->copy_assign_indices(data_, dst, mask);
153}
154
156{
158}
159
161{
163}
164
170
173/* -------------------------------------------------------------------- */
177/* Generic virtual array where each element has the same value. The value is not owned. */
178
179void GVArrayImpl_For_SingleValueRef::get(const int64_t /*index*/, void *r_value) const
180{
181 type_->copy_assign(value_, r_value);
182}
184 void *r_value) const
185{
186 type_->copy_construct(value_, r_value);
187}
188
193
195{
196 type_->fill_assign_indices(value_, dst, mask);
197}
198
200 void *dst) const
201{
203}
204
206{
207 type_->fill_assign_n(value_, dst, mask.size());
208}
209
211 void *dst) const
212{
213 type_->fill_construct_n(value_, dst, mask.size());
214}
215
218/* -------------------------------------------------------------------- */
222/* Same as GVArrayImpl_For_SingleValueRef, but the value is owned. */
225 NonMovable {
226 public:
227 GVArrayImpl_For_SingleValue(const CPPType &type, const int64_t size, const void *value)
229 {
230 value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
231 type.copy_construct(value, (void *)value_);
232 }
233
235 {
236 type_->destruct((void *)value_);
237 MEM_freeN((void *)value_);
238 }
239};
240
243/* -------------------------------------------------------------------- */
251template<int BufferSize> class GVArrayImpl_For_SmallTrivialSingleValue : public GVArrayImpl {
252 private:
254
255 public:
257 const int64_t size,
258 const void *value)
259 : GVArrayImpl(type, size)
260 {
261 BLI_assert(type.is_trivial());
262 BLI_assert(type.alignment() <= 8);
263 BLI_assert(type.size() <= BufferSize);
264 type.copy_construct(value, &buffer_);
265 }
266
267 private:
268 void get(const int64_t index, void *r_value) const final
269 {
270 this->get_to_uninitialized(index, r_value);
271 }
272 void get_to_uninitialized(const int64_t /*index*/, void *r_value) const final
273 {
274 memcpy(r_value, &buffer_, type_->size());
275 }
276
277 void materialize(const IndexMask &mask, void *dst) const final
278 {
279 this->materialize_to_uninitialized(mask, dst);
280 }
281 void materialize_to_uninitialized(const IndexMask &mask, void *dst) const final
282 {
283 type_->fill_construct_indices(buffer_, dst, mask);
284 }
285 void materialize_compressed(const IndexMask &mask, void *dst) const final
286 {
287 this->materialize_compressed_to_uninitialized(mask, dst);
288 }
289 void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const final
290 {
291 type_->fill_construct_n(buffer_, dst, mask.size());
292 }
293
294 CommonVArrayInfo common_info() const final
295 {
296 return CommonVArrayInfo{CommonVArrayInfo::Type::Single, true, &buffer_};
297 }
298};
299
302/* -------------------------------------------------------------------- */
306GVArraySpan::GVArraySpan() = default;
307
309 : GSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray))
310{
311 if (!varray_) {
312 return;
313 }
314
315 size_ = varray_.size();
316 const CommonVArrayInfo info = varray_.common_info();
318 data_ = info.data;
319 }
320 else {
321 owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__);
322 varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
323 data_ = owned_data_;
324 }
325}
326
328 : GSpan(other.type_ptr()), varray_(std::move(other.varray_)), owned_data_(other.owned_data_)
329{
330 if (!varray_) {
331 return;
332 }
333
334 size_ = varray_.size();
335 const CommonVArrayInfo info = varray_.common_info();
337 data_ = info.data;
338 }
339 else {
340 data_ = owned_data_;
341 }
342 other.owned_data_ = nullptr;
343 other.data_ = nullptr;
344 other.size_ = 0;
345}
346
348{
349 if (owned_data_ != nullptr) {
350 type_->destruct_n(owned_data_, size_);
351 MEM_freeN(owned_data_);
352 }
353}
354
356{
357 if (this == &other) {
358 return *this;
359 }
360 std::destroy_at(this);
361 new (this) GVArraySpan(std::move(other));
362 return *this;
363}
364
367/* -------------------------------------------------------------------- */
372
373GMutableVArraySpan::GMutableVArraySpan(GVMutableArray varray, const bool copy_values_to_span)
374 : GMutableSpan(varray ? &varray.type() : nullptr), varray_(std::move(varray))
375{
376 if (!varray_) {
377 return;
378 }
379 size_ = varray_.size();
380 const CommonVArrayInfo info = varray_.common_info();
382 data_ = const_cast<void *>(info.data);
383 }
384 else {
385 owned_data_ = MEM_mallocN_aligned(type_->size() * size_, type_->alignment(), __func__);
386 if (copy_values_to_span) {
387 varray_.materialize_to_uninitialized(IndexRange(size_), owned_data_);
388 }
389 else {
390 type_->default_construct_n(owned_data_, size_);
391 }
392 data_ = owned_data_;
393 }
394}
395
397 : GMutableSpan(other.type_ptr()),
398 varray_(std::move(other.varray_)),
399 owned_data_(other.owned_data_),
400 show_not_saved_warning_(other.show_not_saved_warning_)
401{
402 if (!varray_) {
403 return;
404 }
405 size_ = varray_.size();
406 const CommonVArrayInfo info = varray_.common_info();
408 data_ = const_cast<void *>(info.data);
409 }
410 else {
411 data_ = owned_data_;
412 }
413 other.owned_data_ = nullptr;
414 other.data_ = nullptr;
415 other.size_ = 0;
416}
417
419{
420 if (varray_) {
421 if (show_not_saved_warning_) {
422 if (!save_has_been_called_) {
423 std::cout << "Warning: Call `save()` to make sure that changes persist in all cases.\n";
424 }
425 }
426 }
427 if (owned_data_ != nullptr) {
428 type_->destruct_n(owned_data_, size_);
429 MEM_freeN(owned_data_);
430 }
431}
432
434{
435 if (this == &other) {
436 return *this;
437 }
438 std::destroy_at(this);
439 new (this) GMutableVArraySpan(std::move(other));
440 return *this;
441}
442
444{
445 save_has_been_called_ = true;
446 if (data_ != owned_data_) {
447 return;
448 }
449 varray_.set_all(owned_data_);
450}
451
453{
454 show_not_saved_warning_ = false;
455}
456
458{
459 return varray_;
460}
461
464/* -------------------------------------------------------------------- */
469 protected:
473
474 public:
476 : GVArrayImpl(varray.type(), slice.size()),
477 varray_(std::move(varray)),
478 offset_(slice.start()),
479 slice_(slice)
480 {
482 }
483
484 void get(const int64_t index, void *r_value) const override
485 {
486 varray_.get(index + offset_, r_value);
487 }
488
489 void get_to_uninitialized(const int64_t index, void *r_value) const override
490 {
491 varray_.get_to_uninitialized(index + offset_, r_value);
492 }
493
495 {
496 const CommonVArrayInfo internal_info = varray_.common_info();
497 switch (internal_info.type) {
499 return {};
500 }
503 internal_info.may_have_ownership,
504 POINTER_OFFSET(internal_info.data, type_->size() * offset_));
505 }
507 return internal_info;
508 }
509 }
511 return {};
512 }
513
514 void materialize(const IndexMask &mask, void *dst) const final
515 {
516 IndexMaskMemory memory;
517 const IndexMask shifted_mask = mask.shift(offset_, memory);
518 void *shifted_dst = POINTER_OFFSET(dst, -offset_ * type_->size());
519 varray_.materialize(shifted_mask, shifted_dst);
520 }
521 void materialize_to_uninitialized(const IndexMask &mask, void *dst) const final
522 {
523 IndexMaskMemory memory;
524 const IndexMask shifted_mask = mask.shift(offset_, memory);
525 void *shifted_dst = POINTER_OFFSET(dst, -offset_ * type_->size());
526 varray_.materialize_to_uninitialized(shifted_mask, shifted_dst);
527 }
528 void materialize_compressed(const IndexMask &mask, void *dst) const final
529 {
530 IndexMaskMemory memory;
531 const IndexMask shifted_mask = mask.shift(offset_, memory);
532 varray_.materialize_compressed(shifted_mask, dst);
533 }
534 void materialize_compressed_to_uninitialized(const IndexMask &mask, void *dst) const override
535 {
536 IndexMaskMemory memory;
537 const IndexMask shifted_mask = mask.shift(offset_, memory);
539 }
540};
541
544/* -------------------------------------------------------------------- */
548GVArrayCommon::GVArrayCommon(const GVArrayCommon &other) : storage_(other.storage_)
549{
550 impl_ = this->impl_from_storage();
551}
552
553GVArrayCommon::GVArrayCommon(GVArrayCommon &&other) noexcept : storage_(std::move(other.storage_))
554{
555 impl_ = this->impl_from_storage();
556 other.storage_.reset();
557 other.impl_ = nullptr;
558}
559
564
565GVArrayCommon::GVArrayCommon(std::shared_ptr<const GVArrayImpl> impl) : impl_(impl.get())
566{
567 if (impl) {
568 storage_ = std::move(impl);
569 }
570}
571
573
574void GVArrayCommon::materialize(void *dst) const
575{
576 this->materialize(IndexMask(impl_->size()), dst);
577}
578
579void GVArrayCommon::materialize(const IndexMask &mask, void *dst) const
580{
581 impl_->materialize(mask, dst);
582}
583
588
590{
591 BLI_assert(mask.min_array_size() <= impl_->size());
593}
594
595void GVArrayCommon::materialize_compressed(const IndexMask &mask, void *dst) const
596{
597 impl_->materialize_compressed(mask, dst);
598}
599
604
606{
607 if (this == &other) {
608 return;
609 }
610 storage_ = other.storage_;
611 impl_ = this->impl_from_storage();
612}
613
615{
616 if (this == &other) {
617 return;
618 }
619 storage_ = std::move(other.storage_);
620 impl_ = this->impl_from_storage();
621 other.storage_.reset();
622 other.impl_ = nullptr;
623}
624
626{
627 const CommonVArrayInfo info = impl_->common_info();
628 return info.type == CommonVArrayInfo::Type::Span;
629}
630
632{
633 BLI_assert(this->is_span());
634 const CommonVArrayInfo info = impl_->common_info();
635 return GSpan(this->type(), info.data, this->size());
636}
637
639{
640 const CommonVArrayInfo info = impl_->common_info();
642}
643
644void GVArrayCommon::get_internal_single(void *r_value) const
645{
646 BLI_assert(this->is_single());
647 const CommonVArrayInfo info = impl_->common_info();
648 this->type().copy_assign(info.data, r_value);
649}
650
652{
653 impl_->type().default_construct(r_value);
654 this->get_internal_single(r_value);
655}
656
658{
659 if (!storage_.has_value()) {
660 return nullptr;
661 }
662 return storage_.extra_info().get_varray(storage_.get());
663}
664
666{
667 return IndexRange(this->size());
668}
669
672/* -------------------------------------------------------------------- */
676GVArray::GVArray(const GVArray &other) = default;
677
678GVArray::GVArray(GVArray &&other) noexcept = default;
679
681
682GVArray::GVArray(std::shared_ptr<const GVArrayImpl> impl) : GVArrayCommon(std::move(impl)) {}
683
684GVArray::GVArray(varray_tag::single /*tag*/, const CPPType &type, int64_t size, const void *value)
685{
686 if (type.is_trivial() && type.size() <= 16 && type.alignment() <= 8) {
688 }
689 else {
690 this->emplace<GVArrayImpl_For_SingleValue>(type, size, value);
691 }
692}
693
694GVArray GVArray::ForSingle(const CPPType &type, const int64_t size, const void *value)
695{
696 return GVArray(varray_tag::single{}, type, size, value);
697}
698
699GVArray GVArray::ForSingleRef(const CPPType &type, const int64_t size, const void *value)
700{
701 return GVArray(varray_tag::single_ref{}, type, size, value);
702}
703
705{
706 return GVArray::ForSingleRef(type, size, type.default_value());
707}
708
710{
711 return GVArray(varray_tag::span{}, span);
712}
713
715 protected:
717
718 public:
720 : GVArrayImpl_For_GSpan(array.as_mutable_span()), array_(std::move(array))
721 {
722 }
723};
724
729
731{
732 return GVArray::ForSpan(GSpan(type));
733}
734
736{
737 const CommonVArrayInfo info = this->common_info();
739 return GVArray::ForSingle(this->type(), slice.size(), info.data);
740 }
741 /* Need to check for ownership, because otherwise the referenced data can be destructed when
742 * #this is destructed. */
744 return GVArray::ForSpan(GSpan(this->type(), info.data, this->size()).slice(slice));
745 }
747}
748
750{
751 this->copy_from(other);
752 return *this;
753}
754
756{
757 this->move_from(std::move(other));
758 return *this;
759}
760
763/* -------------------------------------------------------------------- */
767GVMutableArray::GVMutableArray(const GVMutableArray &other) = default;
768GVMutableArray::GVMutableArray(GVMutableArray &&other) noexcept = default;
769
771
772GVMutableArray::GVMutableArray(std::shared_ptr<GVMutableArrayImpl> impl)
773 : GVArrayCommon(std::move(impl))
774{
775}
776
781
782GVMutableArray::operator GVArray() const &
783{
784 GVArray varray;
785 varray.copy_from(*this);
786 return varray;
787}
788
789GVMutableArray::operator GVArray() && noexcept
790{
791 GVArray varray;
792 varray.move_from(std::move(*this));
793 return varray;
794}
795
797{
798 this->copy_from(other);
799 return *this;
800}
801
803{
804 this->move_from(std::move(other));
805 return *this;
806}
807
809{
810 return this->get_impl();
811}
812
813void GVMutableArray::set_all(const void *src)
814{
815 this->get_impl()->set_all(src);
816}
817
819{
820 BLI_assert(this->is_span());
821 const CommonVArrayInfo info = impl_->common_info();
822 return GMutableSpan(this->type(), const_cast<void *>(info.data), this->size());
823}
824
827CommonVArrayInfo GVArrayImpl_For_GSpan_final::common_info() const
828{
830}
831
832CommonVArrayInfo GVArrayImpl_For_SingleValueRef_final::common_info() const
833{
834 return CommonVArrayInfo(CommonVArrayInfo::Type::Single, false, value_);
835}
836
837} // namespace blender
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
#define POINTER_OFFSET(v, ofs)
const RealExtraInfo & extra_info() const
Definition BLI_any.hh:375
bool has_value() const
Definition BLI_any.hh:255
void * get()
Definition BLI_any.hh:324
void default_construct_n(void *ptr, int64_t n) const
void destruct_n(void *ptr, int64_t n) const
void copy_assign_indices(const void *src, void *dst, const IndexMask &mask) const
void fill_assign_n(const void *value, void *dst, int64_t n) const
void fill_construct_indices(const void *value, void *dst, const IndexMask &mask) const
void copy_construct_indices(const void *src, void *dst, const IndexMask &mask) const
void fill_assign_indices(const void *value, void *dst, const IndexMask &mask) const
void fill_construct_n(const void *value, void *dst, int64_t n) const
void copy_construct_compressed(const void *src, void *dst, const IndexMask &mask) const
void copy_assign_n(const void *src, void *dst, int64_t n) const
void copy_construct(const void *src, void *dst) const
void destruct(void *ptr) const
int64_t size() const
int64_t alignment() const
void copy_assign(const void *src, void *dst) const
void move_construct(void *src, void *dst) const
void relocate_assign(void *src, void *dst) const
void default_construct(void *ptr) const
void copy_assign_compressed(const void *src, void *dst, const IndexMask &mask) const
const GVMutableArray & varray() const
GMutableVArraySpan & operator=(GMutableVArraySpan &&other)
GSpan slice(const int64_t start, int64_t size) const
const void * data_
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 get_to_uninitialized(int64_t index, void *r_value) const
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
virtual void materialize_compressed(const IndexMask &mask, void *dst) const override
virtual void materialize_to_uninitialized(const IndexMask &mask, void *dst) const override
void set_by_relocate(int64_t index, void *value) override
virtual void materialize(const IndexMask &mask, void *dst) const override
virtual 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_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
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
IndexMask shift(const int64_t offset, IndexMaskMemory &memory) const
void * MEM_mallocN_aligned(size_t len, size_t alignment, const char *str)
Definition mallocn.cc:110
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static IOCIOImpl * impl
Definition ocio_capi.cc:9
__int64 int64_t
Definition stdint.h:89