HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
executorInterface.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_EXECUTOR_API_H
8 #define PXR_EXEC_VDF_EXECUTOR_API_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/vdf/api.h"
16 #include "pxr/exec/vdf/types.h"
17 
18 #include "pxr/base/tf/hashset.h"
19 
20 #include <atomic>
21 #include <memory>
22 #include <mutex>
23 
25 
26 class VdfMask;
27 class VdfNetwork;
28 class VdfOutput;
29 class VdfRequest;
30 class VdfSchedule;
31 class VdfVector;
32 class VdfExecutionStats;
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 ///
40 /// \brief Abstract base class for classes that execute a VdfNetwork to compute
41 /// a requested set of values.
42 ///
43 
45 {
46 public:
47  /// Noncopyable.
48  ///
51 
52  /// Destructor.
53  ///
54  VDF_API
55  virtual ~VdfExecutorInterface();
56 
57  /// \name Evaluation
58  /// @{
59 
60  /// Executes the \p schedule.
61  ///
62  VDF_API
63  void Run(
64  const VdfSchedule &schedule,
65  VdfExecutorErrorLogger *errorLogger = NULL);
66 
67  /// Executes the \p schedule.
68  ///
69  /// \p computeRequest must be a subset of the scheduled request. If the
70  /// full, scheduled request should be computed, then \p computeRequest
71  /// should be set to schedule.GetRequest().
72  ///
73  VDF_API
74  void Run(
75  const VdfSchedule &schedule,
76  const VdfRequest &computeRequest,
77  VdfExecutorErrorLogger *errorLogger = NULL);
78 
79  /// @}
80 
81 
82  /// \name Factory Construction
83  /// @{
84 
85  /// Returns a factory class facilitating the construction of new executors
86  /// that share traits with this executor instance.
87  ///
88  virtual const VdfExecutorFactoryBase &GetFactory() const = 0;
89 
90  /// @}
91 
92 
93  /// \name Executor Observer Notification
94  /// @{
95 
96  /// Can be called by clients to register a VdfExecutorObserver
97  /// with this executor.
98  ///
99  VDF_API
100  void RegisterObserver(const VdfExecutorObserver *observer) const;
101 
102  /// Must be called by clients to unregister a
103  /// VdfExecutorObserver, which has been previously registered
104  /// with RegisterObserver().
105  ///
106  VDF_API
107  void UnregisterObserver(const VdfExecutorObserver *observer) const;
108 
109  /// @}
110 
111 
112  /// \name Cache Management
113  /// @{
114 
115  /// Resize the executor to accomodate data for the given \p network.
116  ///
117  virtual void Resize(const VdfNetwork &network) {}
118 
119  /// Sets the cached value for a given \p output.
120  ///
121  virtual void SetOutputValue(
122  const VdfOutput &output,
123  const VdfVector &value,
124  const VdfMask &mask) = 0;
125 
126  /// Transfers ownership of the \p value to the given \p output. Returns
127  /// \c true if the transfer of ownership was successful. If the transfer of
128  /// ownership was successful, the executor assumes responsibility for the
129  /// lifetime of \p value. Otherwise, the call site maintains this
130  /// responsibility.
131  ///
132  virtual bool TakeOutputValue(
133  const VdfOutput &output,
134  VdfVector *value,
135  const VdfMask &mask) = 0;
136 
137  /// Returns the cached value for a given \p output if it has a cache
138  /// that contains all values specified by \p mask. Otherwise, returns
139  /// NULL.
140  ///
142  const VdfOutput &output,
143  const VdfMask &mask) const {
144  return _GetOutputValueForReading(output, mask);
145  }
146 
147  /// Duplicates the output data associated with \p sourceOutput and copies
148  /// it to \p destOutput.
149  ///
150  virtual void DuplicateOutputData(
151  const VdfOutput &sourceOutput,
152  const VdfOutput &destOutput) = 0;
153 
154  /// @}
155 
156 
157  /// \name Executor Hierarchy Management
158  /// @{
159 
160  /// Returns the parent executor, if any.
161  ///
163  return _parentExecutor;
164  }
165 
166  /// Sets the parent executor.
167  ///
168  /// This method also inherits the execution stats from the parent executor,
169  /// unless the executor already has its execution stats set.
170  ///
171  /// XXX: We need to get rid of this public API, since most executors do not
172  /// support changing out the parent executor after construction.
173  ///
174  VDF_API
175  void SetParentExecutor(const VdfExecutorInterface *parentExecutor);
176 
177  /// @}
178 
179 
180  /// \name Invalidation
181  /// @{
182 
183  /// Invalidates the network, starting from the masked outputs in
184  /// \p request.
185  ///
186  /// Performs an optimized vectorized traversal.
187  ///
188  VDF_API
189  void InvalidateValues(
190  const VdfMaskedOutputVector &invalidationRequest);
191 
192  /// Invalidate all state depending on network topology. This must be
193  /// called after changes to the network have been made.
194  ///
195  /// XXX:exec
196  /// I believe that we should not have this kind of API exposed. Clients
197  /// should not have to know about the internal state kept in the
198  /// executors. This is very similiar to schedules and perhaps should be
199  /// treated like schedules by being registered with the networks that
200  /// they depend on. A generalized mechanism in VdfNetwork might be nice.
201  ///
202  VDF_API
203  void InvalidateTopologicalState();
204 
205  /// Clears the executors buffers
206  ///
207  VDF_API
208  void ClearData();
209 
210  /// Clears the executor buffers for a specific output
211  ///
212  VDF_API
213  void ClearDataForOutput(const VdfId outputId, const VdfId nodeId);
214 
215  /// Returns \c true if the executor buffers are empty.
216  ///
217  virtual bool IsEmpty() const = 0;
218 
219  /// @}
220 
221 
222  /// \name Mung Buffer Locking Invalidation Timestamps
223  /// @{
224 
225  /// Increment this executor's invalidation timestamp for mung
226  /// buffer locking.
227  ///
229  ++_executorInvalidationTimestamp;
230  }
231 
232  /// Inherit the invalidation timestamp from another executor.
233  ///
235  _executorInvalidationTimestamp =
237  }
238 
239  /// Returns this executor's invalidation timestamp
240  ///
242  return _executorInvalidationTimestamp;
243  }
244 
245  /// Returns \c true, if the invalidation timestamps between the \p source
246  /// and \p dest outputs do not match, i.e. the source output should be
247  /// mung buffer locked.
248  ///
249  virtual bool HasInvalidationTimestampMismatch(
250  const VdfOutput &source,
251  const VdfOutput &dest) const = 0;
252 
253  /// @}
254 
255 
256  /// \name Executor Interruption
257  /// @{
258 
259  /// Set the interruption flag.
260  ///
261  void SetInterruptionFlag(const std::atomic_bool *interruptionFlag) {
262  _interruptionFlag = interruptionFlag;
263  }
264 
265  /// Returns the interruption flag
266  ///
267  const std::atomic_bool *GetInterruptionFlag() const {
268  return _interruptionFlag;
269  }
270 
271  /// Returns whether or not the executor has been interrupted, if the
272  /// executor supports interruption. If interruption is not supported, i.e.
273  /// no interruption flag has been set, this will always return \c false.
274  ///
275  bool HasBeenInterrupted() const {
276  return _interruptionFlag && _interruptionFlag->load();
277  }
278 
279  /// @}
280 
281 
282  /// \name Diagnostic Support
283  /// @{
284 
285  /// Sets an execution stats object.
286  ///
287  /// When \p stats is not NULL, then execution statistics will be gathered
288  /// into the object. When NULL, execution statistics will not be gathered.
289  ///
291  _stats = stats;
292  }
293 
294  /// Returns the Execution Stats object, if any.
295  ///
297  return _stats;
298  }
299 
300  /// @}
301 
302 
303 protected:
304 
305  /// Protected default constructor.
306  ///
307  VDF_API
309 
310  /// Construct with a parent executor.
311  ///
312  VDF_API
313  explicit VdfExecutorInterface(const VdfExecutorInterface *parentExecutor);
314 
315  /// Run this executor with the given \p schedule and \p request.
316  ///
317  virtual void _Run(
318  const VdfSchedule &schedule,
319  const VdfRequest &computeRequest,
320  VdfExecutorErrorLogger *errorLogger) = 0;
321 
322  /// Returns a value for the cache that flows across \p connection.
323  ///
324  virtual const VdfVector *_GetInputValue(
325  const VdfConnection &connection,
326  const VdfMask &mask) const = 0;
327 
328  /// Returns an output value for reading.
329  ///
330  virtual const VdfVector *_GetOutputValueForReading(
331  const VdfOutput &output,
332  const VdfMask &mask) const = 0;
333 
334  /// Returns an output value for writing.
335  ///
336  virtual VdfVector *_GetOutputValueForWriting(
337  const VdfOutput &output) const = 0;
338 
339  /// Returns \c true if the output is already invalid for the given
340  /// \p invalidationMask.
341  ///
342  virtual bool _IsOutputInvalid(
343  const VdfId outputId,
344  const VdfMask &invalidationMask) const = 0;
345 
346  /// Called during invalidation to mark outputs as invalid and determine
347  /// when the traversal can terminate early.
348  ///
349  /// Returns \c true if there was anything to invalidate and \c false if
350  /// \p output was already invalid.
351  ///
352  virtual bool _InvalidateOutput(
353  const VdfOutput &output,
354  const VdfMask &invalidationMask) = 0;
355 
356  /// This method is called as a pre-processing step before an
357  /// InvalidateValues() call. The method will return \c true if
358  /// \p processedRequest is to override the originally supplied
359  /// \p invalidationRequest for executor invalidation.
360  ///
362  const VdfMaskedOutputVector &invalidationRequest,
363  VdfMaskedOutputVector *processedRequest) {
364  return false;
365  }
366 
367  /// Called before invalidation begins to update the timestamp that will be
368  /// written for every VdfOutput visited during invalidation. This timestamp
369  /// is later used to identify outputs for mung buffer locking.
370  ///
371  virtual void _UpdateInvalidationTimestamp() = 0;
372 
373  /// Virtual implementation of the ClearData call. This may be
374  /// overridden by classes, which derive from VdfExecutorInterface.
375  ///
376  VDF_API
377  virtual void _ClearData();
378 
379  /// Virtual implementation of the ClearDataForOutput call. This may be
380  /// overridden by classes, which derive from VdfExecutorInterface.
381  ///
382  VDF_API
383  virtual void _ClearDataForOutput(const VdfId outputId, const VdfId nodeId);
384 
385  /// Called to set destOutput's buffer output to be a reference to the
386  /// buffer output of sourceOutput.
387  ///
388  virtual void _SetReferenceOutputValue(
389  const VdfOutput &destOutput,
390  const VdfOutput &sourceOutput,
391  const VdfMask &sourceMask) const = 0;
392 
393  /// Mark the output as having been visited. This is only to be used by
394  /// the speculation engine to tell its parent executor that an output
395  /// has been visited and should be marked for invalidation.
396  ///
397  virtual void _TouchOutput(const VdfOutput &output) const = 0;
398 
399 private:
400 
401  // VdfContext needs access to _SetReferenceOutputValue,
402  // _GetOutputValueForReading, _GetOutputValueForWriting and _LogWarning.
403  friend class VdfContext;
404 
405  // VdfIterator needs friend access to _GetInputValue,
406  // _GetOutputValueForReading and _GetOutputValueForWriting.
407  friend class VdfIterator;
408 
409  // VdfSpeculationNode needs friend access to _GetOutputValueForWriting.
410  friend class VdfSpeculationNode;
411 
412  // These classes need access to _TouchOutput.
413  template<template <typename> class E, class D>
415  template<class T> friend class VdfSpeculationExecutorEngine;
416  template<class T> friend class VdfPullBasedExecutorEngine;
417  template<class T> friend class VdfParallelSpeculationExecutorEngine;
418 
419  // VdfExecutorInvalidator needs access to _InvalidateOutput.
421 
422  // The optional invalidator, responsible for invalidating output state
423  // and temporary buffers for outputs and their dependent outputs.
424  std::unique_ptr<VdfExecutorInvalidator> _invalidator;
425 
426  // Optional, externally provided (i.e. not owned by the executor) object
427  // to keep track of execution statistics.
428  VdfExecutionStats *_stats;
429 
430  // Keeps track of the VdfExecutorObservers registered with this executor
432  mutable _Observers _observers;
433 
434  // Access to the _observers set can happen from multiple threads. The
435  // scenario where this happens is when background execution is interrupted
436  // with sharing enabled. Interuption iterates over the _observers lists in
437  // order to notify. That notification causes sharing node to release
438  // sub-executors via a worker thread. That also does unregister from the
439  // _observers set while the main thread is still using the set to interrupt.
440  mutable std::recursive_mutex _observersLock;
441 
442  // The executor stores its own invalidation timestamp.
443  // This timestamp will be applied to the data manager upon
444  // invalidating values.
445  VdfInvalidationTimestamp _executorInvalidationTimestamp;
446 
447  // Optional parent executor.
448  const VdfExecutorInterface *_parentExecutor;
449 
450  // Interruption flag
451  const std::atomic_bool *_interruptionFlag;
452 
453 };
454 
455 ///////////////////////////////////////////////////////////////////////////////
456 
458 
459 #endif
VdfExecutionStats * GetExecutionStats() const
VdfInvalidationTimestamp GetExecutorInvalidationTimestamp() const
const std::atomic_bool * GetInterruptionFlag() const
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
virtual void Resize(const VdfNetwork &network)
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
This is an interface for any class that wants to listen to specific executor events, such as executor deletion, or clearing data on the executor.
#define VDF_API
Definition: api.h:25
Executor used in speculation.
Contains a specification of how to execute a particular VdfNetwork.
Definition: schedule.h:40
bool HasBeenInterrupted() const
GLsizei GLsizei GLchar * source
Definition: glcorearb.h:803
GLint GLuint mask
Definition: glcorearb.h:124
void SetInterruptionFlag(const std::atomic_bool *interruptionFlag)
A node that pulls on a vector of value that are downstream of the current execution position...
virtual bool _PreProcessInvalidation(const VdfMaskedOutputVector &invalidationRequest, VdfMaskedOutputVector *processedRequest)
void InheritExecutorInvalidationTimestamp(const VdfExecutorInterface &executor)
#define VDF_API_TYPE
Definition: api.h:26
LeafData & operator=(const LeafData &)=delete
unsigned int VdfInvalidationTimestamp
Type of the timestamp that identifies the most recent round of invalidation.
Definition: types.h:74
const VdfVector * GetOutputValue(const VdfOutput &output, const VdfMask &mask) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
void IncrementExecutorInvalidationTimestamp()
void SetExecutionStats(VdfExecutionStats *stats)
This class provides an executor engine to the speculation executor.
This class is a collection of common functions used by pulled based executors.
Abstract base class for classes that execute a VdfNetwork to compute a requested set of values...
std::vector< VdfMaskedOutput > VdfMaskedOutputVector
const VdfExecutorInterface * GetParentExecutor() const
uint64_t VdfId
The unique identifier type for Vdf objects.
Definition: types.h:107