HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vectorImpl_Contiguous.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_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"
15 #include "pxr/exec/vdf/mask.h"
20 
21 #include "pxr/base/tf/mallocTag.h"
22 
24 
25 /// Implements Vdf_VectorData storage that holds a contiguous range of
26 /// elements, which may be a subrange of the logical vector size.
27 ///
28 template <typename TYPE>
30  : public Vdf_VectorDataTyped<TYPE>
31 {
32  static_assert(
33  !Vdf_IsBoxedContainer<TYPE>,
34  "Only Vdf_VectorImplBoxed may hold boxed values");
35 
36 public:
37 
38  /// Dense vector constructor.
39  ///
40  /// Constructs a vector of whose size is \p size. Storage is allocated
41  /// for the range [0, size-1].
42  ///
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 
51  /// Sparse vector constructor.
52  ///
53  /// Constructs a vector whose size is \p size. Storage is allocated for
54  /// the range [first, last].
55  ///
56  Vdf_VectorImplContiguous(size_t size, size_t first, size_t last)
57  {
58  _AllocateSpace(size, first, last);
59  }
60 
61  /// Sparse vector constructor.
62  ///
63  /// Constructs a vector whose size is the width of \p bits. Storage is
64  /// allocated for the range [bits.GetFirstSet(), bits.GetLastSet()].
65  ///
67  {
68  _AllocateSpace(bits);
69  }
70 
71  /// Sparse vector constructor.
72  ///
73  /// Constructs a vector whose size is \p size. Storage is allocated for
74  /// the range [bits.GetFirstSet(), bits.GetLastSet()]. Elements are
75  /// copied from \p data for each set bit in \p bits.
76  ///
77  /// Note that the block of memory allocated is contiguous even if the mask
78  /// contains holes. Only the elements specified by the mask will be
79  /// copied, all other elements will remain uninitialized.
80  ///
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 
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();
167  destData->New< Vdf_VectorImplCompressed<TYPE> >(
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);
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) {
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 
289  {
290  return Vdf_VectorData::Info(
291  /* data = */ _data,
292  /* size = */ _size,
293  /* first = */ _first,
294  /* last = */ _last);
295  }
296 
297 private:
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 
328 private:
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>;
339 #undef VDF_DECLARE_EXTERN_VECTOR_IMPL_CONTIGUOUS
340 
342 
343 #endif
GLint first
Definition: glcorearb.h:405
bool IsSharable() const override
Vdf_VectorImplContiguous(size_t size, size_t first, size_t last)
size_t GetFirstSet() const
Definition: mask.h:226
const GLdouble * v
Definition: glcorearb.h:837
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
Vdf_CompressedIndexMapping * compressedIndexMapping
Definition: vectorData.h:205
AllSetView GetAllSetView() const
#define VDF_FOR_EACH_COMMON_TYPE(macro)
VDF_FOR_EACH_COMMON_TYPE expands macro for each common type.
void Expand(size_t first, size_t last) override
void Assign(const TYPE *data, const VdfMask &mask)
void CloneSubset(const VdfMask &mask, Vdf_VectorData::DataHolder *destData) const override
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
static void Copy(T *dest, const T *source, size_t size)
Vdf_VectorData::Info GetInfo() override
VdfMask::Bits const & GetBits() const
Definition: mask.h:556
Fast, compressed bit array which is capable of performing logical operations without first decompress...
void Clone(Vdf_VectorData::DataHolder *destData) const override
static constexpr size_t _VectorSharingSize
Definition: vectorData.h:42
#define TF_DEV_AXIOM(cond)
Vdf_VectorImplContiguous(const TYPE *data, const VdfMask::Bits &bits)
void Merge(const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const override
GLintptr offset
Definition: glcorearb.h:665
void MoveInto(Vdf_VectorData::DataHolder *destData) override
virtual void Clone(DataHolder *destData) const =0
Vdf_VectorImplContiguous(Vdf_VectorImplContiguous &&sourceData)
#define __ARCH_PRETTY_FUNCTION__
Definition: functionLite.h:29
size_t GetNumSet() const
GLint GLuint mask
Definition: glcorearb.h:124
size_t GetLastSet() const
Definition: mask.h:236
bool AreAllUnset() const
#define VDF_DECLARE_EXTERN_VECTOR_IMPL_CONTIGUOUS(type)
bool IsAllZeros() const
Definition: mask.h:206
Implements a Vdf_VectorData storage that holds a boxed element.
size_t GetSize() const
Definition: mask.h:158
__hostdev__ uint64_t last(uint32_t i) const
Definition: NanoVDB.h:5976
GLsizeiptr size
Definition: glcorearb.h:664
size_t GetSize() const
#define VDF_API_TYPE
Definition: api.h:26
Implements a Vdf_VectorData storage that is always empty.
size_t GetLastSet() const
Base const * Get() const
Returns a Base pointer to the held instance.
static VDF_API bool ShouldStoreCompressed(const VdfMask::Bits &bits, int elementSize)
size_t GetNumStoredElements() const override
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void Box(const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const override
Vdf_VectorImplContiguous(const VdfMask::Bits &bits)
size_t GetSize() const override
size_t GetFirstSet() const
bool AreContiguouslySet() const
Definition: format.h:1821
Implements a Vdf_VectorData storage that is holds a subset of a vector. The subset is determined by a...
Vdf_VectorImplContiguous(const Vdf_VectorImplContiguous &rhs)