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 return
104 _view->_inputName == rhs._view->_inputName &&
105 _connectionIndex == rhs._connectionIndex &&
106 _rangeIndex == rhs._rangeIndex;
107 }
108
111 bool operator!=(const const_iterator &rhs) const {
112 return !operator==(rhs);
113 }
114
118 const_iterator &operator++();
119
123 return _subrange;
124 }
125
129 return &_subrange;
130 }
131
132 private:
133
134 // Only VdfSubrangeView is allowed to construct instances of this class.
135 friend class VdfSubrangeView;
136
137 // Construct an iterator owned by the specified view at the given
138 // connection index. Constructs an iterator at-end if connectionIndex is
139 // less than 0.
140 const_iterator(const VdfSubrangeView &view, int connectionIndex);
141
142 // Sets the subrange from the currently set connection- and range index.
143 void _AdvanceSubrange(unsigned int rangeIndex);
144
145 // Set the subrange from the currently set connection.
146 bool _SubrangeFromConnectionIndex(
147 const VdfContext &context,
148 const TfToken &inputName);
149
150 // Sets the subrange from the currently set range index.
151 bool _SubrangeFromRangeIndex(
152 const VdfContext &context,
153 const TfToken &inputName,
154 const Vdf_VectorSubrangeAccessor<T> &accessor);
155
156 // Returns a subrange that is at-end, i.e. an empty range with both
157 // begin and end iterators at-end.
158 Subrange _SubrangeAtEnd();
159
160 // Advances this iterator to the end.
161 void _AdvanceToEnd();
162
163 // The view owning this iterator.
164 const VdfSubrangeView *_view;
165
166 // The current connection index.
167 int _connectionIndex;
168
169 // The current range index within the connection.
170 unsigned int _rangeIndex;
171
172 // The current iterator subrange.
173 Subrange _subrange;
174
175 };
176
180 const_iterator begin() const {
181 return const_iterator(*this, 0);
182 }
183
187 const_iterator end() const {
188 return const_iterator(*this, -1);
189 }
190
191private:
192
193 // A pointer to the context instance.
194 const VdfContext *_context;
195
196 // The name token of the input to build subranges for. Must extend the
197 // lifetime of the token.
198 const TfToken _inputName;
199
200};
201
203
204template<typename T>
205VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::const_iterator(
206 const VdfSubrangeView &view,
207 int connectionIndex) :
208 _view(&view),
209 _connectionIndex(connectionIndex),
210 _rangeIndex(0),
211 _subrange(_SubrangeAtEnd())
212{
213 // If we have a valid connection index, advance to the first valid subrange.
214 if (connectionIndex >= 0) {
215 _AdvanceSubrange(0);
216 }
217}
218
219template<typename T>
220typename VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator &
221VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::operator++()
222{
223 // Advance to the next subrange.
224 _AdvanceSubrange(_rangeIndex + 1);
225 return *this;
226}
227
228template<typename T>
229void
230VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_AdvanceSubrange(
231 unsigned int rangeIndex)
232{
233 const VdfContext &context = *_view->_context;
234 const TfToken &inputName = _view->_inputName;
235 const VdfInput *input = _view->_GetNode(context).GetInput(inputName);
236
237 // Set the next range index.
238 _rangeIndex = rangeIndex;
239
240 // If we have a valid input and connection index, set the current subrange.
241 if (input && _connectionIndex >= 0) {
242
243 // Start with the current connection, and keep moving on to the next
244 // connection until we have found the current subrange, or have reached
245 // the last connection.
246 const int numConnections = input->GetNumConnections();
247 for (; _connectionIndex < numConnections; ++_connectionIndex) {
248
249 // Get the connection and mask.
250 const VdfConnection &c = (*input)[_connectionIndex];
251 const VdfMask &mask = c.GetMask();
252
253 // If the mask is all zeros or if the connected output is not
254 // required, move on to the next connection.
255 if (mask.IsAllZeros() || !_view->_IsRequiredInput(context, c)) {
256 continue;
257 }
258
259 // If the connected output does not provide a value, try to set
260 // an empty subrange from the current connection.
261 const VdfVector *v = _view->_GetInputValue(context, c, mask);
262 if (!v) {
263 if (_SubrangeFromConnectionIndex(context, inputName)) {
264 return;
265 }
266 } else {
267 const Vdf_VectorSubrangeAccessor<T> accessor =
268 v->GetSubrangeAccessor<T>();
269
270 // If the current connection does not provide a boxed value, try
271 // to set the subrange from the current connection.
272 if (!accessor.IsBoxed()) {
273 if (_SubrangeFromConnectionIndex(context, inputName)) {
274 return;
275 }
276 }
277
278 // If the current connection provides a boxed value, try to set
279 // the subrange from the boxed container provided on the current
280 // connection.
281 else {
282 if (_SubrangeFromRangeIndex(context, inputName, accessor)) {
283 return;
284 }
285 }
286 }
287
288 // The subrange is not on the current connection. Reset the range
289 // index and move on to the next connection.
290 _rangeIndex = 0;
291 }
292 }
293
294 // If we have not found a single valid connection, there are no more
295 // subranges. We have reached the end.
296 _AdvanceToEnd();
297}
298
299template<typename T>
300bool
302 _SubrangeFromConnectionIndex(
303 const VdfContext &context,
304 const TfToken &inputName)
305{
306 using Iterator = typename Subrange::iterator;
307
308 // If the current range index exceeds the number of ranges provided on this
309 // connection (non-boxed values only provide a single range), we need to
310 // move on to the next connection.
311 if (_rangeIndex > 0) {
312 return false;
313 }
314
315 // Build an iterator range beginning at the current connection, and ending
316 // at the next connection.
317 _subrange = Subrange(
318 Iterator(context, inputName, _connectionIndex, 0),
319 Iterator(context, inputName, _connectionIndex + 1, 0));
320
321 return true;
322}
323
324template<typename T>
325bool
327 _SubrangeFromRangeIndex(
328 const VdfContext &context,
329 const TfToken &inputName,
330 const Vdf_VectorSubrangeAccessor<T> &accessor)
331{
332 using Iterator = typename Subrange::iterator;
333
334 // Get the boxed container provided by the current connection value.
335 const Vdf_BoxedRanges &boxedRanges = accessor.GetBoxedRanges();
336
337 // If the current range index exceeds the number of ranges provided on this
338 // connection (boxed values can provide multiple ranges), we need to move
339 // on to the next connection.
340 if (_rangeIndex >= boxedRanges.GetNumRanges()) {
341 return false;
342 }
343
344 // Get the boxed container range that corresponds to the current
345 // range index.
346 const Vdf_BoxedRanges::Range boxedRange = boxedRanges.GetRange(_rangeIndex);
347
348 // Build an iterator range beginning at the current connection (offset by
349 // the beginning of the boxed range), and ending at the current connection
350 // (offset by the end of the boxed range.)
351 _subrange = Subrange(
352 Iterator(context, inputName, _connectionIndex, boxedRange.begin),
353 Iterator(context, inputName, _connectionIndex, boxedRange.end));
354
355 return true;
356}
357
358template<typename T>
360VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_SubrangeAtEnd()
361{
362 using Iterator = typename Subrange::iterator;
363
364 return Subrange(
365 Iterator(*_view->_context, _view->_inputName, -1, 0),
366 Iterator(*_view->_context, _view->_inputName, -1, 0));
367}
368
369template<typename T>
370void
371VdfSubrangeView<VdfReadIteratorRange<T>>::const_iterator::_AdvanceToEnd()
372{
373 _connectionIndex = -1;
374 _rangeIndex = 0;
375 _subrange = _SubrangeAtEnd();
376}
377
378PXR_NAMESPACE_CLOSE_SCOPE
379
380#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:111
bool operator==(const const_iterator &rhs) const
Returns true if this iterator and rhs compare equal.
Definition: subrangeView.h:102
reference operator*() const
Returns a reference to the current subrange of input values.
Definition: subrangeView.h:122
pointer operator->() const
Returns a pointer to the current subrange of input values.
Definition: subrangeView.h:128
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