HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
parallelExecutorDataManager.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_PARALLEL_EXECUTOR_DATA_MANAGER_H
8 #define PXR_EXEC_VDF_PARALLEL_EXECUTOR_DATA_MANAGER_H
9 
10 ///\file
11 
12 #include "pxr/pxr.h"
13 
17 #include "pxr/exec/vdf/output.h"
20 #include "pxr/exec/vdf/types.h"
21 
23 
24 class VdfMask;
25 class VdfVector;
26 
27 /// Forward definition of the traits class, which will be specialized by the
28 /// derived data manager implementation, and contain at least a type definition
29 /// for the DataHandle.
30 template<typename DerivedClass> struct Vdf_ParallelExecutorDataManagerTraits;
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 ///
34 /// \class VdfParallelExecutorDataManager
35 ///
36 /// \brief This class provides functionality to manage executor data
37 /// stored as VdfExecutorData from multiple threads. The methods in this
38 /// data manager are thread-safe unless called out to not be thread-safe
39 /// in the documentation.
40 ///
41 template < typename DerivedClass >
44  DerivedClass,
45  typename Vdf_ParallelExecutorDataManagerTraits<DerivedClass>::DataHandle
46  >
47 {
48 public:
49 
50  /// The data handle type defined via the specialized traits class.
51  ///
52  typedef
55 
56  /// The base class type.
57  ///
58  typedef
61 
62  /// Returns the input value flowing across the given \p connection with the
63  /// given \p mask. If the the cache is not valid, or if the cache does not
64  /// contain all the elements in \p mask, returns NULL. If no output data
65  /// exists for \p output, it will not be created.
66  ///
68  const VdfConnection &connection,
69  const VdfMask &mask) const;
70 
71  /// Returns the cached value for a given \p output and \p mask. If the the
72  /// cache is not valid, or if the cache does not contain all the elements in
73  /// \p mask, returns NULL. If no output data exists for \p output, it will
74  /// not be created.
75  ///
77  const DataHandle dataHandle,
78  const VdfMask &mask) const;
79 
80  /// Returns a new or existing output value.
81  ///
83  const VdfOutput &output,
84  const DataHandle dataHandle) const;
85 
86  /// Sets the cached value for a given \p output, creating the output cache
87  /// if necessary.
88  ///
89  /// If the output already contains data, it will be merged with the new
90  /// data as indicated by \p value and \p mask.
91  ///
92  /// This method provides very limited thread-safety: It is safe to call
93  /// this method if the data manager is already sized appropriately, and
94  /// during a round of evaluation, data is set no more than once per
95  /// individual output. It is not safe to call this method concurrently on
96  /// the same output, including an output that may have its value mutated as
97  /// part of a concurrent round of evaluation.
98  ///
99  void SetOutputValue(
100  const VdfOutput &output,
101  const VdfVector &value,
102  const VdfMask &mask);
103 
104  /// Transfers the ownership of \p value to the given \p output. Returns
105  /// \c true if this succeeds. The output will assume responsibility for the
106  /// lifetime management of \p value, if successful. Otherwise, the call site
107  /// maintains this responsibility.
108  ///
109  /// If a value has previously been transferred to this \p output, the
110  /// method will fail to transfer the ownership of this \p value and return
111  /// \c false.
112  ///
113  bool TakeOutputValue(
114  const VdfOutput &output,
115  VdfVector *value,
116  const VdfMask &mask);
117 
118  /// Called to set destOutput's buffer output to be a reference to the
119  /// \p sourceValue.
120  ///
122  const VdfVector *sourceValue,
123  const VdfId destOutputId) const;
124 
125  /// Creates a new cache for an output, given the output data object.
126  ///
128  const VdfOutput &output,
129  VdfExecutorBufferData *bufferData);
130 
131  /// Creates a new cache for an output, given the output data object. This
132  /// method makes sure that the returned vector is properly resized to
133  /// accommodate all the elements set in the specified \p bits.
134  ///
136  const VdfOutput &output,
137  VdfExecutorBufferData *bufferData,
138  const VdfMask::Bits &bits);
139 
140  /// Duplicates the output data associated with \p sourceOutput and copies
141  /// it to \p destOutput.
142  ///
143  /// This method is not thread-safe.
144  ///
145  void DuplicateOutputData(
146  const VdfOutput &sourceOutput,
147  const VdfOutput &destOutput);
148 
149  /// Returns \c true if the output is already invalid for the given
150  /// \p invalidationMask.
151  ///
152  bool IsOutputInvalid(
153  const VdfId outputId,
154  const VdfMask &invalidationMask) const;
155 
156  /// Marks \p output as invalid.
157  ///
158  /// Returns \c true if there was anything to invalidate and false if the
159  /// \p output was already invalid.
160  ///
161  /// This method is not thread-safe.
162  ///
163  bool InvalidateOutput(
164  const VdfOutput &output,
165  const VdfMask &invalidationMask);
166 
167  /// Marks the data at the given \p output as having been touched by
168  /// evaluation.
169  ///
170  void Touch(const VdfOutput &output) const;
171 
172  /// Increments the the current invalidation timestamp on this executor.
173  ///
174  /// This method is not thread-safe.
175  ///
177  const VdfInvalidationTimestamp &timestamp) {
178  _invalidationTimestamp = timestamp;
179  }
180 
181  /// Returns the current invalidation timestamp on this executor.
182  ///
184  return _invalidationTimestamp;
185  }
186 
187  /// Returns \c true, if the invalidation timestamps between
188  /// \p sourceExecutorData and \p destExecutorData do not match, i.e. the
189  /// source output should be mung buffer locked.
190  ///
192  const DataHandle &sourceHandle,
193  const DataHandle &destHandle) const;
194 
195 protected:
196 
197  /// Constructor
198  ///
200  _invalidationTimestamp(
201  VdfExecutorInvalidationData::InitialInvalidationTimestamp + 1)
202  { }
203 
204  /// Prevent destruction via base class pointers (static polymorphism only).
205  ///
207 
208 private:
209 
210  // Returns an output value for reading.
211  //
212  VdfVector *_GetOutputValueForReading(
213  VdfExecutorBufferData *bufferData,
214  const VdfMask &mask) const;
215 
216  // The current invalidation timestamp, recording the timestamp that was
217  // applied to the last (if any) round of outputs traversed during
218  // invalidation. This record and the timestamps on individual ExecutorData
219  // objects are the keys to activating mung buffer locking.
220  //
221  VdfInvalidationTimestamp _invalidationTimestamp;
222 };
223 
224 ///////////////////////////////////////////////////////////////////////////////
225 
226 template<typename DerivedClass>
227 VdfVector *
229  const VdfConnection &connection,
230  const VdfMask &mask) const
231 {
232  // For associated inputs, we need to grab the input value from the
233  // associated output. This is because read/write buffers have been
234  // prepared before the node callback is invoked.
235  // Values for read outputs originate from the source output on the
236  // input connection.
237 
238  const VdfInput &input = connection.GetTargetInput();
239  const VdfOutput *ao = input.GetAssociatedOutput();
240 
241  if (!ao || input.GetNumConnections() != 1) {
242  return GetOutputValueForReading(
243  Base::_GetDataHandle(connection.GetSourceOutput().GetId()), mask);
244  }
245 
246  // Note that read/write output values are always passed via the private
247  // buffers. The only time read/writes are published is when they reach
248  // an output that no longer passes the value, or when a kept buffer is
249  // being published. Therefore, we always read output values for read/writes
250  // out of the private buffer, if requested as an input value.
251 
252  const DataHandle dataHandle = Base::_GetDataHandle(ao->GetId());
253  return Base::_IsValidDataHandle(dataHandle)
254  ? _GetOutputValueForReading(
255  Base::_GetPrivateBufferData(dataHandle), mask)
256  : nullptr;
257 }
258 
259 template<typename DerivedClass>
260 VdfVector *
262  const DataHandle dataHandle,
263  const VdfMask &mask) const
264 {
265  // Output values are always read from public buffers. When nodes are
266  // evaluated, they mutate the private buffers, which are then published
267  // as soon as the node completes. Note, however, that read/write buffers
268  // will never be published until they reach on output that no longer passes
269  // the value.
270 
271  if (!Base::_IsValidDataHandle(dataHandle)) {
272  return nullptr;
273  }
274 
275  // Attempt to read from the public buffer, first.
276  VdfExecutorBufferData *publicData = Base::_GetPublicBufferData(dataHandle);
277  if (VdfVector *value = _GetOutputValueForReading(publicData, mask)) {
278  return value;
279  }
280 
281  // Then, fall back to reading from the transferred data, if available.
282  VdfExecutorBufferData *transferData =
283  Base::_GetTransferredBufferData(dataHandle);
284  return transferData
285  ? _GetOutputValueForReading(transferData, mask)
286  : nullptr;
287 }
288 
289 template<typename DerivedClass>
290 VdfVector *
292  const VdfOutput &output,
293  const DataHandle handle) const
294 {
295  // If the handle is not valid, we can't return a value for writing.
296  if (!Base::_IsValidDataHandle(handle)) {
297  return nullptr;
298  }
299 
300  // Note that output values are always written to private buffers. These
301  // private buffers will then be published once the node has completed
302  // evaluation.
303 
304  VdfExecutorBufferData *bufferData = Base::_GetPrivateBufferData(handle);
305  if (VdfVector *value = bufferData->GetExecutorCache()) {
306  return value;
307  }
308 
309  // Create a new output value, if there isn't one already available.
310  return CreateOutputCache(output, bufferData);
311 }
312 
313 template < typename DerivedClass >
314 void
316  const VdfOutput &output,
317  const VdfVector &value,
318  const VdfMask &mask)
319 {
320  // Make sure the data manager is appropriately sized.
321  Base::_Resize(output.GetNode().GetNetwork());
322 
323  // Mark the output as having been touched by evaluation, in order
324  // for it to be considered by invalidation.
325  const VdfId outputId = output.GetId();
326  Base::_Touch(outputId);
327 
328  // Retrieve the data at the output
329  const DataHandle handle = Base::_GetOrCreateDataHandle(outputId);
330  VdfExecutorBufferData *privateBuffer = Base::_GetPrivateBufferData(handle);
331  VdfExecutorBufferData *publicBuffer = Base::_GetPublicBufferData(handle);
332 
333  // Merge with existing data or replace?
334  const VdfMask &publicMask = publicBuffer->GetExecutorCacheMask();
335  const VdfVector *publicValue = publicBuffer->GetExecutorCache();
336  const bool mergeData =
337  publicValue &&
338  !publicMask.IsEmpty() &&
339  publicMask != mask;
340 
341  // Set the new output value, merging in the previously available public
342  // data, if any.
343  if (mergeData) {
344  const VdfMask privateMask = publicMask | mask;
345  VdfVector *outputValue = privateBuffer->CreateExecutorCache(
346  output.GetSpec(), privateMask.GetBits());
347  outputValue->Merge(*publicValue, publicMask - mask);
348  outputValue->Merge(value, mask);
349  privateBuffer->SetExecutorCacheMask(privateMask);
350  } else {
351  VdfVector *outputValue =
352  privateBuffer->CreateExecutorCache(output.GetSpec());
353  outputValue->Copy(value, mask);
354  privateBuffer->SetExecutorCacheMask(mask);
355  }
356 
357  // We just set the private buffer data, now let's publish it. Note, that
358  // we can no longer modify the private or public buffer data after this
359  // step, since it could lead to race conditions.
360  Base::_PublishPrivateBufferData(handle);
361 }
362 
363 template < typename DerivedClass >
364 bool
366  const VdfOutput &output,
367  VdfVector *value,
368  const VdfMask &mask)
369 {
370  // Make sure the data manager is appropriately sized.
371  Base::_Resize(output.GetNode().GetNetwork());
372 
373  // Mark the output as having been touched by evaluation, in order
374  // for it to be considered by invalidation.
375  const VdfId outputId = output.GetId();
376  Base::_Touch(outputId);
377 
378  // Retrieve the data at the output
379  const DataHandle handle = Base::_GetOrCreateDataHandle(outputId);
380 
381  // Attempt to transfer the value.
382  return Base::_TransferBufferData(handle, value, mask);
383 }
384 
385 template < typename DerivedClass >
386 void
388  const VdfVector *sourceValue,
389  const VdfId destOutputId) const
390 {
391  const DataHandle handle = Base::_GetDataHandle(destOutputId);
392  TF_DEV_AXIOM(Base::_IsValidDataHandle(handle));
393 
394  VdfExecutorBufferData *bufferData = Base::_GetPrivateBufferData(handle);
395 
396  // XXX:cleanup This const_cast is real trouble.
397  bufferData->YieldOwnership(const_cast<VdfVector *>(sourceValue));
398 }
399 
400 template < typename DerivedClass >
401 VdfVector *
403  const VdfOutput &output,
404  VdfExecutorBufferData *bufferData)
405 {
406  TfAutoMallocTag2 tag(
407  "Vdf", "VdfParallelExecutorDataManager::CreateOutputCache");
408 
409  // If the executor is providing its own cache-reuse mechanism, then
410  // we assert that the cache is NULL before we get here. Otherwise,
411  // we will try to reuse whatever cache is there already.
412  TF_DEV_AXIOM(!bufferData->GetExecutorCache());
413 
414  return bufferData->CreateExecutorCache(output.GetSpec());
415 }
416 
417 template < typename DerivedClass >
418 VdfVector *
420  const VdfOutput &output,
421  VdfExecutorBufferData *bufferData,
422  const VdfMask::Bits &bits)
423 {
424  TfAutoMallocTag2 tag(
425  "Vdf", "VdfParallelExecutorDataManager::CreateOutputCache");
426 
427  // If the executor is providing its own cache-reuse mechanism, then
428  // we assert that the cache is NULL before we get here. Otherwise,
429  // we will try to reuse whatever cache is there already.
430  TF_DEV_AXIOM(!bufferData->GetExecutorCache());
431 
432  return bufferData->CreateExecutorCache(output.GetSpec(), bits);
433 }
434 
435 template < typename DerivedClass >
436 void
438  const VdfOutput &sourceOutput,
439  const VdfOutput &destOutput)
440 {
441  // Make sure the data manager is appropriately sized for us to copy
442  // the source value to the destination output.
443  Base::_Resize(destOutput.GetNode().GetNetwork());
444 
445  // Untouch the destination data, unless the source data has been touched.
446  // This needs to happen even if we don't get a sourceHandle below.
447  const VdfId destOutputId = destOutput.GetId();
448  const VdfId sourceOutputId = sourceOutput.GetId();
449  Base::_Untouch(destOutputId);
450  if (Base::_Untouch(sourceOutputId)) {
451  Base::_Touch(sourceOutputId);
452  Base::_Touch(destOutputId);
453  }
454 
455  // If the source output data exists, clone it to the destination
456  // output data.
457  const DataHandle sourceHandle = Base::_GetDataHandle(sourceOutputId);
458  if (!Base::_IsValidDataHandle(sourceHandle)) {
459  return;
460  }
461 
462  // Get the destination data handle.
463  const DataHandle destHandle = Base::_GetOrCreateDataHandle(destOutputId);
464 
465  // Clone the buffer data.
466  Base::_GetPublicBufferData(sourceHandle)->Clone(
467  Base::_GetPublicBufferData(destHandle));
468 
469  // Clone the invalidation data.
470  Base::_GetInvalidationData(sourceHandle)->Clone(
471  Base::_GetInvalidationData(destHandle));
472 
473  // Copy the invalidation timestamp.
474  Base::_SetInvalidationTimestamp(
475  destHandle, Base::_GetInvalidationTimestamp(sourceHandle));
476 }
477 
478 template < typename DerivedClass >
479 bool
481  const VdfId outputId,
482  const VdfMask &invalidationMask) const
483 {
484  // If the output has been touched by evaluation, it is valid.
485  const bool wasTouched = Base::_IsTouched(outputId);
486  if (wasTouched) {
487  return false;
488  }
489 
490  // If there is no data handle for the output, the output has never been
491  // evaluated and therefore is still invalid.
492  const DataHandle handle = Base::_GetDataHandle(outputId);
493  if (!Base::_IsValidDataHandle(handle)) {
494  return true;
495  }
496 
497  // Let's check if the invalidation data is marked invalid for the given
498  // mask.
499  return Base::_GetInvalidationData(handle)->IsInvalid(
500  invalidationMask, wasTouched);
501 }
502 
503 template < typename DerivedClass >
504 bool
506  const VdfOutput &output,
507  const VdfMask &invalidationMask)
508 {
509  // Untouch the output. If it has been touched, we need to creata a data
510  // handle for it, even though it may have never been evaluated with this
511  // data manager.
512  const VdfId outputId = output.GetId();
513  const bool wasTouched = Base::_Untouch(outputId);
514 
515  // Retrieve the data handle for the output.
516  const DataHandle handle = wasTouched
517  ? Base::_GetOrCreateDataHandle(outputId)
518  : Base::_GetDataHandle(outputId);
519 
520  // Thou shalt not invalidate what has not been evaluated (unless it has
521  // been touched, of course)!
522  if (!Base::_IsValidDataHandle(handle)) {
523  return false;
524  }
525 
526  // Invalidate the output via the VdfExecutorInvalidationData. Make sure
527  // to also untouch the output, if it has previously been touched by
528  // evaluation.
529  const bool didInvalidate = Base::_GetInvalidationData(handle)->Invalidate(
530  invalidationMask, wasTouched);
531 
532  // If the output had previously been touched, and it has now been
533  // invalidated. Make sure to invalidate the VdfExecutorBufferData.
534  if (didInvalidate) {
535 
536  // Update the invalidation timestamp, by applying the timestamp from
537  // the data manager to the timestamp stored at the output.
538  Base::_SetInvalidationTimestamp(handle, GetInvalidationTimestamp());
539 
540  // Retrieve the buffer data stored at the output.
541  VdfExecutorBufferData *bufferData = Base::_GetPublicBufferData(handle);
542 
543  // We only need to invalidate the executor cache if the buffer has one.
544  if (!bufferData->GetExecutorCacheMask().IsEmpty()) {
545 
546  // If this is an output in the pool, let's apply sparse
547  // invalidation.
548  if (Vdf_IsPoolOutput(output)) {
549 
550  // Sparsely invalidate the executor cache mask, using the bits
551  // in the invalidation mask. During a steady-state mung, the
552  // cache and invalidation masks will likely always be the same
553  // across iterations, so we memoize this operation.
554  //
555  // XXX: Memoize!
556  //
557  VdfMask newCacheMask =
558  bufferData->GetExecutorCacheMask() - invalidationMask;
559 
560  // If the new cache mask is now all-zeros, remove the cache
561  // entirely, otherwise simply set the new cache mask.
562  if (newCacheMask.IsAllZeros()) {
563  bufferData->ResetExecutorCache();
564  } else {
565  bufferData->SetExecutorCacheMask(newCacheMask);
566  }
567  }
568 
569  // Otherwise, we simply remove the cache entirely.
570  else {
571  bufferData->ResetExecutorCache();
572  }
573  }
574 
575  // Also clear any transferred data.
576  Base::_ResetTransferredBufferData(handle);
577 
578  // We did some invalidation.
579  return true;
580  }
581 
582  // Nothing to invalidate.
583  return false;
584 }
585 
586 template < typename DerivedClass >
587 void
589  const VdfOutput &output) const
590 {
591  Base::_Touch(output.GetId());
592 }
593 
594 template < typename DerivedClass >
595 bool
597  const DataHandle &sourceHandle,
598  const DataHandle &destHandle) const
599 {
600  // For this method to return true, indicating that the source output should
601  // be locked for mung buffer locking, the invalidation timestamp stored in
602  // the destination data object must match the current invalidation
603  // timestamp. Furthermore, the source data object must have an invalidation
604  // timestamp different from our current invalidation timestamp.
605  // Essentially, this means that in the latest round of invalidation, the
606  // destination output has been invalidated, whereas the source output
607  // remained untouched.
608  // If this method returns true, the cache at the source output can be
609  // mung buffer locked, because it won't receive invalidation, whereas any
610  // output below (and including) the destination output will!
611 
612  return
613  Base::_IsValidDataHandle(sourceHandle) &&
614  Base::_IsValidDataHandle(destHandle) &&
615  Base::_GetInvalidationTimestamp(sourceHandle) !=
616  _invalidationTimestamp &&
617  Base::_GetInvalidationTimestamp(destHandle) ==
618  _invalidationTimestamp;
619 }
620 
621 template < typename DerivedClass >
622 VdfVector *
624  VdfExecutorBufferData *bufferData,
625  const VdfMask &mask) const
626 {
627  // We have the output value if
628  // o The output data exists
629  // o The cache is not empty
630  // o One of the following is true:
631  // o The request mask has no bits set because we ask for an
632  // attribute with shape of length zero (e.g., points attribute
633  // with zero points in it.
634  // or
635  // o The output is not dirty and
636  // o The computed mask covers what is requested.
637 
638  VdfVector *value = bufferData->GetExecutorCache();
639  const bool hasValue =
640  value &&
641  (mask.IsAllZeros() ||
642  (bufferData->GetExecutorCacheMask().IsAnySet() &&
643  bufferData->GetExecutorCacheMask().Contains(mask)));
644 
645  return hasValue ? value : nullptr;
646 }
647 
649 
650 #endif
bool IsOutputInvalid(const VdfId outputId, const VdfMask &invalidationMask) const
The interface contract for the static polymorphism used by parallel executor data manager implementat...
bool IsEmpty() const
Definition: mask.h:168
bool InvalidateOutput(const VdfOutput &output, const VdfMask &invalidationMask)
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
size_t GetNumConnections() const
Definition: input.h:58
static VdfVector * CreateOutputCache(const VdfOutput &output, VdfExecutorBufferData *bufferData)
VdfId GetId() const
Definition: output.h:100
void DuplicateOutputData(const VdfOutput &sourceOutput, const VdfOutput &destOutput)
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
void Touch(const VdfOutput &output) const
const VdfNode & GetNode() const
Definition: output.h:57
bool IsAnySet() const
Definition: mask.h:216
VDF_API const VdfOutputSpec & GetSpec() const
This class provides functionality to manage executor data stored as VdfExecutorData from multiple thr...
VdfMask::Bits const & GetBits() const
Definition: mask.h:556
Fast, compressed bit array which is capable of performing logical operations without first decompress...
void UpdateInvalidationTimestamp(const VdfInvalidationTimestamp &timestamp)
Definition: input.h:35
VdfVector * GetOrCreateOutputValueForWriting(const VdfOutput &output, const DataHandle dataHandle) const
#define TF_DEV_AXIOM(cond)
VdfVector * CreateExecutorCache(const VdfOutputSpec &spec)
void Copy(const VdfVector &rhs, const VdfMask &mask)
Definition: vector.h:281
void ResetExecutorCache(const VdfMask &mask)
const VdfNetwork & GetNetwork() const
Definition: node.h:138
const VdfInput & GetTargetInput() const
Returns the input connector (ie. target) for this connection.
Definition: connection.h:87
bool Vdf_IsPoolOutput(const VdfOutput &output)
void SetReferenceOutputValue(const VdfVector *sourceValue, const VdfId destOutputId) const
void SetOutputValue(const VdfOutput &output, const VdfVector &value, const VdfMask &mask)
const VdfInvalidationTimestamp & GetInvalidationTimestamp() const
GLint GLuint mask
Definition: glcorearb.h:124
bool HasInvalidationTimestampMismatch(const DataHandle &sourceHandle, const DataHandle &destHandle) const
Vdf_ParallelExecutorDataManagerInterface< DerivedClass, DataHandle > Base
VDF_API void Merge(const VdfVector &rhs, const VdfMask::Bits &bits)
void SetExecutorCacheMask(const VdfMask &mask)
bool Contains(const VdfMask &mask) const
Definition: mask.h:186
This object is responsible for storing the executor buffer data, comprised of the executor cache vect...
Vdf_ParallelExecutorDataManagerTraits< DerivedClass >::DataHandle DataHandle
bool IsAllZeros() const
Definition: mask.h:206
VdfVector * GetInputValue(const VdfConnection &connection, const VdfMask &mask) const
const VdfOutput & GetSourceOutput() const
Returns the output (ie. source) for this connection.
Definition: connection.h:63
const VdfMask & GetExecutorCacheMask() const
VdfVector * GetOutputValueForReading(const DataHandle dataHandle, const VdfMask &mask) const
const VdfOutput * GetAssociatedOutput() const
Definition: input.h:82
unsigned int VdfInvalidationTimestamp
Type of the timestamp that identifies the most recent round of invalidation.
Definition: types.h:74
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
VdfVector * GetExecutorCache() const
bool TakeOutputValue(const VdfOutput &output, VdfVector *value, const VdfMask &mask)
uint64_t VdfId
The unique identifier type for Vdf objects.
Definition: types.h:107