HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dependencyCache.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_EF_DEPENDENCY_CACHE_H
8 #define PXR_EXEC_EF_DEPENDENCY_CACHE_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/ef/api.h"
15 
16 #include "pxr/base/tf/bits.h"
18 #include "pxr/exec/vdf/node.h"
19 #include "pxr/exec/vdf/types.h"
20 
21 #include <tbb/concurrent_vector.h>
22 
23 #include <atomic>
24 #include <unordered_map>
25 #include <vector>
26 
28 
29 class VdfNetwork;
30 
31 ////////////////////////////////////////////////////////////////////////////////
32 ///
33 /// \class EfDependencyCache
34 ///
35 /// Caches output traversals by associating an input request with a set of
36 /// stored output dependencies, as determined by a predicate function.
37 ///
38 /// The traversals in this cache are invalidated by calling the
39 /// WillDeleteConnection and DidConnect methods in response to network edits
40 /// (WillDeleteNode, WillDeleteConnection, DidConnect). Invalidation is
41 /// optionally sparse, depending on the value of the \p updateIncrementally flag
42 /// passed to FindOutputs and FindNodes.
43 ///
45 {
46 public:
47  /// The predicate function that determines the cached dependencies.
48  ///
49  /// Takes the node currently being visited, as well as a result map to
50  /// insert output and node dependencies into.
51  ///
52  /// Returns \c false in order to stop the traversal at the current branch,
53  /// and \c true to continue.
54  ///
55  using PredicateFunction =
56  bool (*) (
57  const VdfNode &node,
59  std::vector<const VdfNode *> *);
60 
61  /// Constructor.
62  ///
63  EF_API
64  explicit EfDependencyCache(PredicateFunction predicate);
65 
66  /// Destructor.
67  ///
68  EF_API
70 
71  /// Find the output dependencies associated with the given request.
72  ///
73  /// Set \p updateIncrementally to \c true for cached dependencies that
74  /// should be sparsely invalidated and updated incrementally.
75  ///
76  /// Note that the masks here may sometimes be empty, to signify that an
77  /// output mask couldn't be inferred for that output. If an output is
78  /// returned with an empty mask, that output is reachable from the provided
79  /// outputs but the mask associated with the traversal is unknown.
80  ///
81  /// \note
82  /// This method is *not* thread safe.
83  ///
84  EF_API
86  const VdfMaskedOutputVector &outputs,
87  bool updateIncrementally) const;
88 
89  /// Find the node dependencies associated with the given request.
90  ///
91  /// Set \p updateIncrementally to \c true for cached dependencies that
92  /// should be sparsely invalidated and updated incrementally.
93  ///
94  /// \note
95  /// This method is *not* thread safe.
96  ///
97  EF_API
98  const std::vector<const VdfNode *> &FindNodes(
99  const VdfMaskedOutputVector &outputs,
100  bool updateIncrementally) const;
101 
102  /// Invalidate all cached dependencies.
103  ///
104  /// \note
105  /// This method is *not* thread safe.
106  ///
107  EF_API
108  void Invalidate();
109 
110  /// Invalidate all traversals dependent on this connection.
111  ///
112  /// \note
113  /// Intermixed concurrent calls to this method and to DidConnect are
114  /// supported. (Though it's not safe for any given source and target output
115  /// pair to be concurrently connected and deleted.)
116  ///
117  EF_API
118  void WillDeleteConnection(const VdfConnection &connection);
119 
120  /// Invalidate all traversals dependent on this new connection.
121  ///
122  /// \note
123  /// Intermixed concurrent calls to this method and to WillDeleteConnection
124  /// are supported. (Though it's not safe for any given source and target
125  /// output pair to be concurrently connected and deleted.)
126  ///
127  EF_API
128  void DidConnect(const VdfConnection &connection);
129 
130 private:
131 
132  // The cache entry stored for each traversal.
133  class _Entry {
134  public:
135  // Constructor.
136  _Entry(bool updateIncrementally)
137  : updateIncrementally(updateIncrementally)
138  , valid(true)
139  {}
140 
141  // Returns \c true if the traversal contains the specified node.
142  bool ContainsNode(const VdfNode &node) const {
143  const VdfIndex nodeIndex = VdfNode::GetIndexFromId(node.GetId());
144  return
145  nodeRefs.GetSize() > nodeIndex &&
146  nodeRefs.IsSet(nodeIndex);
147  }
148 
149  bool IsValid() const {
150  return valid.load(std::memory_order_relaxed);
151  }
152 
153  void Invalidate() {
154  valid.store(std::memory_order_relaxed);
155  }
156 
157  // The resulting output dependencies.
158  VdfOutputToMaskMap outputDeps;
159 
160  // The resulting node dependencies.
161  std::vector<const VdfNode *> nodeDeps;
162 
163  // Struct that represents a connection that may or may not exist.
164  //
165  // We store added connections using this representation beacuse it's
166  // possible that a connection may be added and then later removed.
167  // Therefore, rather than storing pointers to added connections, we
168  // store the information needed to look up the connection from the
169  // network.
170  struct _Connection {
172  VdfId sourceNodeId_,
173  TfToken outputName_,
174  VdfId targetNodeId_,
175  TfToken inputName_)
176  : sourceNodeId(sourceNodeId_)
177  , outputName(outputName_)
178  , targetNodeId(targetNodeId_)
179  , inputName(inputName_)
180  {}
181 
182  // Returns the pointer to this connection, if it exists in the given
183  // network; otherwise returns nullptr.
184  EF_API
186  const VdfNetwork *network) const;
187 
192  };
193 
194  // Any newly added connections that may affect this traversal.
195  //
196  // If this vector is non-empty when the entry is queried, the traversal
197  // must be incrementally updated.
198  tbb::concurrent_vector<_Connection> newConnections;
199 
200  // Every output and mask encountered during the traversal.
201  //
202  // Note that the masks here may sometimes be empty, to signify that an
203  // output mask couldn't be inferred for that output.
204  VdfOutputToMaskMap outputRefs;
205 
206  // Every node encountered during the traversal.
207  TfBits nodeRefs;
208 
209  // The number of outputs for each node at the time of the traversal
210  std::vector<size_t> nodeNumOutputs;
211 
212  // Incrementally update this traversal?
213  bool updateIncrementally;
214 
215  // Set to false when the entry is fully invalid.
216  std::atomic<bool> valid;
217  };
218 
219  // Find an entry in the cache.
220  const _Entry & _Find(
221  const VdfMaskedOutputVector &outputs,
222  bool updateIncrementally) const;
223 
224  // Populates the cache with a new entry for the given request.
225  const _Entry & _PopulateCache(
226  const VdfMaskedOutputVector& outputs,
227  bool updateIncrementally) const;
228 
229  // Traverse with the specified outputs and extend the traversal entry.
230  void _Traverse(
231  const VdfMaskedOutputVector &outputs,
232  _Entry *entry) const;
233 
234  // Update the existing traversal, by building a partial request from
235  // the new connections stored in the traversal entry.
236  void _TraversePartially(
237  const VdfNetwork *network,
238  _Entry *entry) const;
239 
240  // Gather dependencies for the partial traversal across the new connection.
241  // Will return \c true if the source output is included in the existing
242  // traversal entry.
243  bool _GatherDependenciesForNewConnection(
244  _Entry *entry,
245  const VdfConnection &connection,
246  VdfMaskedOutputVector *dependencies) const;
247 
248  // Gather dependencies for the partial traversal on a node that has been
249  // extended with additional outputs.
250  void _GatherDependenciesForExtendedNode(
251  const _Entry &entry,
252  const VdfNode &node,
253  VdfMaskedOutputVector *dependencies) const;
254 
255  // The traversal node callback.
256  static bool _NodeCallback(
257  const VdfNode &node,
258  PredicateFunction predicate,
259  _Entry *entry);
260 
261  // The traversal output callback.
262  static bool _OutputCallback(
263  const VdfOutput &output,
264  const VdfMask &mask,
265  const VdfInput *input,
266  _Entry *entry);
267 
268  //
269  // Data members
270  //
271 
272  // The cache is a map from VdfMaskedOutputVector to stored entry.
273  using _Cache = std::unordered_map<
275 
276  // Dependency cache.
277  mutable _Cache _cache;
278 
279  // The predicate function.
280  PredicateFunction _predicate;
281 
282 };
283 
285 
286 #endif
EF_API void WillDeleteConnection(const VdfConnection &connection)
EF_API const VdfOutputToMaskMap & FindOutputs(const VdfMaskedOutputVector &outputs, bool updateIncrementally) const
EF_API const std::vector< const VdfNode * > & FindNodes(const VdfMaskedOutputVector &outputs, bool updateIncrementally) const
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
_Connection(VdfId sourceNodeId_, TfToken outputName_, VdfId targetNodeId_, TfToken inputName_)
Definition: node.h:52
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
EF_API ~EfDependencyCache()
EF_API void DidConnect(const VdfConnection &connection)
OutGridT const XformOp bool bool
VdfId sourceNodeId
Definition: input.h:35
Definition: token.h:70
TfToken inputName
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
VdfId GetId() const
Definition: node.h:116
GLint GLuint mask
Definition: glcorearb.h:124
static VdfIndex GetIndexFromId(const VdfId id)
Definition: node.h:123
std::unordered_map< const VdfOutput *, VdfMask, TfHash > VdfOutputToMaskMap
A map from output pointer to mask.
Definition: types.h:104
EF_API void Invalidate()
EF_API VdfConnection * GetConnection(const VdfNetwork *network) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool(*)(const VdfNode &node, VdfOutputToMaskMap *, std::vector< const VdfNode * > *) PredicateFunction
VdfId targetNodeId
EF_API EfDependencyCache(PredicateFunction predicate)
std::vector< VdfMaskedOutput > VdfMaskedOutputVector
TfToken outputName
#define EF_API
Definition: api.h:25
uint64_t VdfId
The unique identifier type for Vdf objects.
Definition: types.h:107
uint32_t VdfIndex
The index type for Vdf objects.
Definition: types.h:110