Loading...
Searching...
No Matches
vectorImpl_Contiguous.h
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_IMPL_CONTIGUOUS_H
8#define PXR_EXEC_VDF_VECTOR_IMPL_CONTIGUOUS_H
9
10#include "pxr/pxr.h"
11
12#include "pxr/exec/vdf/api.h"
13#include "pxr/exec/vdf/boxedContainer.h"
14#include "pxr/exec/vdf/forEachCommonType.h"
15#include "pxr/exec/vdf/mask.h"
16#include "pxr/exec/vdf/vectorDataTyped.h"
17#include "pxr/exec/vdf/vectorImpl_Boxed.h"
18#include "pxr/exec/vdf/vectorImpl_Compressed.h"
19#include "pxr/exec/vdf/vectorImpl_Dispatch.h"
20
22
23PXR_NAMESPACE_OPEN_SCOPE
24
28template <typename TYPE>
29class VDF_API_TYPE Vdf_VectorImplContiguous final
30 : public Vdf_VectorDataTyped<TYPE>
31{
32 static_assert(
33 !Vdf_IsBoxedContainer<TYPE>,
34 "Only Vdf_VectorImplBoxed may hold boxed values");
35
36public:
37
43 explicit Vdf_VectorImplContiguous(size_t size)
44 : _data(size ? new TYPE[size] : nullptr)
45 , _size(size)
46 , _first(0)
47 , _last(size ? size-1 : 0)
48 {
49 }
50
56 Vdf_VectorImplContiguous(size_t size, size_t first, size_t last)
57 {
58 _AllocateSpace(size, first, last);
59 }
60
67 {
68 _AllocateSpace(bits);
69 }
70
81 Vdf_VectorImplContiguous(const TYPE *data, const VdfMask::Bits &bits)
82 {
83 _AllocateSpace(bits);
84
85 if (_data) {
86 // We can allow to copy only elements that are needed, since _data[]
87 // is default initialized.
88 const size_t firstSet = bits.GetFirstSet();
89 Vdf_VectorImplDispatch<TYPE>::Copy(_data - firstSet, data, bits);
90 }
91 }
92
94 _size(rhs._size),
95 _first(rhs._first),
96 _last(rhs._last)
97 {
98 if (rhs._data) {
99 const size_t numUsed = _last - _first + 1;
100 _data = new TYPE[numUsed];
101 TF_DEV_AXIOM(_data);
102
103 Vdf_VectorImplDispatch<TYPE>::Copy(_data, rhs._data, numUsed);
104 } else {
105 _data = NULL;
106 }
107 }
108
110 _data(sourceData._data),
111 _size(sourceData._size),
112 _first(sourceData._first),
113 _last(sourceData._last)
114 {
115 sourceData._data = NULL;
116 sourceData._size = 0;
117 sourceData._first = 0;
118 sourceData._last = 0;
119 }
120
122 {
123 delete [] _data;
124 }
125
126 void MoveInto(Vdf_VectorData::DataHolder *destData) override
127 {
128 TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
129 destData->Destroy();
130 destData->New< Vdf_VectorImplContiguous >(std::move(*this));
131 }
132
133 void Clone(Vdf_VectorData::DataHolder *destData) const override
134 {
135 TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
136 destData->Destroy();
137 destData->New< Vdf_VectorImplContiguous >(*this);
138 }
139
140 void CloneSubset(const VdfMask &mask,
141 Vdf_VectorData::DataHolder *destData) const override
142 {
143 TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
144 TF_DEV_AXIOM(_size == mask.GetSize());
145
146 // We're a contiguous vector and there is potential for more subsetting.
147 if (mask.IsAllZeros()) {
148
149 // In this case we want to store an empty vector that indicates
150 // that we have the correct size, but there are no stored values.
151 destData->Destroy();
152 destData->New< Vdf_VectorImplEmpty<TYPE> >(mask.GetSize());
153
154 } else if (Vdf_VectorData::ShouldStoreCompressed(
155 mask.GetBits(), sizeof(TYPE)) ) {
156 // Check to see if the destination data is already a compressed
157 // vector. If it is, we'll try to avoid reallocating by simply
158 // copying a subset of our data into the existing compressed vector.
159 // The allocation is avoided only if the mask numset is exactly
160 // the same as the destination's raw storage size.
161 Vdf_VectorImplCompressed<TYPE> *destCompressed =
162 dynamic_cast<Vdf_VectorImplCompressed<TYPE> *>(destData->Get());
163 if (destCompressed) {
164 destCompressed->Assign(&(_data[-_first]), mask);
165 } else {
166 destData->Destroy();
168 &(_data[-_first]), mask.GetBits() );
169 }
170
171 } else {
172
173 // Here's where we can create a subset vector.
174 size_t firstSet = mask.GetFirstSet();
175 size_t lastSet = mask.GetLastSet();
176
177 if (firstSet == _first && lastSet == _last) {
178
179 // In this case we want all of this already subset vector.
180 Clone(destData);
181
182 } else {
183
184 // Here we're splitting up the already contiguous vector a
185 // little more.
186 destData->Destroy();
187 destData->New< Vdf_VectorImplContiguous >(
188 _data - _first, mask.GetBits());
189 }
190 }
191 }
192
193 void Box(const VdfMask::Bits &bits,
194 Vdf_VectorData::DataHolder *destData) const override
195 {
196 TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
197 TF_VERIFY(bits.GetFirstSet() >= _first);
198 TF_VERIFY(bits.GetLastSet() <= _last);
199
201 if (bits.AreContiguouslySet()) {
202 const size_t offset = bits.GetFirstSet() - _first;
203 for (size_t i = 0; i < v.size(); ++i) {
204 v[i] = _data[offset + i];
205 }
206 } else {
207 size_t i = 0;
208 for (const uint32_t idx : bits.GetAllSetView()) {
209 v[i++] = _data[idx - _first];
210 }
211 }
212
213 destData->Destroy();
214 destData->New< Vdf_VectorImplBoxed<TYPE> >(std::move(v));
215 }
216
217 void Merge(const VdfMask::Bits &bits,
218 Vdf_VectorData::DataHolder *destData) const override
219 {
220 // Retrieve the destination information
221 Vdf_VectorData::Info info = destData->Get()->GetInfo();
222
223 // The destination must be a contiguous vector
224 if (!TF_VERIFY(
225 info.size > 1 &&
226 info.compressedIndexMapping == NULL &&
227 info.data, "destData is not a Vdf_VectorImplContiguous.")) {
228 return;
229 }
230
231 // Merge the requested data into the destination vector
232 TYPE *typedDest = static_cast<TYPE*>(info.data);
233 Vdf_VectorImplDispatch<TYPE>::Copy(
234 typedDest - info.first, _data - _first, bits);
235 }
236
237 void Expand(size_t first, size_t last) override
238 {
239 // Make sure that the storage grows, but never shrinks. If the storage
240 // is currently empty, use the passed in range.
241 const size_t newFirst = _data ? std::min(_first, first) : first;
242 const size_t newLast = _data ? std::max(_last, last) : last;
243
244 // If the storage space is already big enough, there is nothing
245 // to do here.
246 if (_first == newFirst && _last == newLast) {
247 return;
248 }
249
250 // Retain a pointer to the old data
251 TYPE *oldData = _data;
252
253 // Allocate a new data section
254 const size_t newSize = newLast - newFirst + 1;
255 _data = new TYPE[newSize];
256 TF_DEV_AXIOM(_data);
257
258 // Copy the old data, if available
259 if (oldData) {
260 Vdf_VectorImplDispatch<TYPE>::Copy(
261 _data + _first - newFirst, oldData, _last - _first + 1);
262 delete[] oldData;
263 }
264
265 // Set the new info
266 _first = newFirst;
267 _last = newLast;
268 }
269
270 size_t GetSize() const override
271 {
272 return _size;
273 }
274
275 size_t GetNumStoredElements() const override
276 {
277 if (!_data) {
278 return 0;
279 }
280 return _last - _first + 1;
281 }
282
283 bool IsSharable() const override
284 {
285 return _size >= Vdf_VectorData::_VectorSharingSize;
286 }
287
288 Vdf_VectorData::Info GetInfo() override
289 {
290 return Vdf_VectorData::Info(
291 /* data = */ _data,
292 /* size = */ _size,
293 /* first = */ _first,
294 /* last = */ _last);
295 }
296
297private:
298
299 void _AllocateSpace(const VdfMask::Bits &bits)
300 {
301 if (bits.AreAllUnset()) {
302 _data = nullptr;
303 _size = bits.GetSize();
304 _first = 0;
305 _last = 0;
306 } else {
307 _AllocateSpace(bits.GetSize(),
308 bits.GetFirstSet(),
309 bits.GetLastSet());
310 }
311 }
312
313 void _AllocateSpace(size_t size, size_t firstIndex, size_t lastIndex)
314 {
315 _size = size;
316
317 _first = firstIndex;
318 TF_DEV_AXIOM(_first < _size);
319
320 _last = lastIndex;
321 TF_DEV_AXIOM(_last >= _first);
322
323 const size_t numUsed = _last - _first + 1;
324 _data = new TYPE[numUsed];
325 TF_DEV_AXIOM(_data);
326 }
327
328private:
329
330 TYPE *_data;
331 size_t _size;
332 size_t _first;
333 size_t _last;
334};
335
336#define VDF_DECLARE_EXTERN_VECTOR_IMPL_CONTIGUOUS(type) \
337 extern template class VDF_API_TYPE Vdf_VectorImplContiguous<type>;
338VDF_FOR_EACH_COMMON_TYPE(VDF_DECLARE_EXTERN_VECTOR_IMPL_CONTIGUOUS)
339#undef VDF_DECLARE_EXTERN_VECTOR_IMPL_CONTIGUOUS
340
341PXR_NAMESPACE_CLOSE_SCOPE
342
343#endif
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 AreContiguouslySet() const
Returns true if the set bits in this bit array are contiguous.
size_t GetLastSet() const
Returns the index of the last bit set in the bit array.
size_t GetFirstSet() const
Returns the index of the first bit set in the bit array.
bool AreAllUnset() const
Returns true, if all the bits in this bit array are unset.
size_t GetNumSet() const
Returns the number of bits currently set in this array.
Scoped (i.e.
Definition: mallocTag.h:249
This simple container stores multiple values that flow through the network as a single data flow elem...
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.
Implements a Vdf_VectorData storage that holds a boxed element.
Implements a Vdf_VectorData storage that is holds a subset of a vector.
void Assign(const TYPE *data, const VdfMask &mask)
Assigns the subset of data that is described by mask into this sparse vector.
Implements Vdf_VectorData storage that holds a contiguous range of elements, which may be a subrange ...
Vdf_VectorImplContiguous(const VdfMask::Bits &bits)
Sparse vector constructor.
Vdf_VectorImplContiguous(size_t size)
Dense vector constructor.
Vdf_VectorImplContiguous(const TYPE *data, const VdfMask::Bits &bits)
Sparse vector constructor.
Vdf_VectorImplContiguous(size_t size, size_t first, size_t last)
Sparse vector constructor.
Implements a Vdf_VectorData storage that is always empty.
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 IsAllZeros() const
Returns true if this mask has all entries unset.
Definition: mask.h:206
size_t GetLastSet() const
Returns the last set bit in the mask.
Definition: mask.h:236
size_t GetFirstSet() const
Returns the first set bit in the mask.
Definition: mask.h:226
VdfMask::Bits const & GetBits() const
Get this mask's content as CtCompressedfBits.
Definition: mask.h:556
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition: diagnostic.h:205
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:266