HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
network.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_NETWORK_H
8 #define PXR_EXEC_VDF_NETWORK_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/vdf/api.h"
15 #include "pxr/exec/vdf/types.h"
16 
17 #include "pxr/base/tf/hash.h"
18 #include "pxr/base/tf/hashset.h"
20 #include "pxr/base/tf/span.h"
21 
22 #include "tbb/concurrent_queue.h"
23 #include "tbb/concurrent_unordered_map.h"
24 #include "tbb/concurrent_vector.h"
25 
26 #include <atomic>
27 #include <cstdint>
28 #include <vector>
29 #include <iosfwd>
30 #include <memory>
31 #include <unordered_map>
32 
34 
35 class TfToken;
36 
37 class VdfConnection;
38 class VdfInput;
39 class VdfObjectPtr;
40 class VdfMask;
41 class VdfMaskedOutput;
42 class VdfNode;
43 class VdfOutput;
44 class VdfSchedule;
45 class VdfPoolChainIndex;
46 class VdfPoolChainIndexer;
48 class Vdf_InputAndOutputSpecsRegistry;
49 class Vdf_ScheduleInvalidator;
50 
52 
53 ////////////////////////////////////////////////////////////////////////////////
54 ///
55 /// \class VdfNetwork
56 ///
57 /// A VdfNetwork is a collection of VdfNodes and their connections.
58 ///
60 {
61 public:
62 
63  /// Constant for connection API to indicate to place the connection at
64  /// the end.
65  ///
66  static const int AppendConnection = -1;
67 
68  /// Constructs an empty network.
69  ///
70  VDF_API
71  VdfNetwork();
72 
73  /// Destructs the network and the nodes managed by it.
74  ///
75  VDF_API
76  ~VdfNetwork();
77 
78  /// Retrieves a debug name for a given node
79  ///
80  VDF_API
81  const std::string GetNodeDebugName(const VdfNode *node) const;
82 
83  /// Returns the number of indices currently available for outputs. Note
84  /// that this is a high water mark, and that the number of outputs
85  /// currently in the network may be less than the value returned.
86  ///
87  uint32_t GetOutputCapacity() const {
88  return _outputCapacity.load(std::memory_order_acquire);
89  }
90 
91  /// Returns the number of entries currently available for nodes and
92  /// for which it is valid to call GetNode(). Note that some entries
93  /// may be NULL.
94  ///
95  size_t GetNodeCapacity() const { return _nodes.size(); }
96 
97  /// Returns the number of nodes that are currently owned by the network.
98  ///
99  size_t GetNumOwnedNodes() const {
100  return _nodes.size() - _freeNodeIds.unsafe_size();
101  }
102 
103  /// Returns the node at index \p i.
104  ///
105  const VdfNode *GetNode(size_t i) const {
106  return i < _nodes.size() ? _nodes[i] : nullptr;
107  }
108 
109  /// Returns the non-const node at index \p i.
110  ///
111  VdfNode *GetNode(size_t i) {
112  return i < _nodes.size() ? _nodes[i] : nullptr;
113  }
114 
115  /// Returns the node with id \p nodeId, if it exists.
116  ///
117  VDF_API
118  const VdfNode *GetNodeById(const VdfId nodeId) const;
119 
120  /// Returns the non-const node with id \p nodeId, if it exists
121  ///
122  VDF_API
123  VdfNode *GetNodeById(const VdfId nodeId);
124 
125  /// \name Edit
126  ///
127  /// Used by clients to edit networks, e.g., to perform incremental changes.
128  ///
129  /// @{
130 
131  /// \class EditMonitor
132  ///
133  /// An abstract class to monitor network edit operations.
134  ///
135  /// Note that "will" notification is sent before any edits are made. "Did"
136  /// notification is sent after the edit operation is completed.
137  ///
139  {
140  public:
141  VDF_API
142  virtual ~EditMonitor();
143 
144  /// Will be called before a network is to be cleared out.
145  ///
146  /// When clearing out a network all nodes and connections will be
147  /// deleted. Note that we don't sent notices for them during the
148  /// clear operation.
149  ///
150  virtual void WillClear() = 0;
151 
152  /// Will be called after a connection has been made.
153  ///
154  virtual void DidConnect(const VdfConnection *connection) = 0;
155 
156  /// Will be called after a node has been added to the network.
157  ///
158  virtual void DidAddNode(const VdfNode *node) = 0;
159 
160  /// Will be called before \p node is deleted.
161  ///
162  virtual void WillDelete(const VdfNode *node) = 0;
163 
164  /// Will be called before a connection is deleted.
165  ///
166  virtual void WillDelete(const VdfConnection *connection) = 0;
167  };
168 
169  /// Clears all nodes from the network.
170  ///
171  VDF_API
172  void Clear();
173 
174  /// Connects the \p output to the given \p inputNode's input \p inputName
175  /// with \p mask. If \p atIndex is >= 0 the connection will be placed at
176  /// index \p atIndex on the target input. Otherwise it will be appened
177  /// at the end.
178  ///
179  VDF_API
181  VdfOutput *output,
182  VdfNode *inputNode,
183  const TfToken &inputName,
184  const VdfMask &mask,
185  int atIndex = AppendConnection);
186 
187  /// Connects the \p maskedOutput to the given \p inputNode's input
188  /// \p inputName. If \p atIndex is >= 0 the connection will be placed at
189  /// index \p atIndex on the target input. Otherwise it will be appened
190  /// at the end.
191  ///
192  VDF_API
194  const VdfMaskedOutput &maskedOutput,
195  VdfNode *inputNode,
196  const TfToken &inputName,
197  int atIndex = AppendConnection);
198 
199  /// Deletes \p node from the network.
200  ///
201  /// The node must have no inputs and no outputs connected.
202  ///
203  /// Note: Calling Delete() may change the index VdfNetwork assigns to each
204  /// VdfNode.
205  ///
206  /// Returns true, if the node has been deleted.
207  ///
208  VDF_API
209  bool Delete(VdfNode *node);
210 
211  /// Deletes \p connection from the network.
212  ///
213  VDF_API
214  void Disconnect(VdfConnection *connection);
215 
216  /// Disconnects and deletes \p node.
217  ///
218  /// Returns true, if the node has been deleted.
219  ///
220  VDF_API
221  bool DisconnectAndDelete(VdfNode *node);
222 
223  /// Reorders all input connections for \p input according to the mapping
224  /// defined by \p newToOldIndices.
225  ///
226  /// \param input
227  /// The input with the input connections to be reordered.
228  ///
229  /// \param newToOldIndices
230  /// For each index `i`, `newToOldIndices[i]` is the old connection index and
231  /// `i` is the desired new connection index. The number of indices given
232  /// must be the same as the number of input connections, each index must
233  /// be a valid connection index, and the indices must be unique.
234  ///
235  VDF_API
237  VdfInput *input,
238  const TfSpan<const VdfConnectionVector::size_type> &newToOldIndices);
239 
240  /// Registers an edit monitor for this network. The edit monitor needs to
241  /// be persistent as long as the network is alive and will receive
242  /// notifications for network edits.
243  ///
244  VDF_API
245  void RegisterEditMonitor(EditMonitor *monitor);
246 
247  /// Unregisters an edit monitor for this network.
248  ///
249  VDF_API
250  void UnregisterEditMonitor(EditMonitor *monitor);
251 
252  /// Returns the current edit version of the network. The version will
253  /// be updated every time the network topology changes.
254  ///
255  /// Note, no assumptions shall be made about the absolute value returned
256  /// from this function. It is merely guaranteed that if two version of the
257  /// same VdfNetwork instance equal, no topological edits have been made!
258  ///
259  size_t GetVersion() const {
260  return _version.load(std::memory_order_acquire);
261  }
262 
263  /// @}
264 
265 
266  /// \name Statistics
267  /// @{
268 
269  /// Prints useful statistics about the network to \p os.
270  ///
271  /// Returns the numer of nodes owned by this network.
272  ///
273  VDF_API
274  size_t DumpStats(std::ostream &os) const;
275 
276  /// @}
277 
278  /// \name Pool Chain Index
279  /// @{
280 
281  /// Returns the pool chain index from the pool chain indexer.
282  ///
283  VDF_API
284  VdfPoolChainIndex GetPoolChainIndex(const VdfOutput &output) const;
285 
286  /// @}
287 
288 private:
289 
290  friend class VdfNode;
291  friend class VdfIsolatedSubnetwork;
292  friend class VdfOutput;
293 
294  // Registers a name for a given node.
295  //
296  // Only VdfNode should call this function.
297  //
298  void _RegisterNodeDebugName(
299  const VdfNode &node, VdfNodeDebugNameCallback &&callback);
300 
301  // Unregisters a name for a given node.
302  //
303  // Should only be called by VdfNode's destructor.
304  //
305  void _UnregisterNodeDebugName(const VdfNode &node);
306 
307  // Adds a node to this network.
308  //
309  // Returns the index of node that was added. Once a node is added to the
310  // network, the network takes ownership. Only VdfNode should call
311  // this function.
312  //
313  void _AddNode(VdfNode *node);
314 
315  // Delete a node helper.
316  //
317  void _DeleteNode(VdfNode *node);
318 
319  // Removes the connection from the network, but does not delete it. Sends
320  // out the deletion notification, as well as invalidates any structures
321  // dependent on the connection state.
322  //
323  void _RemoveConnection(VdfConnection *connection);
324 
325  // Delete a connection helper function. Note that this method won't
326  // send out deletion notification.
327  //
328  void _DeleteConnection(VdfConnection *connection);
329 
330  // Removes \p node from the network, but doesn't delete it. Uses \p monitor
331  // to notify about any reindexing.
332  //
333  void _RemoveNode(VdfNode *node);
334 
335  // Informs the network that the affects mask for \p output has changed.
336  //
337  void _DidChangeAffectsMask(VdfOutput &output);
338 
339  // Returns an output id for a newly created output to use.
340  //
341  size_t _AcquireOutputId();
342 
343  // Releases an output id for use by a future output.
344  //
345  void _ReleaseOutputId(const VdfId id);
346 
347  // Increment the network edit version.
348  //
349  void _IncrementVersion();
350 
351  // \name Schedule Management
352  //
353  // These are methods that can only be called by VdfSchedule to register
354  // an unregister itself from a network.
355  //
356  // These methods are thread-safe and can safely be called from
357  // within execution. This is needed for clients that schedule during
358  // execution (e.g. speculation).
359  //
360  // @{
361 
362  friend class VdfSchedule;
363 
364  // Sets that a schedule is referencing this network.
365  //
366  void _RegisterSchedule(VdfSchedule *schedule) const;
367 
368  // Clears the schedule from the list of schedules referencing this network.
369  //
370  void _UnregisterSchedule(VdfSchedule *schedule) const;
371 
372  // Returns a pointer to the schedule invalidator.
373  //
374  Vdf_ScheduleInvalidator* _GetScheduleInvalidator() const {
375  return _scheduleInvalidator.get();
376  }
377 
378  // @}
379 
380  // Returns the input/output specs registry for this network.
381  //
382  Vdf_InputAndOutputSpecsRegistry &_GetInputOutputSpecsRegistry() {
383  return *_specsRegistry;
384  }
385 
386  // The complete list of nodes managed by this network.
387  tbb::concurrent_vector<VdfNode *> _nodes;
388 
389  // A queue of ids that are free to be assigned to new nodes.
390  tbb::concurrent_queue<VdfId> _freeNodeIds;
391 
392  // The version with which to initialize new nodes
393  VdfVersion _initialNodeVersion;
394 
395  // The number of output indices in this network.
396  std::atomic<uint32_t> _outputCapacity;
397 
398  // The free output indices in the network.
399  tbb::concurrent_queue<VdfId> _freeOutputIds;
400 
401  // The list of static edit monitors registered with this network.
402  using _EditMonitorVector = TfSmallVector<EditMonitor *, 1>;
403  _EditMonitorVector _monitors;
404 
405  // Helper class for invalidating schedules after topological changes.
406  std::unique_ptr<Vdf_ScheduleInvalidator> _scheduleInvalidator;
407 
408  // Pool Chain Indexer
409  std::unique_ptr<VdfPoolChainIndexer> _poolChainIndexer;
410 
411  // Input and output specs registry.
412  std::unique_ptr<Vdf_InputAndOutputSpecsRegistry> _specsRegistry;
413 
414  // Edit version.
415  std::atomic<size_t> _version;
416 
417  // Map from node to debug name.
418  using _NodeDebugNamesMap = tbb::concurrent_unordered_map<
419  VdfIndex,
420  std::unique_ptr<Vdf_ExecNodeDebugName>,
421  TfHash>;
422 
423  _NodeDebugNamesMap _nodeDebugNames;
424 };
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 
429 
430 #endif
uint32_t VdfVersion
The version type for Vdf objects.
Definition: types.h:113
VDF_API bool DisconnectAndDelete(VdfNode *node)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
VDF_API void Clear()
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
VDF_API const std::string GetNodeDebugName(const VdfNode *node) const
VDF_API VdfConnection * Connect(VdfOutput *output, VdfNode *inputNode, const TfToken &inputName, const VdfMask &mask, int atIndex=AppendConnection)
Definition: input.h:35
Definition: hash.h:472
static const int AppendConnection
Definition: network.h:66
Definition: token.h:70
size_t GetNumOwnedNodes() const
Definition: network.h:99
Contains a specification of how to execute a particular VdfNetwork.
Definition: schedule.h:40
Definition: span.h:70
TfHashSet< const VdfOutput *, TfHash > VdfOutputPtrSet
Definition: network.h:49
GLint GLuint mask
Definition: glcorearb.h:124
VDF_API void Disconnect(VdfConnection *connection)
size_t GetVersion() const
Definition: network.h:259
const VdfNode * GetNode(size_t i) const
Definition: network.h:105
VDF_API void ReorderInputConnections(VdfInput *input, const TfSpan< const VdfConnectionVector::size_type > &newToOldIndices)
Class to hold on to an externally owned output and a mask.
Definition: maskedOutput.h:31
VDF_API VdfNetwork()
VDF_API bool Delete(VdfNode *node)
#define VDF_API_TYPE
Definition: api.h:26
VDF_API const VdfNode * GetNodeById(const VdfId nodeId) const
VDF_API void UnregisterEditMonitor(EditMonitor *monitor)
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
VdfNode * GetNode(size_t i)
Definition: network.h:111
VDF_API size_t DumpStats(std::ostream &os) const
uint32_t GetOutputCapacity() const
Definition: network.h:87
size_t GetNodeCapacity() const
Definition: network.h:95
VDF_API VdfPoolChainIndex GetPoolChainIndex(const VdfOutput &output) const
VDF_API void RegisterEditMonitor(EditMonitor *monitor)
VDF_API ~VdfNetwork()
std::function< std::string()> VdfNodeDebugNameCallback
Type of callback for building a node debug name.
Definition: types.h:71
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