Loading...
Searching...
No Matches
subrangeView.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_SUBRANGE_VIEW_H
8#define PXR_EXEC_VDF_SUBRANGE_VIEW_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/exec/vdf/boxedContainer.h"
17#include "pxr/exec/vdf/input.h"
18#include "pxr/exec/vdf/node.h"
20#include "pxr/exec/vdf/vectorSubrangeAccessor.h"
21
22#include <iterator>
23
24PXR_NAMESPACE_OPEN_SCOPE
25
26class TfToken;
27class VdfContext;
28template<typename> class VdfSubrangeView;
29
61template<typename T>
63{
64public:
65
68 using Subrange = VdfReadIteratorRange<T>;
69
73 VdfSubrangeView(const VdfContext &context, const TfToken &inputName) :
74 _context(&context),
75 _inputName(inputName)
76 {}
77
80 class const_iterator
81 {
82 public:
83
86 using value_type = const Subrange;
87
91
95
98 using iterator_category = std::forward_iterator_tag;
99
102 bool operator==(const const_iterator &rhs) const;
103
106 bool operator!=(const const_iterator &rhs) const {
107 return !operator==(rhs);
108 }
109
113 const_iterator &operator++();
114
118 return _subrange;
119 }
120
124 return &_subrange;
125 }
126
127 private:
128
129 // Only VdfSubrangeView is allowed to construct instances of this class.
130 friend class VdfSubrangeView;
131
132 // Construct an iterator owned by the specified view at the given
133 // connection index. Constructs an iterator at-end if connectionIndex is
134 // less than 0.
135 const_iterator(const VdfSubrangeView &view, int connectionIndex);
136
137 // Sets the subrange from the currently set connection- and range index.
138 void _AdvanceSubrange(unsigned int rangeIndex);
139
140 // Set the subrange from the currently set connection.
141 bool _SubrangeFromConnectionIndex(
142 const VdfContext &context,
143 const TfToken &inputName);
144
145 // Sets the subrange from the currently set range index.
146 bool _SubrangeFromRangeIndex(
147 const VdfContext &context,
148 const TfToken &inputName,
149 const Vdf_VectorSubrangeAccessor<T> &accessor);
150
151 // Returns a subrange that is at-end, i.e. an empty range with both
152 // begin and end iterators at-end.
153 Subrange _SubrangeAtEnd();
154
155 // Advances this iterator to the end.
156 void _AdvanceToEnd();
157
158 // The view owning this iterator.
159 const VdfSubrangeView *_view;
160
161 // The current connection index.
162 int _connectionIndex;
163
164 // The current range index within the connection.
165 unsigned int _rangeIndex;
166
167 // The current iterator subrange.
168 Subrange _subrange;
169
170 };
171
175 const_iterator begin() const {
176 return const_iterator(*this, 0);
177 }
178
182 const_iterator end() const {
183 return const_iterator(*this, -1);
184 }
185
186private:
187
188 // A pointer to the context instance.
189 const VdfContext *_context;
190
191 // The name token of the input to build subranges for. Must extend the
192 // lifetime of the token.
193 const TfToken _inputName;
194
195};
196
198
199template<typename T>
200VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::const_iterator(
201 const VdfSubrangeView &view,
202 int connectionIndex) :
203 _view(&view),
204 _connectionIndex(connectionIndex),
205 _rangeIndex(0),
206 _subrange(_SubrangeAtEnd())
207{
208 // If we have a valid connection index, advance to the first valid subrange.
209 if (connectionIndex >= 0) {
210 _AdvanceSubrange(0);
211 }
212}
213
214template<typename T>
215bool
216VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::operator==(
217 const const_iterator &rhs) const
218{
219 return
220 _view->_inputName == rhs._view->_inputName &&
221 _connectionIndex == rhs._connectionIndex &&
222 _rangeIndex == rhs._rangeIndex;
223}
224
225template<typename T>
226typename VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator &
227VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::operator++()
228{
229 // Advance to the next subrange.
230 _AdvanceSubrange(_rangeIndex + 1);
231 return *this;
232}
233
234template<typename T>
235void
236VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_AdvanceSubrange(
237 unsigned int rangeIndex)
238{
239 const VdfContext &context = *_view->_context;
240 const TfToken &inputName = _view->_inputName;
241 const VdfInput *input = _view->_GetNode(context).GetInput(inputName);
242
243 // Set the next range index.
244 _rangeIndex = rangeIndex;
245
246 // If we have a valid input and connection index, set the current subrange.
247 if (input && _connectionIndex >= 0) {
248
249 // Start with the current connection, and keep moving on to the next
250 // connection until we have found the current subrange, or have reached
251 // the last connection.
252 const int numConnections = input->GetNumConnections();
253 for (; _connectionIndex < numConnections; ++_connectionIndex) {
254
255 // Get the connection and mask.
256 const VdfConnection &c = (*input)[_connectionIndex];
257 const VdfMask &mask = c.GetMask();
258
259 // If the mask is all zeros or if the connected output is not
260 // required, move on to the next connection.
261 if (mask.IsAllZeros() || !_view->_IsRequiredInput(context, c)) {
262 continue;
263 }
264
265 // If the connected output does not provide a value, try to set
266 // an empty subrange from the current connection.
267 const VdfVector *v = _view->_GetInputValue(context, c, mask);
268 if (!v) {
269 if (_SubrangeFromConnectionIndex(context, inputName)) {
270 return;
271 }
272 } else {
273 const Vdf_VectorSubrangeAccessor<T> accessor =
274 v->GetSubrangeAccessor<T>();
275
276 // If the current connection does not provide a boxed value, try
277 // to set the subrange from the current connection.
278 if (!accessor.IsBoxed()) {
279 if (_SubrangeFromConnectionIndex(context, inputName)) {
280 return;
281 }
282 }
283
284 // If the current connection provides a boxed value, try to set
285 // the subrange from the boxed container provided on the current
286 // connection.
287 else {
288 if (_SubrangeFromRangeIndex(context, inputName, accessor)) {
289 return;
290 }
291 }
292 }
293
294 // The subrange is not on the current connection. Reset the range
295 // index and move on to the next connection.
296 _rangeIndex = 0;
297 }
298 }
299
300 // If we have not found a single valid connection, there are no more
301 // subranges. We have reached the end.
302 _AdvanceToEnd();
303}
304
305template<typename T>
306bool
308 _SubrangeFromConnectionIndex(
309 const VdfContext &context,
310 const TfToken &inputName)
311{
312 using Iterator = typename Subrange::iterator;
313
314 // If the current range index exceeds the number of ranges provided on this
315 // connection (non-boxed values only provide a single range), we need to
316 // move on to the next connection.
317 if (_rangeIndex > 0) {
318 return false;
319 }
320
321 // Build an iterator range beginning at the current connection, and ending
322 // at the next connection.
323 _subrange = Subrange(
324 Iterator(context, inputName, _connectionIndex, 0),
325 Iterator(context, inputName, _connectionIndex + 1, 0));
326
327 return true;
328}
329
330template<typename T>
331bool
333 _SubrangeFromRangeIndex(
334 const VdfContext &context,
335 const TfToken &inputName,
336 const Vdf_VectorSubrangeAccessor<T> &accessor)
337{
338 using Iterator = typename Subrange::iterator;
339
340 // Get the boxed container provided by the current connection value.
341 const Vdf_BoxedRanges &boxedRanges = accessor.GetBoxedRanges();
342
343 // If the current range index exceeds the number of ranges provided on this
344 // connection (boxed values can provide multiple ranges), we need to move
345 // on to the next connection.
346 if (_rangeIndex >= boxedRanges.GetNumRanges()) {
347 return false;
348 }
349
350 // Get the boxed container range that corresponds to the current
351 // range index.
352 const Vdf_BoxedRanges::Range boxedRange = boxedRanges.GetRange(_rangeIndex);
353
354 // Build an iterator range beginning at the current connection (offset by
355 // the beginning of the boxed range), and ending at the current connection
356 // (offset by the end of the boxed range.)
357 _subrange = Subrange(
358 Iterator(context, inputName, _connectionIndex, boxedRange.begin),
359 Iterator(context, inputName, _connectionIndex, boxedRange.end));
360
361 return true;
362}
363
364template<typename T>
366VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_SubrangeAtEnd()
367{
368 using Iterator = typename Subrange::iterator;
369
370 return Subrange(
371 Iterator(*_view->_context, _view->_inputName, -1, 0),
372 Iterator(*_view->_context, _view->_inputName, -1, 0));
373}
374
375template<typename T>
376void
377VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_AdvanceToEnd()
378{
379 _connectionIndex = -1;
380 _rangeIndex = 0;
381 _subrange = _SubrangeAtEnd();
382}
383
384PXR_NAMESPACE_CLOSE_SCOPE
385
386#endif
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:71
Each range represents a logical group of elements stored in a Vdf_BoxedContainer.
Range GetRange(unsigned int i) const
Returns the range at index i.
unsigned int GetNumRanges() const
Returns the number of individual ranges stored in this container.
A range of data elements as denoted by [ begin, end ) indices.
Specialized vector accessor for read access to boxed containers.
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
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:37
bool IsAllZeros() const
Returns true if this mask has all entries unset.
Definition: mask.h:206
This class allows for construction of iterable ranges of input values.
std::forward_iterator_tag iterator_category
The STL category of this iterator type.
Definition: subrangeView.h:98
bool operator!=(const const_iterator &rhs) const
Returns true if this iterator and rhs do not compare equal.
Definition: subrangeView.h:106
reference operator*() const
Returns a reference to the current subrange of input values.
Definition: subrangeView.h:117
pointer operator->() const
Returns a pointer to the current subrange of input values.
Definition: subrangeView.h:123
This class enables iteration over subranges of input values, where each subrange contains values orig...
Definition: subrangeView.h:28
This class is used to abstract away knowledge of the cache data used for each node.
Definition: vector.h:56
Vdf_VectorSubrangeAccessor< TYPE > GetSubrangeAccessor() const
Provide read-only access to the boxed subranges held by this vector.
Definition: vector.h:525