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.
int difference_type
The type used to identify distance between instances of this iterator.
VdfReadIterator & operator++()
Increment operator to point to the next element.
const T value_type
Type of the elements this iterator gives access to.
VdfReadIterator(const VdfContext &context, const TfToken &inputName)
Constructs a read iterator.
bool operator!=(const VdfReadIterator &rhs) const
Returns true if this iterator and rhs do not compare equal.
bool IsAtEnd() const
Returns true if the iterator is done iterating and false otherwise.
void AdvanceToEnd()
Advance the iterator to the end.
std::forward_iterator_tag iterator_category
The STL category of this iterator type.
value_type * pointer
Type of a pointer to a value of this iterator.
bool operator==(const VdfReadIterator &rhs) const
Returns true if this iterator and rhs compare equal.
size_t ComputeSize() const
Returns the total number of data elements that will be iterated over.
value_type & reference
Type of a reference to a value of this iterator.
pointer operator->() const
Returns pointer to current element.
reference operator*() const
Returns reference to current element.
This class enables iteration over subranges of input values, where each subrange contains values orig...
A read-only accessor for low-level acces to the contents of the VdfVector.
Definition vector.h:476
size_t GetNumValues() const
Returns the size of the vector, i.e.
Definition vector.h:489
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:521
#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,...