HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sparseVectorizedInputTraverser.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_SPARSE_VECTORIZED_INPUT_TRAVERSER_H
8 #define PXR_EXEC_VDF_SPARSE_VECTORIZED_INPUT_TRAVERSER_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/vdf/api.h"
17 #include "pxr/exec/vdf/object.h"
20 
22 #include "pxr/base/tf/hashmap.h"
23 #include "pxr/base/tf/stl.h"
24 
25 #include <functional>
26 #include <unordered_map>
27 #include <vector>
28 
30 
31 class VdfNode;
32 
33 /// \class VdfSparseVectorizedInputTraverser
34 ///
35 /// \brief A class used for fast sparse traversals of VdfNetworks in the
36 /// output-to-input direction in a vectorized manner.
37 ///
38 /// A sparse traversal takes affects masks into account and avoids
39 /// traversing nodes that don't have an affect on the outputs
40 /// requested for the traversal. This is most often useful for
41 /// dependency traversals.
42 ///
43 /// In contrast, VdfIsTopologicalSourceNode() does a full topological
44 /// traversal.
45 ///
47 {
48 public:
49 
50  /// Callback mode for the node callback.
52  {
53  /// Invoke the node callback on all inputs. This is the default.
55 
56  /// Invoke the node callback only on terminal nodes.
58  };
59 
60  /// \name Basic Traversal
61  /// @{
62 
63  /// Callback used when traversing a network.
64  ///
65  /// Called for each node that is visited that affects values of the initial
66  /// requests. The TfBits parameter is used to identify which requests
67  /// caused the callback to be called.
68  ///
69  /// A return value of false halts traversal locally but allows prior
70  /// branches of traversal to continue.
71  ///
72  using NodeCallback = std::function<
73  bool (const VdfNode &, const TfBits &)>;
74 
75  /// Traverses the network in the input direction, starting from the
76  /// masked outputs in \p sharedMaskedOutputs.
77  ///
78  /// Calls \p nodeCallback for each node visited in the sparse
79  /// traversal.
80  ///
81  /// If \p callbackMode is set to CallbackModeTerminalNodes, then the
82  /// \p nodeCallback is only invoked on terminal nodes (i.e. nodes without
83  /// input connections). If it is set to CallbackModeAllNodes (which is the
84  /// default), then the callback is invoked on all nodes that are visited
85  /// by the traverser.
86  ///
87  /// If the callback returns \c false, then traversal halts locally
88  /// but prior branches of traversal continue.
89  ///
90  VDF_API
91  void Traverse(
92  const VdfMaskedOutputVector &sharedMaskedOutputs,
93  const NodeCallback &nodeCallback,
94  CallbackMode callbackMode);
95 
96  /// Callback used when traversing a network.
97  ///
98  /// Called for each connection that is visited that affects values of the
99  /// initial requests. The TfBits parameter is used to identify which
100  /// requests caused the callback to be called.
101  ///
102  /// A return value of false halts traversal locally but allows prior
103  /// branches of traversal to continue.
104  ///
105  using ConnectionCallback = std::function<
106  bool (const VdfConnection &, const TfBits &)>;
107 
108  /// Traverses the network in the input direction, starting from the
109  /// masked outputs in \p sharedMaskedOutputs.
110  ///
111  /// Calls \p connectionCallback for each connection visited in the sparse
112  /// traversal.
113  ///
114  /// If the callback returns \c false, then traversal halts locally
115  /// but prior branches of traversal continue.
116  ///
117  VDF_API
119  const VdfMaskedOutputVector &sharedMaskedOutputs,
120  const ConnectionCallback &connectionCallback);
121 
122  /// @}
123 
124 private:
125 
126  // Helper class that holds a set of unique masks along with their request
127  // bits.
128  class _MasksToRequestsMap
129  {
130  // Map of unique masks to request indices using them.
131  typedef
133  _MaskToRequestBitsMap;
134 
135  public:
136 
137  // Ctor to initialize an empty object.
138  _MasksToRequestsMap(size_t numRequests = 0)
139  : _numRequests(numRequests) {}
140 
141  // Ctor to initialize /w a single \p mask and \p requestBits.
142  _MasksToRequestsMap(const VdfMask &mask, const TfBits &requestBits)
143  : _numRequests(requestBits.GetSize()) {
144  _maskToRequestBitsMap[mask] = requestBits;
145  }
146 
147  // Adds \p mask @ \p requestIndex.
148  void AddMask(const VdfMask &mask, size_t requestIndex) {
149 
150  static TfBits empty;
151 
152  std::pair<_MaskToRequestBitsMap::iterator, bool> res =
153  _maskToRequestBitsMap.insert(std::make_pair(mask, empty));
154 
155  if (res.second) {
156  res.first->second.Resize(_numRequests);
157  res.first->second.ClearAll();
158  }
159 
160  TF_VERIFY(!res.first->second.IsSet(requestIndex));
161  res.first->second.Set(requestIndex);
162  }
163 
164  // Adds \p mask with \p requestBits.
165  void AddMask(const VdfMask &mask, const TfBits &requestBits) {
166 
167  std::pair<_MaskToRequestBitsMap::iterator, bool> res =
168  _maskToRequestBitsMap.insert(std::make_pair(mask, requestBits));
169 
170  // If we didn't succeed to insert mask as a new entry, we must merge
171  // in our new requestBits.
172 
173  if (!res.second)
174  res.first->second |= requestBits;
175  }
176 
177  // Iteration support.
178  typedef _MaskToRequestBitsMap::const_iterator const_iterator;
179 
180  const_iterator begin() const {
181  return _maskToRequestBitsMap.begin();
182  }
183 
184  const_iterator end() const {
185  return _maskToRequestBitsMap.end();
186  }
187 
188  // Returns the request bits for \p mask. Note that mask doesn't need
189  // to be an exact match.
190  const TfBits *GetRequestBits(const VdfMask &mask) const;
191 
192  private:
193 
194  size_t _numRequests;
195 
196  _MaskToRequestBitsMap _maskToRequestBitsMap;
197  };
198 
199  // Helper to kick off the traversal.
200  void _Traverse(const VdfMaskedOutputVector &sharedMaskedOutputs);
201 
202  // Helper to traverse an output.
203  void _TraverseOutput(
204  const VdfOutput *output,
205  const _MasksToRequestsMap &masks);
206 
207 private:
208 
209  // The callback to use.
210  NodeCallback _nodeCallback;
211  ConnectionCallback _connectionCallback;
212 
213  // The current callback mode.
214  CallbackMode _callbackMode;
215 
216  // Type used to identify the masks/request-bits that have already been
217  // visited for traversed connections. Note that we can't bunch together
218  // all seen dependency bits along all seen request bits, because we could
219  // have say two cycles through a single connection. The first cycle would
220  // manage to set all dependency bits there are and when the second cycle
221  // for different request bits visits the connection the second time (since
222  // there are two cycles) we would believe we would have seen that second
223  // request with the second dependency mask already.
224 
225  typedef
227  _VisitedConnections;
228 
229  _VisitedConnections _visitedConnections;
230 
231  // The traversal stack frames, used as the stack. We are using an
232  // unordered_map, because begin() will be called frequently and entries
233  // will be erased from the front of the map.
234  typedef
235  std::unordered_map<const VdfOutput *, _MasksToRequestsMap, TfHash>
236  _Stack;
237 
238  _Stack _stack;
239 
240  // A type used to represent an input in a priority queue.
241  typedef std::pair<const VdfOutput *, _MasksToRequestsMap> _PrioritizedOutput;
242 
243  // A map from pool chain index to prioritized output, used to ensure that we
244  // process outputs in their order in the pool chain.
245  //
246  // Note that using a std::map<> gives us the _PrioritizedOutputs sorted by
247  // the pool chain index (the int key).
248  //
249  typedef std::map<VdfPoolChainIndex, _PrioritizedOutput,
250  std::greater<VdfPoolChainIndex> > _PrioritizedOutputMap;
251 
252  _PrioritizedOutputMap _prioritizedOutputs;
253 
254  // Initialized, empty _MasksToRequestsMap.
255  _MasksToRequestsMap _emptyRequestToMaskMap;
256 };
257 
259 
260 #endif
_IteratorBase< const value_type, typename _Vector::const_iterator > const_iterator
Definition: denseHashMap.h:227
CallbackMode
Callback mode for the node callback.
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
Definition: node.h:52
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
#define VDF_API
Definition: api.h:25
OutGridT const XformOp bool bool
std::function< bool(const VdfConnection &, const TfBits &)> ConnectionCallback
A class used for fast sparse traversals of VdfNetworks in the output-to-input direction in a vectoriz...
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
Definition: bits.h:48
VDF_API void Traverse(const VdfMaskedOutputVector &sharedMaskedOutputs, const NodeCallback &nodeCallback, CallbackMode callbackMode)
GLuint GLuint end
Definition: glcorearb.h:475
GLint GLuint mask
Definition: glcorearb.h:124
void Resize(size_t num)
Definition: bits.h:185
Invoke the node callback on all inputs. This is the default.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:587
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
VDF_API void TraverseWithConnectionCallback(const VdfMaskedOutputVector &sharedMaskedOutputs, const ConnectionCallback &connectionCallback)
std::vector< VdfMaskedOutput > VdfMaskedOutputVector
std::function< bool(const VdfNode &, const TfBits &)> NodeCallback