Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1//
2// Copyright 2025 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_EXEC_VDF_VECTOR_H
8#define PXR_EXEC_VDF_VECTOR_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/exec/vdf/api.h"
15#include "pxr/exec/vdf/boxedContainerTraits.h"
16#include "pxr/exec/vdf/mask.h"
17#include "pxr/exec/vdf/vectorAccessor.h"
18#include "pxr/exec/vdf/vectorImpl_Boxed.h"
19#include "pxr/exec/vdf/vectorImpl_Compressed.h"
20#include "pxr/exec/vdf/vectorImpl_Contiguous.h"
21#include "pxr/exec/vdf/vectorImpl_Empty.h"
22#include "pxr/exec/vdf/vectorImpl_Shared.h"
23#include "pxr/exec/vdf/vectorImpl_Single.h"
24
25#include "pxr/base/arch/hints.h"
28#include "pxr/base/vt/value.h"
29
30#include <iosfwd>
31#include <new>
32#include <type_traits>
33#include <typeinfo>
34#include <vector>
35
36PXR_NAMESPACE_OPEN_SCOPE
37
38template <typename T>
40
56{
57public:
58
61 VdfVector(const VdfVector &rhs)
62 {
63 // We need to new an empty impl because Clone() always expects
64 // a valid _data to clone into.
65 rhs._data.Get()->NewEmpty(0, &_data);
66 rhs._data.Get()->Clone(&_data);
67 }
68
72 const VdfVector &rhs,
73 const VdfMask &mask)
74 {
75 // CloneSubset expects valid _data to copy into, so first create
76 // an empty vector.
77 rhs._data.Get()->NewEmpty(0, &_data);
78
79 // If the mask is all ones, take advange of the potentially faster
80 // Clone() method.
81 if (mask.IsAllOnes()) {
82 rhs._data.Get()->Clone(&_data);
83 } else if (mask.IsAnySet()) {
84 rhs._data.Get()->CloneSubset(mask, &_data);
85 }
86 }
87
91 ConstructBoxedCopy
92 };
93
95 const VdfVector &rhs,
96 const VdfMask &mask,
98 {
99 if (rhs.GetSize() != mask.GetSize()) {
101 "size mismatch: rhs.GetSize() (%zu) != mask.GetSize() (%zu)",
102 rhs.GetSize(), mask.GetSize());
103 }
104
105 // Box expects valid _data to copy into, so first create an
106 // empty vector.
107 rhs._data.Get()->NewEmpty(0, &_data);
108 if (mask.IsAnySet()) {
109 rhs._data.Get()->Box(mask.GetBits(), &_data);
110 }
111 }
112
117 const VdfVector &rhs,
118 size_t size)
119 {
120 if (size == 0) {
121 rhs._data.Get()->NewEmpty(0, &_data);
122 } else if (size == 1){
123 rhs._data.Get()->NewSingle(&_data);
124 } else{
125 rhs._data.Get()->NewDense(size, &_data);
126 }
127 }
128
132 {
133 rhs._data.Get()->NewEmpty(0, &_data);
134 rhs._data.Get()->MoveInto(&_data);
135 }
136
140 {
141 _data.Destroy();
142 }
143
146 size_t GetSize() const { return _data.Get()->GetSize(); }
147
150 bool IsEmpty() const { return GetSize() == 0; }
151
154 size_t GetNumStoredElements() const
155 {
156 return _data.Get()->GetNumStoredElements();
157 }
158
161 template<typename TYPE>
162 void Set(TYPE &&data)
163 {
164 // We need to decay because TYPE is deduced as T& when l-values are
165 // passed and T may also be cv-qualified. This decayed type is what
166 // is held by the underlying vector impl that provides storage.
167 using T = typename std::decay<TYPE>::type;
168
169 _CheckType<T>();
170 _data.Destroy();
171 _data.New<Vdf_VectorImplSingle<T>>(std::forward<TYPE>(data));
172 }
173
176 template <typename TYPE>
178 {
179 _CheckType<TYPE>();
180 _data.Destroy();
181 _data.New<Vdf_VectorImplBoxed<TYPE>>(data);
182 }
183 // Unfortunately, we have to provide overloads for all combinations of
184 // const-qualification & reference category due to the unconstrained Set
185 // overload. Everything other than non-const rvalue reference gets
186 // copied.
187 //
188 template <typename TYPE>
189 void Set(Vdf_BoxedContainer<TYPE> &data)
190 {
191 const Vdf_BoxedContainer<TYPE> &cdata = data;
192 this->Set(cdata);
193 }
194 template <typename TYPE>
195 void Set(const Vdf_BoxedContainer<TYPE> &&data)
196 {
197 const Vdf_BoxedContainer<TYPE> &cdata = data;
198 this->Set(cdata);
199 }
200
203 template <typename TYPE>
205 {
206 _CheckType<TYPE>();
207 _data.Destroy();
208 _data.New<Vdf_VectorImplBoxed<TYPE>>(std::move(data));
209 }
210
217 template<typename TYPE>
218 void Resize(size_t size)
219 {
220 _CheckType<TYPE>();
221
222 _data.Destroy();
223
224 // Note that we never construct a compressed vector impl, here. The
225 // purpose of this function is to resize the vector to be able to
226 // accommodate all the data denoted in \p mask, but we do not support
227 // merging data into a compressed vector without first uncompressing.
228
229 if (size == 0)
230 _data.New< Vdf_VectorImplEmpty<TYPE> >(0);
231 else if (size == 1)
233 else
234 _data.New< Vdf_VectorImplContiguous<TYPE> >(size);
235 }
236
243 template<typename TYPE>
244 void Resize(const VdfMask::Bits &bits)
245 {
246 _CheckType<TYPE>();
247
248 _data.Destroy();
249
250 // Note that we never construct a compressed vector impl, here. The
251 // purpose of this function is to resize the vector to be able to
252 // accommodate all the data denoted in \p bits, but we do not support
253 // merging data into a compressed vector without first uncompressing.
254
255 const size_t size = bits.GetSize();
256
257 if (size == 0)
258 _data.New< Vdf_VectorImplEmpty<TYPE> >(0);
259 else if (size == 1)
261 else if (bits.AreAllUnset())
262 _data.New< Vdf_VectorImplEmpty<TYPE> >(size);
263 else
264 _data.New< Vdf_VectorImplContiguous<TYPE> >(bits);
265 }
266
271 VDF_API
272 void Clear();
273
281 void Copy(const VdfVector &rhs, const VdfMask &mask)
282 {
283 _CheckType(rhs);
284
285 // Need to detach local data before copying into it if we are shared.
286 if (ARCH_UNLIKELY(_data.Get()->GetInfo().ownership ==
287 Vdf_VectorData::Info::Ownership::Shared)) {
288 Vdf_VectorImplShared::Detach(&_data);
289 }
290
291 // If the mask is all ones, take advange of the potentially faster
292 // Clone() method.
293 if (mask.IsAllOnes()) {
294 rhs._data.Get()->Clone(&_data);
295 }
296
297 else if (mask.IsAnySet()) {
298 rhs._data.Get()->CloneSubset(mask, &_data);
299 }
300
301 // If the mask is all zeros, create an empty vector instead of
302 // duplicating the rhs vector's implementation with an empty data
303 // section. For compressed vectors, for example, this would cause
304 // problems, because the index mapping would remain uninitialized,
305 // essentially leaving the implementation in a broken state.
306 else {
307 _data.Destroy();
308 rhs._data.Get()->NewEmpty(mask.GetSize(), &_data);
309 }
310 }
311
318 VDF_API
319 void Merge(const VdfVector &rhs, const VdfMask::Bits &bits);
320
323 void Merge(const VdfVector &rhs, const VdfMask &mask) {
324 Merge(rhs, mask.GetBits());
325 }
326
334 bool Share() const
335 {
336 // Bail out if not sharable
337 if (!_data.Get()->IsSharable()) {
338 return false;
339 }
340
341 // Create the new shared impl in a temp DataHolder, _data is moved
342 // into and held by a SharedSource.
344 tmp.New<Vdf_VectorImplShared>(&_data);
345
346 // Move the new shared data into this vector's DataHolder.
347 tmp.Get()->MoveInto(&_data);
348 tmp.Destroy();
349
350 return true;
351 }
352
357 bool IsShared() const
358 {
359 return _data.Get()->GetInfo().ownership ==
360 Vdf_VectorData::Info::Ownership::Shared;
361 }
362
365 bool IsSharable() const
366 {
367 return _data.Get()->IsSharable();
368 }
369
375 template <typename T>
377 ExtractAsVtArray(const size_t size, const int offset) const
378 {
379 Vdf_VectorData* data = _data.Get();
380 const Vdf_VectorData::Info& info = data->GetInfo();
381
382 if (ARCH_UNLIKELY(info.compressedIndexMapping)) {
383 return _DecompressAsVtArray(
384 reinterpret_cast<T *>(info.data),
385 *info.compressedIndexMapping, size, offset);
386 }
387
388 // Need to get a typed pointer to the first element. The memory layout
389 // depends on if the vector is boxed or not. This is what
390 // Vdf_VectorAccessor does under the hood to provide element access.
391 T *access;
392 if (info.layout == Vdf_VectorData::Info::Layout::Boxed) {
393 using BoxedVectorType = Vdf_BoxedContainer<T>;
394 access = reinterpret_cast<BoxedVectorType *>(info.data)->data();
395 } else {
396 access = reinterpret_cast<T *>(info.data) - info.first;
397 }
398
399 access += offset;
400
401 return info.ownership == Vdf_VectorData::Info::Ownership::Shared
402 ? VtArray<T>(data->GetSharedSource(), access, size)
403 : VtArray<T>(access, access + size);
404 }
405
409 template < typename TYPE >
411 public:
412
415 ReadWriteAccessor() = default;
416
419 bool IsEmpty() const { return _accessor.IsEmpty(); }
420
423 size_t GetNumValues() const { return _accessor.GetNumValues(); }
424
428 bool IsBoxed() const { return _accessor.IsBoxed(); }
429
432 TYPE &operator[](size_t i) const { return _accessor[i]; }
433
434 private:
435
436 // Only VdfVector is allowed to create instances of this class.
437 friend class VdfVector;
438
439 // The constructor used by VdfVector.
441 Vdf_VectorData *data,
442 const Vdf_VectorData::Info &info) :
443 _accessor(data, info)
444 {}
445
446 // The underlying accessor type.
447 Vdf_VectorAccessor<TYPE> _accessor;
448
449 };
450
455 template<typename TYPE>
457 {
458 Vdf_VectorData::Info info = _data.Get()->GetInfo();
459
460 if (ARCH_UNLIKELY(info.ownership ==
461 Vdf_VectorData::Info::Ownership::Shared)) {
462
463 Vdf_VectorImplShared::Detach(&_data);
464
465 // Update the info after detaching.
466 info = _data.Get()->GetInfo();
467 }
468
469 return ReadWriteAccessor<TYPE>(_data.Get(), info);
470 }
471
475 template <typename TYPE>
477 public:
478
481 ReadAccessor() = default;
482
485 bool IsEmpty() const { return _accessor.IsEmpty(); }
486
489 size_t GetNumValues() const { return _accessor.GetNumValues(); }
490
494 bool IsBoxed() const { return _accessor.IsBoxed(); }
495
498 const TYPE& operator[](size_t i) const { return _accessor[i]; }
499
500 private:
501
502 // Only VdfVector is allowed to create instances of this class.
503 friend class VdfVector;
504
505 // The constructor used by VdfVector.
507 Vdf_VectorData* data,
508 const Vdf_VectorData::Info& info):
509 _accessor(data, info)
510 {}
511
512 // The underlying accessor type.
513 Vdf_VectorAccessor<TYPE> _accessor;
514 };
515
520 template <typename TYPE>
522 {
523 return ReadAccessor<TYPE>(_data.Get(), _data.Get()->GetInfo());
524 }
525
531 template <typename TYPE>
533 {
535 _data.Get(), _data.Get()->GetInfo());
536 }
537
540 template<typename TYPE>
541 bool Holds() const
542 {
543 static_assert(
544 !Vdf_IsBoxedContainer<TYPE>,
545 "VdfVector::Holds cannot check for boxed-ness");
546
547 return TfSafeTypeCompare(_GetTypeInfo(), typeid(TYPE));
548 }
549
557 {
558 if (&rhs == this)
559 return *this;
560
561 _CheckType(rhs);
562
563 rhs._data.Get()->Clone(&_data);
564
565 return *this;
566 }
567
574 {
575 if (&rhs == this)
576 return *this;
577
578 _CheckType(rhs);
579
580 rhs._data.Get()->MoveInto(&_data);
581
582 return *this;
583 }
584
593 {
594 return _data.Get()->EstimateElementMemory();
595 }
596
606 public:
607
610 VDF_API
611 friend std::ostream &operator<<(std::ostream &, const DebugPrintable &);
612
613 private:
614
615 // Only VdfVector is allowed to create instances of this class.
616 friend class VdfVector;
617
618 // Constructor.
619 DebugPrintable(const Vdf_VectorData *data, const VdfMask &mask) :
620 _data(data), _mask(mask)
621 {}
622
623 // The vector to be printed.
624 const Vdf_VectorData *_data;
625
626 // The mask denoting which elements in the vector should be printed.
627 const VdfMask _mask;
628
629 };
630
635 {
636 return DebugPrintable(_data.Get(), mask);
637 }
638
639// -----------------------------------------------------------------------------
640
641protected:
642
643 // Constructs an empty VdfVector. Note that publicly we're only allowed
644 // to create a VdfTypedVector. See also
645 // VdfExecutionTypeRegistry::CreateEmptyVector(const TfType&).
646 //
647 VdfVector()
648 {
649 // We rely on VdfTypedVector to make an empty data of the correct
650 // type for the default construction case.
651 }
652
653private:
654
655 // Helper for ExtractAsVtArray.
656 //
657 // Decompresses the contents of a compressed vector into a VtArray.
658 // Compressed vectors are always copied because they're never sharable.
659 template <typename T>
660 static VtArray<T> _DecompressAsVtArray(
661 const T* const access,
662 const Vdf_CompressedIndexMapping &indexMapping,
663 const size_t size,
664 const int offset) {
665
666 VtArray<T> array;
667
668 // This is not a general purpose compressed vector copy. VtArray
669 // extraction requests a contiguous range of logical indices and we
670 // assume that this cannot span multiple blocks of data.
671 if (size_t dataIdx; _ComputeCompressedExtractionIndex(
672 indexMapping, size, offset, &dataIdx)) {
673 const T* const src = access + dataIdx;
674 array.assign(src, src+size);
675 }
676 return array;
677 }
678
679 // Computes the data index into a compressed vector impl for the logical
680 // offset.
681 //
682 // Returns true if (offset, size) is contained in a single block of data
683 // and a valid index was written to *dataIdx. Otherwise, returns false.
684 VDF_API
685 static bool _ComputeCompressedExtractionIndex(
686 const Vdf_CompressedIndexMapping &indexMapping,
687 size_t size,
688 int offset,
689 size_t *dataIdx);
690
691 // Helper function that delivers an error message when type checking fails.
692 VDF_API
693 static void _PostTypeError(
694 const std::type_info &thisTypeInfo,
695 const std::type_info &otherTypeInfo);
696
697 void _CheckType(
698 const std::type_info &otherTypeInfo) const
699 {
700 const std::type_info &thisTypeInfo = _GetTypeInfo();
701 if (!TfSafeTypeCompare(thisTypeInfo, otherTypeInfo)) {
702 _PostTypeError(thisTypeInfo, otherTypeInfo);
703 }
704 }
705
706 void _CheckType(const VdfVector &rhs) const
707 {
708 _CheckType(rhs._GetTypeInfo());
709 }
710
711 template <typename TYPE>
712 void _CheckType() const
713 {
714 _CheckType(typeid(TYPE));
715 }
716
717 const std::type_info &_GetTypeInfo() const
718 {
719 return _data.Get()->GetTypeInfo();
720 }
721
722protected:
723
724 // Holder of the actual implementation of Vdf_VectorData that holds this
725 // vector's data. This is protected so that it can be initialized from
726 // our only derived class VdfTypedVector.
727 mutable Vdf_VectorData::DataHolder _data;
728};
729
730PXR_NAMESPACE_CLOSE_SCOPE
731
732#endif
Low-level utilities for informing users of various internal and external diagnostic conditions.
Fast, compressed bit array which is capable of performing logical operations without first decompress...
size_t GetSize() const
Returns the size of the bit array, ie.
bool AreAllUnset() const
Returns true, if all the bits in this bit array are unset.
This simple container stores multiple values that flow through the network as a single data flow elem...
This collection of IndexBlockMappings is all the info required to take a logical index into a compres...
void New(Args &&... args)
Creates an instance.
void Destroy()
Destroys a held instance.
Base const * Get() const
Returns a Base pointer to the held instance.
Accessor class.
bool IsBoxed() const
Returns true if this accessor is providing element-wise access into a boxed container.
bool IsEmpty() const
Returns true if vector is empty.
size_t GetNumValues() const
Returns size of the vector, ie.
Abstract base class for storing data in a VdfVector.
Definition: vectorData.h:27
Implements a Vdf_VectorData storage that holds a boxed element.
Implements Vdf_VectorData storage that holds a contiguous range of elements, which may be a subrange ...
Implements a Vdf_VectorData storage that is always empty.
Implements a Vdf_VectorData storage the supports reference counted sharing of other vector implementa...
Implements a Vdf_VectorData storage that is holds a single element.
Specialized vector accessor for read access to boxed containers.
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:37
size_t GetSize() const
Returns the size of the mask.
Definition: mask.h:158
bool IsAnySet() const
Returns true, if there is at least a single set entry.
Definition: mask.h:216
bool IsAllOnes() const
Returns true if this mask has all entries set.
Definition: mask.h:196
VdfMask::Bits const & GetBits() const
Get this mask's content as CtCompressedfBits.
Definition: mask.h:556
An ostream-able object wrapping a VdfVector instance, as well as a mask indicating which elements in ...
Definition: vector.h:605
VDF_API friend std::ostream & operator<<(std::ostream &, const DebugPrintable &)
Ostream operator.
A read-only accessor for low-level acces to the contents of the VdfVector.
Definition: vector.h:476
bool IsBoxed() const
Returns true if this accessor is providing element-wise access into a boxed container.
Definition: vector.h:494
bool IsEmpty() const
Returns true if the vector is empty.
Definition: vector.h:485
const TYPE & operator[](size_t i) const
Returns a const reference to an element.
Definition: vector.h:498
size_t GetNumValues() const
Returns the size of the vector, i.e.
Definition: vector.h:489
ReadAccessor()=default
Default constructor.
A read/write accessor for low-level access to the contents of the VdfVector.
Definition: vector.h:410
bool IsBoxed() const
Returns true if this accessor is providing element-wise access into a boxed container.
Definition: vector.h:428
TYPE & operator[](size_t i) const
Returns a mutable reference to an element.
Definition: vector.h:432
bool IsEmpty() const
Returns true of the vector is empty.
Definition: vector.h:419
ReadWriteAccessor()=default
Default constructor.
size_t GetNumValues() const
Returns the size of the vector, i.e.
Definition: vector.h:423
This class is used to abstract away knowledge of the cache data used for each node.
Definition: vector.h:56
void Set(TYPE &&data)
Forwards data into the vector.
Definition: vector.h:162
size_t GetSize() const
Returns the number of elements held in this vector.
Definition: vector.h:146
void Set(Vdf_BoxedContainer< TYPE > &&data)
Move boxed values into the vector.
Definition: vector.h:204
size_t EstimateElementMemory() const
Returns the number of bytes necessary to store a single element of this VdfVector.
Definition: vector.h:592
VdfVector(const VdfVector &rhs)
Copy constructor.
Definition: vector.h:61
bool IsShared() const
Returns true if the vector has been shared.
Definition: vector.h:357
VdfVector(VdfVector &&rhs)
Move constructor.
Definition: vector.h:131
void Set(const Vdf_BoxedContainer< TYPE > &data)
Copy boxed values into the vector.
Definition: vector.h:177
bool IsSharable() const
Returns true if the vector can be shared.
Definition: vector.h:365
VdfVector & operator=(const VdfVector &rhs)
Copies the content of rhs into this vector.
Definition: vector.h:556
~VdfVector()
Destructor.
Definition: vector.h:139
void Resize(const VdfMask::Bits &bits)
Allocates space for the elements denoted by bits.
Definition: vector.h:244
size_t GetNumStoredElements() const
Returns the number of elements for which this vector has storage.
Definition: vector.h:154
VtArray< T > ExtractAsVtArray(const size_t size, const int offset) const
Extracts this vector's values into a VtArray<T>.
Definition: vector.h:377
VdfVector(const VdfVector &rhs, size_t size)
Construct a vector with the same element type as rhs and of size size.
Definition: vector.h:116
bool Share() const
Embeds the current vector's existing implementaion into a reference counted implementaion so that the...
Definition: vector.h:334
bool IsEmpty() const
Returns whether or not this vector is empty.
Definition: vector.h:150
DebugPrintable GetDebugPrintable(const VdfMask &mask) const
Returns an ostream-able object, which can be used to debug print the contents of this VdfVector,...
Definition: vector.h:634
VdfVector(const VdfVector &rhs, const VdfMask &mask)
Copy constructor with subset copying.
Definition: vector.h:71
VdfVector & operator=(VdfVector &&rhs)
Moves the content of rhs into this vector.
Definition: vector.h:573
ReadAccessor< TYPE > GetReadAccessor() const
GetReadAccessor() allows low level read-only access to the content of of the VdfVector via the Vdf_Ve...
Definition: vector.h:521
void Resize(size_t size)
Allocates space for size number of elements.
Definition: vector.h:218
void Copy(const VdfVector &rhs, const VdfMask &mask)
Copies the contents of rhs into this vector.
Definition: vector.h:281
Vdf_VectorSubrangeAccessor< TYPE > GetSubrangeAccessor() const
Provide read-only access to the boxed subranges held by this vector.
Definition: vector.h:532
bool Holds() const
Checks if a vector holds a specific type.
Definition: vector.h:541
ConstructBoxedCopyTag
Copy constructor with boxing.
Definition: vector.h:90
VDF_API void Clear()
Destroys contents of this vector.
ReadWriteAccessor< TYPE > GetReadWriteAccessor() const
GetReadWriteAccessor() allows low level access to the content of the VdfVector via the Vdf_VectorData...
Definition: vector.h:456
VDF_API void Merge(const VdfVector &rhs, const VdfMask::Bits &bits)
Merges the contents of rhs into this vector.
void Merge(const VdfVector &rhs, const VdfMask &mask)
Same as Merge(), but takes a VdfMask instead of a bitset.
Definition: vector.h:323
Represents an arbitrary dimensional rectangular container class.
Definition: array.h:213
std::enable_if<!std::is_integral< ForwardIter >::value >::type assign(ForwardIter first, ForwardIter last)
Assign array contents.
Definition: array.h:887
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:68
Compiler hints.
Safely compare C++ RTTI type structures.
bool TfSafeTypeCompare(const std::type_info &t1, const std::type_info &t2)
Safely compare std::type_info structures.