HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vectorImpl_Compressed.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_COMPRESSED_H
8 #define PXR_EXEC_VDF_VECTOR_IMPL_COMPRESSED_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/exec/vdf/api.h"
17 #include "pxr/exec/vdf/mask.h"
20 
21 #include "pxr/base/tf/mallocTag.h"
22 
24 
25 /// \brief Implements a Vdf_VectorData storage that is holds a subset of a
26 /// vector. The subset is determined by a supplied VdfMask. Each bit
27 /// in the mask maps to an element in the given vector. The storage
28 /// omits all elements associated with zeros in the mask.
29 ///
30 /// See vdf/compressedIndexMapping.h for details on the mapping implementation.
31 ///
32 template<typename TYPE>
34  : public Vdf_VectorDataTyped<TYPE>
35 {
36  static_assert(
37  !Vdf_IsBoxedContainer<TYPE>,
38  "Only Vdf_VectorImplBoxed may hold boxed values");
39 
40 public :
41 
42  /// Construct storage for the elements of \p data indicated by \p bits.
43  Vdf_VectorImplCompressed(const TYPE *data, const VdfMask::Bits &bits) :
44  _compressedIndexMapping(new Vdf_CompressedIndexMapping())
45  {
46  _AllocateSpace(bits);
47  _Initialize(data, bits);
48  }
49 
50  /// Construct enough storage to hold as many elements as \p bits has set.
51  explicit Vdf_VectorImplCompressed(const VdfMask::Bits &bits) :
52  _compressedIndexMapping(new Vdf_CompressedIndexMapping())
53  {
54  _AllocateSpace(bits);
55  _Initialize(NULL, bits);
56  }
57 
59 
60  // Move ctor
62  _data(sourceData._data),
63  _logicalSize(sourceData._logicalSize),
64  _compressedIndexMapping(sourceData._compressedIndexMapping)
65  {
66  sourceData._data = NULL;
67  sourceData._logicalSize = 0;
68  sourceData._compressedIndexMapping = NULL;
69  }
70 
72  {
73  if (_data)
74  delete [] _data;
75 
76  if (_compressedIndexMapping)
77  delete _compressedIndexMapping;
78  }
79 
80  void MoveInto(Vdf_VectorData::DataHolder *destData) override
81  {
82  TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
83  destData->Destroy();
84  destData->New< Vdf_VectorImplCompressed >(std::move(*this));
85  }
86 
87  void Clone(Vdf_VectorData::DataHolder *destData) const override
88  {
89  TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
90  destData->Destroy();
91  destData->New< Vdf_VectorImplCompressed >(*this);
92  }
93 
94  /// Assigns the subset of \p data that is described by \p mask into this
95  /// sparse vector.
96  ///
97  void Assign(const TYPE *data, const VdfMask &mask)
98  {
99  // If our current data isn't the exact right size to store the data
100  // we are supposed to copy, delete our array and 'new' one of the
101  // appropriate size.
102  if (GetNumStoredElements() != mask.GetNumSet()) {
103  delete [] _data;
104  _data = new TYPE[mask.GetNumSet()];
105  }
106 
107  _Initialize(data, mask.GetBits());
108  }
109 
110  void CloneSubset(const VdfMask &mask,
111  Vdf_VectorData::DataHolder *destData) const override;
112 
113  void Box(const VdfMask::Bits &bits,
114  Vdf_VectorData::DataHolder *destData) const override;
115 
116  void Merge(const VdfMask::Bits &bits,
117  Vdf_VectorData::DataHolder *destData) const override;
118 
119  size_t GetSize() const override
120  {
121  return _logicalSize;
122  }
123 
124  size_t GetNumStoredElements() const override
125  {
126  if (_compressedIndexMapping->_blockMappings.size() > 0) {
127  return _compressedIndexMapping->_blockMappings.back().dataEndIndex;
128  } else {
129  return 0;
130  }
131  }
132 
134  {
135  return Vdf_VectorData::Info(
136  /* data = */ _data,
137  /* size = */ _logicalSize,
138  /* first = */ _compressedIndexMapping->GetFirstIndex(),
139  /* last = */ _compressedIndexMapping->GetLastIndex(),
140  /* compressedIndexMapping = */ _compressedIndexMapping);
141  }
142 
143 private :
144 
145  /// Constructs a compressed vector containing the elements from \p data that
146  /// are specified by \p mask.
147  ///
148  /// Note that the block of memory allocated by the sparse vector is
149  /// contiguous even if the mask contains holes. Only the elements
150  /// specified by the mask will be stored, and all other elements will be
151  /// omitted.
152  ///
153  /// If \p data is NULL, the compressed vector is left uninitialized.
154  ///
155  void _Initialize(const TYPE *data, const VdfMask::Bits &bits);
156 
157  void _AllocateSpace(const VdfMask::Bits &bits)
158  {
159  _data = new TYPE[bits.GetNumSet()];
160  }
161 
162 private:
163 
164  TYPE *_data;
165  size_t _logicalSize;
166  Vdf_CompressedIndexMapping *_compressedIndexMapping;
167 };
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 
171 template<typename TYPE>
173  const Vdf_VectorImplCompressed &rhs) :
174  _logicalSize(rhs._logicalSize),
175  _compressedIndexMapping(new Vdf_CompressedIndexMapping(
176  *rhs._compressedIndexMapping))
177 {
178  if (rhs._data) {
179  const size_t numUsed = rhs.GetNumStoredElements();
180 
181  _data = new TYPE[numUsed];
182  TF_DEV_AXIOM(_data);
183  Vdf_VectorImplDispatch<TYPE>::Copy(_data, rhs._data, numUsed);
184 
185  } else {
186 
187  _data = NULL;
188 
189  }
190 
191 }
192 
193 template<typename TYPE>
194 void
196  const VdfMask &mask, Vdf_VectorData::DataHolder *destData) const
197 {
198  TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
199  TF_DEV_AXIOM(_logicalSize == mask.GetSize());
200  const VdfMask::Bits &bits = mask.GetBits();
201 
202  // Allocate space and build an index mapping, leaving data uninitialized.
203  // This is a little more than necessary but very easy to accomplish.
204  destData->Destroy();
205  destData->New< Vdf_VectorImplCompressed >(bits);
206  Vdf_VectorImplCompressed * destImpl =
207  dynamic_cast<Vdf_VectorImplCompressed *>(destData->Get());
208 
209  // Copy the relevant data from me into the destination. The mapping is
210  // conveniently already set up.
211  size_t srcBlockHint = 0;
212  size_t destBlockHint = 0;
213  using View = VdfMask::Bits::PlatformsView;
214  View platforms = bits.GetPlatformsView();
215  for (View::const_iterator it=platforms.begin(), e=platforms.end(); it != e;
216  ++it) {
217  if (it.IsSet()) {
218  const size_t index = *it;
219  const size_t srcDataIdx =
220  _compressedIndexMapping->FindDataIndex(index, &srcBlockHint);
221  const size_t destDataIdx = destImpl->
222  _compressedIndexMapping->FindDataIndex(index, &destBlockHint);
224  destImpl->_data + destDataIdx, _data + srcDataIdx,
225  it.GetPlatformSize());
226  }
227  }
228 }
229 
230 template<typename TYPE>
231 void
233  const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const
234 {
235  TfAutoMallocTag tag("Vdf", __ARCH_PRETTY_FUNCTION__);
236  TF_VERIFY(bits.GetFirstSet() >= _compressedIndexMapping->GetFirstIndex());
237  TF_VERIFY(bits.GetLastSet() <= _compressedIndexMapping->GetLastIndex());
238 
240 
241  size_t i = 0;
242  size_t blockHint = 0;
243  for (const uint32_t idx : bits.GetAllSetView()) {
244  const size_t dataIdx =
245  _compressedIndexMapping->FindDataIndex(idx, &blockHint);
246  v[i++] = _data[dataIdx];
247  }
248 
249  destData->Destroy();
250  destData->New< Vdf_VectorImplBoxed<TYPE> >(std::move(v));
251 }
252 
253 template<typename TYPE>
254 void
256  const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const
257 {
258  // Retrieve the destination information
259  Vdf_VectorData::Info info = destData->Get()->GetInfo();
260 
261  // The destination must be a dense vector
262  if (!TF_VERIFY(
263  info.size > 1 &&
264  info.compressedIndexMapping == NULL &&
265  info.data, "destData is not a Vdf_VectorImplDense.")) {
266  return;
267  }
268 
269  // Merge the requested data into the destination vector (must be
270  // sparse or dense)
271  size_t srcBlockHint = 0;
272  TYPE *typedDest = static_cast<TYPE*>(info.data);
273 
274  // Copy in chunks.
275  using View = VdfMask::Bits::PlatformsView;
276  View platforms = bits.GetPlatformsView();
277  for (View::const_iterator it=platforms.begin(), e=platforms.end(); it != e;
278  ++it) {
279  if (it.IsSet()) {
280  const size_t index = *it;
281  const size_t srcDataIdx =
282  _compressedIndexMapping->FindDataIndex(index, &srcBlockHint);
284  typedDest + index - info.first, _data + srcDataIdx,
285  it.GetPlatformSize());
286  }
287  }
288 }
289 
290 template<typename TYPE>
291 void
293  const TYPE *srcData, const VdfMask::Bits &bits)
294 {
295  // Note the logical size of the vector is not the same
296  // as how much data it stores.
297  _logicalSize = bits.GetSize();
298  const size_t newStorageSize = bits.GetNumSet();
299 
300  // Check to make sure that we have elements to copy.
301  if (newStorageSize == 0) {
302  // We have nothing to store.
303  return;
304  }
305 
306  // Compute the compressed index mapping, which is only
307  // dependent on the layout of the set bits, and
308  // provides a mapping from logical indices to
309  // packed stored data indices in _data. This is
310  // the key to compressed vector memory savings.
311  _compressedIndexMapping->Initialize(bits);
312 
313  // If specified, initialize this vector's data, using the
314  // compressed index mapping. Copy from the srcData in chunks
315  // as specified by the mask.
316  if (srcData) {
317  size_t destDataIdx = 0;
318  using View = VdfMask::Bits::PlatformsView;
319  View platforms = bits.GetPlatformsView();
320  for (View::const_iterator it=platforms.begin(), e=platforms.end();
321  it != e; ++it) {
322  if (it.IsSet()) {
323  const size_t platformSize = it.GetPlatformSize();
325  _data + destDataIdx, srcData + *it, platformSize);
326  destDataIdx += platformSize;
327  }
328  }
329  }
330 
331  // A few sanity check axioms.
332  TF_DEV_AXIOM(_logicalSize > 0);
333  TF_DEV_AXIOM(_data);
334 }
335 
336 #if !defined(ARCH_OS_WINDOWS)
337 #define VDF_DECLARE_EXTERN_VECTOR_IMPL_COMPRESSED(type) \
338  extern template class VDF_API_TYPE Vdf_VectorImplCompressed<type>;
340 #undef VDF_DECLARE_EXTERN_VECTOR_IMPL_COMPRESSED
341 #endif // !defined(ARCH_OS_WINDOWS)
342 
344 
345 #endif
void CloneSubset(const VdfMask &mask, Vdf_VectorData::DataHolder *destData) const override
#define VDF_DECLARE_EXTERN_VECTOR_IMPL_COMPRESSED(type)
virtual size_t GetNumStoredElements() const =0
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 Assign(const TYPE *data, const VdfMask &mask)
void Box(const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const override
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)
VdfMask::Bits const & GetBits() const
Definition: mask.h:556
Fast, compressed bit array which is capable of performing logical operations without first decompress...
Vdf_VectorImplCompressed(Vdf_VectorImplCompressed &&sourceData)
#define TF_DEV_AXIOM(cond)
Vdf_VectorImplCompressed(const TYPE *data, const VdfMask::Bits &bits)
Construct storage for the elements of data indicated by bits.
void Clone(Vdf_VectorData::DataHolder *destData) const override
void MoveInto(Vdf_VectorData::DataHolder *destData) override
Vdf_VectorData::Info GetInfo() override
#define __ARCH_PRETTY_FUNCTION__
Definition: functionLite.h:29
size_t GetNumSet() const
GLint GLuint mask
Definition: glcorearb.h:124
void Merge(const VdfMask::Bits &bits, Vdf_VectorData::DataHolder *destData) const override
Vdf_VectorImplCompressed(const VdfMask::Bits &bits)
Construct enough storage to hold as many elements as bits has set.
Implements a Vdf_VectorData storage that holds a boxed element.
size_t GetSize() const
Definition: mask.h:158
virtual void CloneSubset(const VdfMask &mask, DataHolder *destData) const =0
PlatformsView GetPlatformsView() const
size_t GetSize() const
#define VDF_API_TYPE
Definition: api.h:26
size_t GetLastSet() const
Base const * Get() const
Returns a Base pointer to the held instance.
size_t GetNumSet() const
Definition: mask.h:246
GLuint index
Definition: glcorearb.h:786
size_t GetSize() const override
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
virtual void Box(const VdfMask::Bits &bits, DataHolder *destData) const =0
size_t GetNumStoredElements() const override
size_t GetFirstSet() const
Definition: format.h:1821
View< Mode::Platforms > PlatformsView
virtual void Merge(const VdfMask::Bits &bits, DataHolder *destData) const =0
Implements a Vdf_VectorData storage that is holds a subset of a vector. The subset is determined by a...