HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
readIterator.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_READ_ITERATOR_H
8 #define PXR_EXEC_VDF_READ_ITERATOR_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
15 #include "pxr/exec/vdf/iterator.h"
16 #include "pxr/exec/vdf/node.h"
18 #include "pxr/exec/vdf/vector.h"
19 
20 #include "pxr/base/tf/diagnostic.h"
21 
22 #include <iterator>
23 
25 
26 ////////////////////////////////////////////////////////////////////////////////
27 ///
28 /// \class VdfReadIterator
29 ///
30 /// An iterator that provides read access to input values using a context.
31 ///
32 /// \note This is a ForwardIterator with the exception of a missing
33 /// post-increment operator. The implementation of a post-increment operator
34 /// would be slower than that of pre-increment and to prevent erroneous use it
35 /// has been omitted entirely.
36 ///
37 template<typename T>
39 {
40 public:
41 
42  /// Type of the elements this iterator gives access to.
43  ///
44  using value_type = const T;
45 
46  /// The type used to identify distance between instances of this iterator.
47  ///
49 
50  /// Type of a reference to a value of this iterator.
51  ///
52  using reference = value_type &;
53 
54  /// Type of a pointer to a value of this iterator.
55  ///
56  using pointer = value_type *;
57 
58  /// The STL category of this iterator type.
59  ///
60  using iterator_category = std::forward_iterator_tag;
61 
62  /// Constructs a read iterator
63  ///
64  VdfReadIterator(const VdfContext &context, const TfToken &inputName);
65 
66  /// Returns \c true if this iterator and \p rhs compare equal.
67  ///
68  bool operator==(const VdfReadIterator &rhs) const;
69 
70  /// Returns \c true if this iterator and \p rhs do not compare equal.
71  ///
72  bool operator!=(const VdfReadIterator &rhs) const {
73  return !operator==(rhs);
74  }
75 
76  /// Increment operator to point to the next element. Calling this on an
77  /// iterator that IsAtEnd() is invalid and will lead to undefined behavior.
78  ///
80 
81  /// Returns reference to current element. Calling this on an iterator that
82  /// IsAtEnd() is invalid and will lead to undefined behavior.
83  ///
84  reference operator*() const {
85  return *operator->();
86  }
87 
88  /// Returns pointer to current element. Calling this on an iterator that
89  /// IsAtEnd() is invalid and will lead to undefined behavior.
90  ///
91  pointer operator->() const;
92 
93  /// Returns true if the iterator is done iterating and false otherwise.
94  ///
95  bool IsAtEnd() const {
96  return _connectionIndex == -1;
97  }
98 
99  /// Returns the total number of data elements that will be iterated over.
100  ///
101  size_t ComputeSize() const;
102 
103  /// Advance the iterator to the end.
104  ///
105  void AdvanceToEnd();
106 
107 private:
108 
109  // VdfSubrangeView has access to the private constructor.
110  template<typename> friend class VdfSubrangeView;
111 
112  // Construct a read iterator beginning at the specified connection and boxed
113  // index. Will seek to the next valid connection if the specified connection
114  // does not provide data.
116  const VdfContext &context,
117  const TfToken &inputName,
118  int connectionIndex,
119  unsigned int boxedIndex);
120 
121  // Returns the current index into the data source.
122  friend int Vdf_GetIteratorIndex(const VdfReadIterator &it) {
123  return *it._iterator + it._boxedIndex;
124  }
125 
126  // Returns the name of the current data source.
127  friend bool Vdf_IsIteratorSourcePool(const VdfReadIterator &it) {
128  return Vdf_IsPoolOutput(
129  (*it._input)[it._connectionIndex].GetSourceOutput());
130  }
131 
132  // Sets the current connection from our input connector and returns true if
133  // the connection is valid. If the connection is not valid, we need to jump
134  // to the next connection. Returns true if the specified connection is
135  // a valid data source.
136  bool _SetCurrentConnection(int connectionIndex);
137 
138  // Sets the current boxed index to the specified index, or advances to the
139  // next valid connection if the index exceeds the number of input values
140  // available on this connection. Returns true if a valid data source is
141  // available.
142  bool _SetCurrentBoxedIndex(unsigned int boxedIndex);
143 
144  // Advances to the next input and returns true if one exists,
145  // otherwise returns false to indicate at end. Returns true if there is
146  // a valid data element to advance to.
147  bool _Advance();
148 
149  // Advances to the next input connection with scheduled output data to
150  // source from.
151  bool _AdvanceConnection(int connectionIndex);
152 
153  // The context this iterator is bound to.
154  const VdfContext *_context;
155 
156  // The input connector for this iterator. This is where all the connections
157  // that we are iterating through are connected.
158  const VdfInput *_input;
159 
160  // The index of the current connection.
161  int _connectionIndex;
162 
163  // The index of the current boxed value.
164  unsigned int _boxedIndex;
165 
166  // The iterator for the connection mask.
167  VdfMask::iterator _iterator;
168 
169  // The accessor into the current output value.
170  VdfVector::ReadAccessor<T> _accessor;
171 
172 };
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 
176 template<typename T>
178  const VdfContext &context,
179  const TfToken &inputName) :
180  _context(&context),
181  _input(_GetNode(context).GetInput(inputName)),
182  _connectionIndex(-1),
183  _boxedIndex(0)
184 {
185  // If the input is not valid, or there are no input connections, this
186  // iterator remains empty.
187  if (!_input || _input->GetNumConnections() == 0) {
188  return;
189  }
190 
191  // Advance connections starting at the current connection index -1, to find
192  // the first valid connection with data.
193  if (!_AdvanceConnection(-1)) {
194  AdvanceToEnd();
195  }
196 }
197 
198 template<typename T>
200  const VdfContext &context,
201  const TfToken &inputName,
202  int connectionIndex,
203  unsigned int boxedIndex) :
204  _context(&context),
205  _input(_GetNode(context).GetInput(inputName)),
206  _connectionIndex(-1),
207  _boxedIndex(0)
208 {
209  // If the input is not valid, or the specified connection index is beyond
210  // the number of available connections, this iterator is at-end.
211  if (!_input ||
212  connectionIndex < 0 ||
213  static_cast<size_t>(connectionIndex) >= _input->GetNumConnections()) {
214  return;
215  }
216 
217  // Advance to the next valid connection starting at the previous connection
218  // index. If the previous connection index is -1, find the first valid
219  // connection.
220  if (!_AdvanceConnection(connectionIndex - 1) ||
221  !_SetCurrentBoxedIndex(boxedIndex)) {
222  AdvanceToEnd();
223  }
224 }
225 
226 template<typename T>
227 bool
229 {
230  return
231  _input == rhs._input &&
232  _connectionIndex == rhs._connectionIndex &&
233  _boxedIndex == rhs._boxedIndex &&
234  _iterator == rhs._iterator;
235 }
236 
237 template<typename T>
240 {
241  // Are we already at end()?
242  if (IsAtEnd()) {
243  return *this;
244  }
245 
246  // If not, advance to the next input.
247  if (!_Advance()) {
248  AdvanceToEnd();
249  }
250 
251  return *this;
252 }
253 
254 template<typename T>
257 {
258  TF_DEV_AXIOM(!IsAtEnd());
259  const size_t idx = *_iterator + _boxedIndex;
260 
261  TF_DEV_AXIOM(idx < _accessor.GetNumValues());
262  return &_accessor[idx];
263 }
264 
265 template<typename T>
266 size_t
268 {
269  // Bail out immediately if there is no data to iterate over.
270  if (!_input || _input->GetNumConnections() == 0) {
271  return 0;
272  }
273 
274  // Fast path for single connection, boxed values.
275  if (_input->GetNumConnections() == 1 && _accessor.IsBoxed()) {
276  return _accessor.GetNumValues();
277  }
278 
279  // Iterate over all the connections on the input connector.
280  size_t size = 0;
281  for (const VdfConnection *connection : _input->GetConnections()) {
282 
283  // For connections with 1x1 masks, we could be dealing with boxed
284  // values, so we need to look at the stored value to figure out the
285  // actual number of data values provided.
286  const VdfMask &mask = connection->GetMask();
287  if (mask.GetSize() == 1 && mask.IsAllOnes()) {
288 
289  // If this is a scheduled input value, account for the total number
290  // of data values provided by the boxed container.
291  if (_IsRequiredInput(*_context, *connection)) {
292 
293  if (const VdfVector *v =
294  _GetInputValue(*_context, *connection, mask)) {
295  VdfVector::ReadAccessor<T> accessor =
296  v->template GetReadAccessor<T>();
297  size += accessor.GetNumValues();
298  }
299  }
300  }
301 
302  // For all other masks, the number of entries set in the mask is the
303  // number of input values provided.
304  else {
305  size += mask.GetNumSet();
306  }
307  }
308 
309  // Return the number of input values provided.
310  return size;
311 }
312 
313 template<typename T>
314 void
316 {
317  _connectionIndex = -1;
318  _boxedIndex = 0;
319  _iterator = VdfMask::iterator();
320 }
321 
322 template<typename T>
323 bool
325 {
326  const VdfConnection &connection = (*_input)[connectionIndex];
327  const VdfMask &mask = connection.GetMask();
328 
329  // Reset all indices.
330  _connectionIndex = connectionIndex;
331  _boxedIndex = 0;
332  _iterator = mask.begin();
333 
334  // Reset the accessor
335  _accessor = VdfVector::ReadAccessor<T>();
336 
337  // See if the connection's source output is scheduled. This is not a
338  // valid connection, if the source output is not scheduled.
339  if (!_IsRequiredInput(*_context, connection)) {
340  return false;
341  }
342 
343  // Get the accessor to the data.
344  const VdfVector *data = _GetInputValue(*_context, connection, mask);
345  if (!data) {
346  return false;
347  }
348  _accessor = data->GetReadAccessor<T>();
349 
350  // Return false if the connection does not provide any values.
351  if (!_accessor.GetNumValues()) {
352  return false;
353  }
354 
355  // This is a valid connection if the iterator is valid.
356  return !_iterator.IsAtEnd();
357 }
358 
359 template<typename T>
360 bool
361 VdfReadIterator<T>::_SetCurrentBoxedIndex(unsigned int boxedIndex)
362 {
363  // If the boxed index exceeds the number of available input values, move on
364  // to the next valid connection, if any.
365  if (boxedIndex >= _accessor.GetNumValues()) {
366  return _AdvanceConnection(_connectionIndex);
367  }
368 
369  // Apply the boxed index.
370  _boxedIndex = boxedIndex;
371 
372  // Success!
373  return true;
374 }
375 
376 template<typename T>
377 bool
379 {
380  // When iterating over boxed values, increment the index into the boxed
381  // container.
382  if (_accessor.IsBoxed()) {
383  ++_boxedIndex;
384 
385  // After the last element in the boxed container, move on to the next
386  // connection.
387  if (_boxedIndex >= _accessor.GetNumValues()) {
388  return _AdvanceConnection(_connectionIndex);
389  }
390  }
391 
392  // When iterating over values that are not boxed, increment the mask
393  // iterator.
394  else {
395  ++_iterator;
396 
397  // After the last entry in the mask, move on to the next connection.
398  if (_iterator.IsAtEnd()) {
399  return _AdvanceConnection(_connectionIndex);
400  }
401  }
402 
403  // Successfully reached the next input value.
404  return true;
405 }
406 
407 template<typename T>
408 bool
409 VdfReadIterator<T>::_AdvanceConnection(int connectionIndex)
410 {
411  // Note that we start at '_connectionIndex + 1' because we have already
412  // iterated through the mask of the current connection.
413  const int numConnections = _input->GetNumConnections();
414  for (int i = connectionIndex + 1; i < numConnections; ++i) {
415 
416  // If the next connection has a scheduled data source, we are done.
417  // Skip any data sources that provide no values.
418  if (_SetCurrentConnection(i)) {
419  return true;
420  }
421  }
422 
423  return false;
424 }
425 
427 
428 #endif
value_type * pointer
Definition: readIterator.h:56
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
const GLdouble * v
Definition: glcorearb.h:837
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
size_t GetNumConnections() const
Definition: input.h:58
VdfReadIterator(const VdfContext &context, const TfToken &inputName)
Definition: readIterator.h:177
size_t ComputeSize() const
Definition: readIterator.h:267
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
reference operator*() const
Definition: readIterator.h:84
VdfReadIterator & operator++()
Definition: readIterator.h:239
Definition: input.h:35
bool IsAtEnd() const
Definition: readIterator.h:95
#define TF_DEV_AXIOM(cond)
Definition: token.h:70
value_type & reference
Definition: readIterator.h:52
pointer operator->() const
Definition: readIterator.h:256
bool Vdf_IsPoolOutput(const VdfOutput &output)
friend bool Vdf_IsIteratorSourcePool(const VdfReadIterator &it)
Definition: readIterator.h:127
GLint GLuint mask
Definition: glcorearb.h:124
std::forward_iterator_tag iterator_category
Definition: readIterator.h:60
size_t GetSize() const
Definition: mask.h:158
GLsizeiptr size
Definition: glcorearb.h:664
GLenum void ** pointer
Definition: glcorearb.h:810
ReadAccessor< TYPE > GetReadAccessor() const
Definition: vector.h:521
size_t GetNumSet() const
Definition: mask.h:246
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool operator!=(const VdfReadIterator &rhs) const
Definition: readIterator.h:72
bool operator==(const VdfReadIterator &rhs) const
Definition: readIterator.h:228
bool IsAllOnes() const
Definition: mask.h:196
size_t GetNumValues() const
Definition: vector.h:489
const T value_type
Definition: readIterator.h:44
const VdfMask & GetMask() const
Returns the mask for this connection.
Definition: connection.h:99
Definition: format.h:1821
iterator begin() const
Definition: mask.h:482
friend int Vdf_GetIteratorIndex(const VdfReadIterator &it)
Definition: readIterator.h:122