Loading...
Searching...
No Matches
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
11
12#include "pxr/pxr.h"
13
16#include "pxr/exec/vdf/node.h"
18#include "pxr/exec/vdf/vector.h"
19
21
22#include <iterator>
23
24PXR_NAMESPACE_OPEN_SCOPE
25
37template<typename T>
39{
40public:
41
44 using value_type = const T;
45
48 using difference_type = int;
49
53
57
60 using iterator_category = std::forward_iterator_tag;
61
64 VdfReadIterator(const VdfContext &context, const TfToken &inputName);
65
68 bool operator==(const VdfReadIterator &rhs) const;
69
72 bool operator!=(const VdfReadIterator &rhs) const {
73 return !operator==(rhs);
74 }
75
80
85 return *operator->();
86 }
87
91 pointer operator->() const;
92
95 bool IsAtEnd() const {
96 return _connectionIndex == -1;
97 }
98
101 size_t ComputeSize() const;
102
105 void AdvanceToEnd();
106
107private:
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.
171
172};
173
175
176template<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
198template<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
226template<typename T>
227bool
229{
230 return
231 _input == rhs._input &&
232 _connectionIndex == rhs._connectionIndex &&
233 _boxedIndex == rhs._boxedIndex &&
234 _iterator == rhs._iterator;
235}
236
237template<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
254template<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
265template<typename T>
266size_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)) {
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
313template<typename T>
314void
316{
317 _connectionIndex = -1;
318 _boxedIndex = 0;
319 _iterator = VdfMask::iterator();
320}
321
322template<typename T>
323bool
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
359template<typename T>
360bool
361VdfReadIterator<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
376template<typename T>
377bool
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
407template<typename T>
408bool
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
426PXR_NAMESPACE_CLOSE_SCOPE
427
428#endif
Low-level utilities for informing users of various internal and external diagnostic conditions.
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
A class that fully represents a connection between two VdfNodes.
Definition: connection.h:30
const VdfMask & GetMask() const
Returns the mask for this connection.
Definition: connection.h:99
A context is the parameter bundle passed to callbacks of computations.
Definition: context.h:40
A VdfInput is used to connect a VdfNode to one or more VdfNodes' outputs.
Definition: input.h:36
size_t GetNumConnections() const
Returns the number of connections for this input.
Definition: input.h:58
Base class for libVdf iterators.
Definition: iterator.h:36
Iterator class used to iterate through the elements of the mask.
Definition: mask.h:399
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
iterator begin() const
Returns an iterator that can be used to iterate through the elements of the mask.
Definition: mask.h:482
bool IsAllOnes() const
Returns true if this mask has all entries set.
Definition: mask.h:196
size_t GetNumSet() const
Returns the number of set bits in the mask.
Definition: mask.h:246
An iterator that provides read access to input values using a context.
Definition: readIterator.h:39
int difference_type
The type used to identify distance between instances of this iterator.
Definition: readIterator.h:48
VdfReadIterator & operator++()
Increment operator to point to the next element.
Definition: readIterator.h:239
const T value_type
Type of the elements this iterator gives access to.
Definition: readIterator.h:44
VdfReadIterator(const VdfContext &context, const TfToken &inputName)
Constructs a read iterator.
Definition: readIterator.h:177
bool operator!=(const VdfReadIterator &rhs) const
Returns true if this iterator and rhs do not compare equal.
Definition: readIterator.h:72
bool IsAtEnd() const
Returns true if the iterator is done iterating and false otherwise.
Definition: readIterator.h:95
void AdvanceToEnd()
Advance the iterator to the end.
Definition: readIterator.h:315
std::forward_iterator_tag iterator_category
The STL category of this iterator type.
Definition: readIterator.h:60
value_type * pointer
Type of a pointer to a value of this iterator.
Definition: readIterator.h:56
bool operator==(const VdfReadIterator &rhs) const
Returns true if this iterator and rhs compare equal.
Definition: readIterator.h:228
size_t ComputeSize() const
Returns the total number of data elements that will be iterated over.
Definition: readIterator.h:267
value_type & reference
Type of a reference to a value of this iterator.
Definition: readIterator.h:52
pointer operator->() const
Returns pointer to current element.
Definition: readIterator.h:256
reference operator*() const
Returns reference to current element.
Definition: readIterator.h:84
This class enables iteration over subranges of input values, where each subrange contains values orig...
Definition: subrangeView.h:28
A read-only accessor for low-level acces to the contents of the VdfVector.
Definition: vector.h:469
size_t GetNumValues() const
Returns the size of the vector, i.e.
Definition: vector.h:482
This class is used to abstract away knowledge of the cache data used for each node.
Definition: vector.h:56
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:514
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition: diagnostic.h:205
bool Vdf_IsPoolOutput(const VdfOutput &output)
Returns true if output is a pool output, i.e., an output that has an associated input,...