HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sparseInputPathFinder.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_INPUT_PATH_FINDER_H
8 #define PXR_EXEC_VDF_SPARSE_INPUT_PATH_FINDER_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/vdf/api.h"
16 #include "pxr/exec/vdf/request.h"
17 
18 #include "pxr/base/tf/hash.h"
19 #include "pxr/base/tf/hashmap.h"
20 #include "pxr/base/tf/hashset.h"
22 
23 #include <vector>
24 
26 
27 class VdfNode;
28 
29 ////////////////////////////////////////////////////////////////////////////////
30 ///
31 /// \class VdfSparseInputPathFinder
32 ///
33 /// \brief A class used for fast sparse traversals of VdfNetworks in the
34 /// output-to-input direction when the goal is to find all possible
35 /// paths from an output to a node.
36 ///
37 /// A sparse traversal takes affects masks into account and avoids
38 /// traversing nodes that don't have an affect on the outputs
39 /// requested for the traversal. This is most often useful for
40 /// dependency traversals.
41 ///
42 /// Note that the main point here is to find all possible paths whereas
43 /// the VdfSparseInputTraverser reports only the first path it finds.
44 ///
46 {
47 public:
48 
49  /// Callback to determine if \p input is a relevant path.
50  ///
51  typedef bool (*InputCallback)(const VdfInput &input);
52 
53  /// Traverses the network in the input direction sparsely, starting from
54  /// \p start trying to find all possible paths into \p target.
55  ///
56  /// Will populate \p paths with the results.
57  ///
58  /// Uses \p inputCallback in order to determine which paths are relevant
59  /// and should be reported. The default implementation (used when \p
60  /// inputCallback is NULL) will treat no path as relevant. This makes
61  /// the VdfSparseInputPathFinder behave the same way as the sparse input
62  /// traverser. Only when \p inputCallback returns true for a specific
63  /// input a path will treated as a seperate path.
64  ///
65  VDF_API
66  static void Traverse(
67  const VdfMaskedOutput &start,
68  const VdfMaskedOutput &target,
69  InputCallback inputCallback,
70  std::vector<VdfConnectionConstVector> *paths);
71 
72  /// Convenience method for a common usage of Traverse() where start ==
73  /// target. Finds all the paths in a cycle from \p start back to \p start.
74  ///
75  /// Note, as in Traverse, the network must be fully connected before
76  /// making this call.
77  ///
78  VDF_API
79  static void FindAllCyclePaths(
80  const VdfMaskedOutput &start,
81  InputCallback inputCallback,
82  std::vector<VdfConnectionConstVector> *paths);
83 
84 // -----------------------------------------------------------------------------
85 
86 private:
87 
89  const VdfMaskedOutput &start,
90  const VdfMaskedOutput &target,
91  InputCallback inputCallback,
92  std::vector<VdfConnectionConstVector> *paths);
93 
94  // A class that represents a segment of a path.
95  struct _PathSegment
96  {
97  _PathSegment()
98  : id(0), len(0) {}
99 
100  _PathSegment(unsigned int id, unsigned int len)
101  : id(id), len(len) {}
102 
103  // Equality operator.
104  bool operator==(const _PathSegment &rhs) const {
105  return id == rhs.id && len == rhs.len;
106  }
107 
108  std::string GetAsString() const {
109  return TfStringPrintf("{#%u / %u}", id, len);
110  }
111 
112  unsigned int id, len; // id and length of the segment
113  };
114 
115  // A stack frame, aka. a masked output and its path segment pending to
116  // be visited.
117  struct _StackFrame : public _PathSegment
118  {
119  _StackFrame(
120  const VdfMaskedOutput &maskedOutput,
121  const _PathSegment &segment)
122  : _PathSegment(segment),
123  maskedOutput(maskedOutput) {}
124 
125  VdfMaskedOutput maskedOutput;
126  };
127 
128  // Objects of type _PotentialResult represent potential result paths. They
129  // are created when the traversal encounters a previously visited connection
130  // at \p encountered. However, the moment we discover that path we don't
131  // know if that path may or may not have results because we don't know if it
132  // has been traversed fully.
133  //
134  // Therefore _PotentialResult objects are created and evaluated after the
135  // traversal is finished. Note that the \p ending segment ends at \p
136  // encountered by definition.
137  //
138  struct _PotentialResult
139  {
140  _PotentialResult(
141  const _PathSegment &ending, const _PathSegment &encountered)
142  : ending(ending),
143  encountered(encountered) {}
144 
145  // Equality operator.
146  bool operator==(const _PotentialResult &rhs) const {
147  return ending == rhs.ending && encountered == rhs.encountered;
148  }
149 
150  struct HashFunctor
151  {
152  size_t operator()(const _PotentialResult &p) const {
153  return TfHash::Combine(
154  p.ending.id,
155  p.ending.len,
156  p.encountered.id,
157  p.encountered.len);
158  }
159  };
160 
161  // The ending path segment.
162  _PathSegment ending;
163 
164  // The path and index being merged into. Note that the len of
165  // encountered segment is the last element that is included in the
166  // path.
167  _PathSegment encountered;
168  };
169 
170  using _VisitedDependencyToSegmentMap =
172 
173  // A map from VdfConnection pointer to _VisitedDependencyToSegmentMap.
174  // Tracks visited connections.
175  using _VisitedConnectionsInfoMap =
177 
178  // A map from path to parent _PathSegment. This is used to quickly find
179  // parent path segments or a path. Note that the parent is a path segment
180  // because the parent path may continue after a child forked off it.
181  using _PathToParentSegmentMap =
183 
184  // A map from path to result connection vector. This map tracks the
185  // directly found results during traversal. A directly found result is
186  // when the traversal manages to find the result node without finding a
187  // previously visited connection.
188  using _PathToResultMap =
190 
191  // A map from path to all its children paths.
192  using _PathToPathChildrenMap =
194 
195  // A set of pending results.
196  using _PotentialResults =
198 
199  // A map from path-id to first relevant input discovered.
200  using _PathToRelevanceMap =
202 
203 private:
204 
205  // Helper to traverse a frame.
206  void _TraverseFrame(const _StackFrame &frame, bool isStartFrame);
207 
208  // Helper for _TraverseOutput.
209  void _TraverseSeenConnection(
210  const _PathSegment &ending, const _PathSegment &encountered);
211 
212  // Helper to build the full path from pathId (including all parent paths).
213  VdfConnectionConstVector _BuildFullPath(
214  const _PathSegment &end, const _PathSegment *start) const;
215 
216  // Helper to finalize pending results.
217  void _FinalizePendingResults(
218  std::vector<VdfConnectionConstVector> *paths) const;
219 
220  // Helper to _FinalizePendingResults().
221  void _AppendChildPathsToWorkingSet(
222  std::set<unsigned int> *pathToLookup,
223  unsigned int pathId,
224  const _PathSegment &encounteredSegment,
225  unsigned int joiningPathId) const;
226 
227 private:
228 
229  // The output that we are searching for.
230  const VdfOutput *_targetOutput;
231 
232  // The input callback used to determine if a path is relevant.
233  InputCallback _inputCallback;
234 
235  // The discovered paths index via path index.
236  std::vector<VdfConnectionConstVector> _paths;
237 
238  // A map from path-id to relevance group.
239  _PathToRelevanceMap _pathToRelevanceMap;
240 
241  // Map from VdfConnection pointer to _PathSegment. Tracks visited
242  // connections.
243  _VisitedConnectionsInfoMap _visitedConnectionsInfoMap;
244 
245  // Map from path to parent _PathSegment. This is used to quickly find
246  // parent path segments or a path. Note that the parent is a path segment
247  // because the parent path may continue after a child forked off it.
248  _PathToParentSegmentMap _pathToParentSegmentMap;
249 
250  // A map from path to all its children paths.
251  _PathToPathChildrenMap _pathToPathChildrenMap;
252 
253  // A map from path to result connection vector. This map tracks the
254  // directly found results during traversal. A directly found result is
255  // when the traversal manages to find the result node without finding a
256  // previously visited connection. Note that not all paths have results.
257  _PathToResultMap _pathToResultMap;
258 
259  // A vector of pending stack frames for traversal.
260  std::vector<_StackFrame> _stack;
261 
262  // A set of pending results.
263  _PotentialResults _potentialResults;
264 };
265 
266 #endif
267 
TF_API std::string TfStringPrintf(const char *fmt,...)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLuint start
Definition: glcorearb.h:475
Definition: node.h:52
bool(* InputCallback)(const VdfInput &input)
size_t operator()(const _PotentialResult &p) const
#define VDF_API
Definition: api.h:25
OutGridT const XformOp bool bool
A class used for fast sparse traversals of VdfNetworks in the output-to-input direction when the goal...
Definition: input.h:35
static VDF_API void FindAllCyclePaths(const VdfMaskedOutput &start, InputCallback inputCallback, std::vector< VdfConnectionConstVector > *paths)
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
GLuint GLuint end
Definition: glcorearb.h:475
GLenum target
Definition: glcorearb.h:1667
GLuint id
Definition: glcorearb.h:655
Class to hold on to an externally owned output and a mask.
Definition: maskedOutput.h:31
static size_t Combine(Args &&...args)
Produce a hash code by combining the hash codes of several objects.
Definition: hash.h:487
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
static VDF_API void Traverse(const VdfMaskedOutput &start, const VdfMaskedOutput &target, InputCallback inputCallback, std::vector< VdfConnectionConstVector > *paths)