7#ifndef PXR_EXEC_VDF_PULL_BASED_EXECUTOR_ENGINE_H
8#define PXR_EXEC_VDF_PULL_BASED_EXECUTOR_ENGINE_H
31#include "pxr/base/tf/bits.h"
35PXR_NAMESPACE_OPEN_SCOPE
41#define _VDF_PBEE_PROFILING_ON 0
42#if _VDF_PBEE_PROFILING_ON
43#define VDF_PBEE_TRACE_FUNCTION TRACE_FUNCTION
44#define VDF_PBEE_TRACE_SCOPE TRACE_SCOPE
46#define VDF_PBEE_TRACE_FUNCTION()
47#define VDF_PBEE_TRACE_SCOPE(name)
66template <
typename DataManagerType>
83 DataManagerType *dataManager) :
85 _dataManager(dataManager)
93 const VdfRequest &computeRequest,
96 schedule, computeRequest, errorLogger,
105 template <
typename F >
108 const VdfRequest &computeRequest,
124 ExecutionStagePreRequisitesDone,
128 ExecutionStageReadsDone,
131 ExecutionStageCompute,
143 bool absorbLockedCache =
false);
160 bool absorbLockedCache =
false);
170 const VdfMask &fromMask)
const;
224 return output.GetAssociatedInput() &&
232 struct _OutputToExecute {
237 const VdfMask &lockedCacheMask,
240 stage(ExecutionStageStart),
241 lockedCacheMask(lockedCacheMask),
242 affective(affective),
243 absorbLockedCache(false)
259 bool absorbLockedCache;
268 bool _PushBackOutput(
269 std::vector< _OutputToExecute > *outputs,
270 const VdfMask &lockedCacheMask,
285 void _FinalizeComputedOutput(
288 const bool hasBeenInterrupted,
289 const bool extendRequestMask);
297 bool _UpdateOutputForSMBL(
299 _OutputToExecute *stackEntry,
308 DataManagerType *_dataManager;
313 std::vector<_DataHandle> _dataHandleCache;
319template<
typename DataManagerType>
324 const VdfRequest &computeRequest,
341 VdfRequest::IndexedView requestView(computeRequest);
342 for (
size_t i = 0; i < requestView.GetSize(); ++i) {
354 if (_GetExecutor().GetOutputValue(output, mask)) {
355 callback(*maskedOutput, i);
359 VDF_PBEE_TRACE_SCOPE(
360 "VdfPullBasedExecutorEngine<T>::RunSchedule (executing output)");
361 _ExecuteOutput(state, output, &executedNodes);
364 if (_GetExecutor().HasBeenInterrupted()) {
371 callback(*maskedOutput, i);
376template<
typename DataManagerType>
391 _executor.GetOutputValue(fromOutput, fromMask);
395 VDF_FATAL_ERROR(fromOutput.
GetNode(),
400 VdfVector *result = _dataManager->CreateOutputCache(toOutput, toBuffer);
401 result->
Copy(*sourceVector, fromMask);
405 VdfExecutionStats::ElementsCopiedEvent,
414template<
typename DataManagerType>
423 VDF_PBEE_TRACE_FUNCTION();
434 while (betweenOutput && betweenOutput != &source) {
435 _GetExecutor()._TouchOutput(*betweenOutput);
439 return _PassOrCopyBufferInternal(
440 dataHandle, output, source, inputMask, schedule);
443template<
typename DataManagerType>
457 _dataManager->GetDataHandle(source.
GetId());
464 if (_dataManager->IsValidDataHandle(sourceHandle) &&
469 _dataManager->GetBufferData(sourceHandle);
484 if (_dataManager->HasInvalidationTimestampMismatch(
485 sourceHandle, dataHandle)) {
487 .Msg(
"Mung buffer locking between outputs "
490 output.GetDebugName().c_str());
511 result = _dataManager->PassBuffer(
512 source, sourceBuffer,
513 output, _dataManager->GetBufferData(dataHandle),
517 _executor.GetExecutionStats()) {
519 VdfExecutionStats::ElementsCopiedEvent,
533 VDF_PBEE_TRACE_SCOPE(
534 "VdfPullBasedExecutorEngine<T>::_PassOrCopyBufferInternal "
537 output, _dataManager->GetBufferData(dataHandle), source, inputMask);
543template<
typename DataManagerType>
559 if (numInputNodes == 1 && !input[0].GetMask().IsAllZeros()) {
560 _PassOrCopyBufferInternal(
561 dataHandle, *output, input[0].GetSourceOutput(), mask, schedule);
566 _dataManager->CreateOutputCache(
567 *output, _dataManager->GetBufferData(dataHandle));
570template<
typename DataManagerType>
573 std::vector< _OutputToExecute > *outputs,
574 const VdfMask& lockedCacheMask,
596template<
typename DataManagerType>
600 _OutputToExecute *stackEntry,
603 VDF_PBEE_TRACE_FUNCTION();
606 const _DataHandle dataHandle = _dataManager->GetDataHandle(output.GetId());
607 if (!_dataManager->IsValidDataHandle(dataHandle)) {
613 _dataManager->GetInvalidationTimestamp(dataHandle);
616 if (!invalidationTs) {
628 if (invalidationTs != _dataManager->GetInvalidationTimestamp()) {
629 if (!stackEntry->lockedCacheMask.IsEmpty()) {
630 stackEntry->lockedCacheMask =
VdfMask();
637 bool updated =
false;
643 _dataManager->GetBufferData(dataHandle);
644 VdfSMBLData *smblData = _dataManager->GetOrCreateSMBLData(dataHandle);
651 &stackEntry->lockedCacheMask,
653 stackEntry->absorbLockedCache =
true;
658 if (stackEntry->lockedCacheMask.IsEmpty()) {
669 &stackEntry->lockedCacheMask,
679 if (stackEntry->affective &&
681 stackEntry->lockedCacheMask,
683 stackEntry->affective =
false;
691template<
typename DataManagerType>
699 "----------------- _ExecuteOutput --------- \n");
711 const bool enableSMBL =
712 schedule.
HasSMBL() && !_GetExecutor().GetInterruptionFlag();
715 std::vector< _OutputToExecute > outputsStack;
718 _PushBackOutput(&outputsStack,
VdfMask(), output, schedule);
720 while (!outputsStack.empty()) {
723 if (_GetExecutor().HasBeenInterrupted()) {
729 bool affective = outputsStack.back().affective;
730 VdfMask lockedCacheMask = outputsStack.back().lockedCacheMask;
731 bool absorbLockedCache = outputsStack.back().absorbLockedCache;
734 const VdfMask *requestMask = NULL;
739 switch (outputsStack.back().stage) {
741 case ExecutionStageStart:
744 .Msg(
"{ BeginNode(\"%s\");\n", node.
GetDebugName().c_str());
755 _GetExecutor().GetOutputValue(*output, *requestMask)) {
758 outputsStack.pop_back();
760 TF_DEBUG(VDF_PBEE_TRACE).Msg(
" EndNodeFoundCache(); }\n");
771 _OutputToExecute *stackTop = &outputsStack.back();
772 if (_UpdateOutputForSMBL(*output, stackTop, schedule)) {
773 affective = stackTop->affective;
774 lockedCacheMask = stackTop->lockedCacheMask;
775 absorbLockedCache = stackTop->absorbLockedCache;
784 outputsStack.back().stage = ExecutionStagePreRequisitesDone;
789 if (input.input->GetSpec().IsPrerequisite()) {
790 added |= _PushBackOutput(
791 &outputsStack,
VdfMask(), *input.source, schedule);
803 case ExecutionStagePreRequisitesDone:
811 outputsStack.back().stage = ExecutionStageCompute;
832 added |= _PushBackOutput(
834 *input.source, schedule);
844 input.input->GetAssociatedOutput();
855 added |= _PushBackOutput(
856 &outputsStack, lockedCacheMask,
857 *fromBufferOutput, schedule);
865 added |= _PushBackOutput(
866 &outputsStack, lockedCacheMask, *input.source, schedule);
883 _ComputeNode(state, node, absorbLockedCache);
886 "ComputedNode(\"%s\"); }\n", node.
GetDebugName().c_str());
892 _PassThroughNode(schedule, node, absorbLockedCache);
895 .Msg(
"ComputedNodeInaffective(\"%s\"); }\n",
900 outputsStack.pop_back();
905template<
typename DataManagerType>
910 bool absorbLockedCache)
912 VDF_PBEE_TRACE_FUNCTION();
917 compute(stats, node, VdfExecutionStats::NodeEvaluateEvent);
920 stats->
LogTimestamp(VdfExecutionStats::NodeDidComputeEvent, node);
928 _dataHandleCache.clear();
930 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
935 _dataManager->GetOrCreateDataHandle(output.GetId());
936 _dataHandleCache.push_back(dataHandle);
940 _dataManager->GetBufferData(dataHandle);
945 if (absorbLockedCache ||
947 _IsNotPassing(output, outputId, schedule))) {
950 _dataManager->GetOrCreateSMBLData(dataHandle));
959 _dataManager->Touch(dataHandle);
966 if (
const VdfInput *ai = output.GetAssociatedInput()) {
968 _PrepareReadWriteBuffer(dataHandle, *ai, requestMask, schedule);
969 _dataManager->SetComputedOutputMask(bufferData, requestMask);
975 VDF_PBEE_TRACE_SCOPE(
976 "VdfPullBasedExecutorEngine<T>::_ComputeNode "
983 const bool hasBeenInterrupted = _GetExecutor().HasBeenInterrupted();
993 _dataManager->GetDataHandle(ctd->GetId());
994 if (_dataManager->IsValidDataHandle(dataHandle)) {
995 _dataManager->GetBufferData(dataHandle)->Reset();
1000 size_t outputIndex = 0;
1001 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
1006 const _DataHandle dataHandle = _dataHandleCache[outputIndex++];
1010 _dataManager->GetBufferData(dataHandle);
1015 if (!hasBeenInterrupted &&
1016 !output.GetAssociatedInput() &&
1024 "No value set for output " + output.GetDebugName() +
1025 " of type " + output.GetSpec().GetType().GetTypeName() +
1026 " named " + output.GetName().GetString());
1036 output.GetSpec().GetType(),
1038 _dataManager->GetOrCreateOutputValueForWriting(
1039 output, dataHandle));
1044 _FinalizeComputedOutput(
1048 _IsNotPassing(output, outputId, schedule));
1052 const VdfNode& node = output.GetNode();
1055 VdfExecutionStats::ElementsProcessedEvent,
1062template<
typename DataManagerType>
1067 bool absorbLockedCache)
1069 VDF_PBEE_TRACE_FUNCTION();
1071 bool passedThrough =
false;
1075 compute(stats, node, VdfExecutionStats::NodeEvaluateEvent);
1077 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
1083 _dataManager->GetOrCreateDataHandle(output.GetId());
1087 _dataManager->GetBufferData(dataHandle);
1092 if (absorbLockedCache ||
1094 && _IsNotPassing(output, outputId, schedule))) {
1097 _dataManager->GetOrCreateSMBLData(dataHandle));
1107 _dataManager->Touch(dataHandle);
1112 _PassOrCopySourceOutputBuffer(
1113 dataHandle, output, *fromBufferOutput, requestMask, schedule);
1115 passedThrough =
true;
1117 }
else if (
const VdfInput *ai = output.GetAssociatedInput()) {
1121 TF_DEV_AXIOM(output.GetAssociatedInput()->GetNumConnections()==1);
1124 _PrepareReadWriteBuffer(dataHandle, *ai, requestMask, schedule);
1125 passedThrough =
true;
1130 _FinalizeComputedOutput(
1134 _IsNotPassing(output, outputId, schedule));
1137 return passedThrough;
1140template<
typename DataManagerType>
1143 const _DataHandle dataHandle,
1145 const bool hasBeenInterrupted,
1146 const bool extendRequestMask)
1158 if (hasBeenInterrupted) {
1159 _dataManager->SetComputedOutputMask(bufferData,
VdfMask());
1167 _dataManager->SetComputedOutputMask(
1169 extendRequestMask && !lockedMask.
IsEmpty() ?
1170 lockedMask | requestMask :
1177PXR_NAMESPACE_CLOSE_SCOPE
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
void Set(size_t index)
Sets bit # index to one.
bool IsSet(size_t index) const
Returns true, if bit # index is set.
A context is the parameter bundle passed to callbacks of computations.
This object holds state that remains persistent during one round of network evaluation.
const VdfSchedule & GetSchedule() const
The schedule used for evaluation.
Execution stats profiling event logger.
void LogData(EventType event, const VdfNode &node, EventData data)
Log event API.
void LogTimestamp(EventType event, const VdfNode &node)
Log timestamp API.
static VDF_API void FillVector(TfType type, size_t numElements, VdfVector *vector)
Fills vector with the fallback value registered for the given type.
This object is responsible for storing the executor buffer data, comprised of the executor cache vect...
void ResetExecutorCache(const VdfMask &mask)
Reset the executor cache without releasing any memory and set the executor cache mask to mask.
VDF_API void RetainExecutorCache(const VdfOutputSpec &spec, VdfSMBLData *smblData)
Takes the existing executor cache and retains it within the existing VdfSMBLData object.
const VdfMask & GetExecutorCacheMask() const
Get the available mask.
VdfVector * GetExecutorCache() const
Returns the executor cache stored at this buffer data instance.
VDF_API VdfMask ReleaseExecutorCache(VdfSMBLData *smblData)
Merges the executor cache previously retained in smblData into this cache and releases the SMBL data.
A client may instantiate an object of this class and set it in an executor, to collect errors that ma...
Abstract base class for classes that execute a VdfNetwork to compute a requested set of values.
A VdfMask is placed on connections to specify the data flowing through them.
size_t GetSize() const
Returns the size of the mask.
bool IsAnySet() const
Returns true, if there is at least a single set entry.
bool IsEmpty() const
Returns true if this mask is empty, i.e.
bool Contains(const VdfMask &mask) const
Returns true if mask is a subset-of or equal to this mask, false otherwise.
size_t GetNumSet() const
Returns the number of set bits in the mask.
Class to hold on to an externally owned output and a mask.
VdfOutput * GetOutput() const
Returns the VdfOutput.
const VdfMask & GetMask() const
Returns the VdfMask.
This is the base class for all nodes in a VdfNetwork.
VDF_API const std::string GetDebugName() const
Returns the debug name for this node, if one is registered.
virtual VDF_API VdfRequiredInputsPredicate GetRequiredInputsPredicate(const VdfContext &context) const
Returns a predicate, determining whether a given input and its connections are required in order to f...
virtual void Compute(const VdfContext &context) const =0
This is the method called to perform computation.
A VdfOutput represents an output on a node.
const VdfNode & GetNode() const
Returns the owning node for this output.
VDF_API std::string GetDebugName() const
Returns the debug name for this output.
VdfId GetId() const
The unique id of this output.
This class is a collection of common functions used by pulled based executors.
VdfVector * _PassOrCopySourceOutputBuffer(const _DataHandle dataHandle, const VdfOutput &output, const VdfOutput &source, const VdfMask &inputMask, const VdfSchedule &schedule)
Fast path for when we know ahead of time the output from which we wish to pass the buffer (or copy) a...
VdfPullBasedExecutorEngine(const VdfExecutorInterface &executor, DataManagerType *dataManager)
Constructor.
void _ComputeNode(const VdfEvaluationState &state, const VdfNode &node, bool absorbLockedCache=false)
Computes node.
static bool _IsNotPassing(const VdfOutput &output, const VdfSchedule::OutputId &outputId, const VdfSchedule &schedule)
Returns true if the output is associative but does not pass the buffer to another output.
void _PrepareReadWriteBuffer(const _DataHandle dataHandle, const VdfInput &input, const VdfMask &mask, const VdfSchedule &schedule)
Prepares a buffer for a read/write output.
void RunSchedule(const VdfSchedule &schedule, const VdfRequest &computeRequest, VdfExecutorErrorLogger *errorLogger)
Executes the given schedule with a computeRequest and an optional /p errorLogger.
_ExecutionStage
This enum describes the stages that a node goes through in execution.
DataManagerType * _GetDataManager()
Returns the data manager used by this engine.
VdfVector * _CopyCache(const VdfOutput &toOutput, VdfExecutorBufferData *toBuffer, const VdfOutput &fromOutput, const VdfMask &fromMask) const
Helper method to _PrepareReadWriteBuffer that copies the cache from fromOutput to toOutput.
const VdfExecutorInterface & _GetExecutor()
Returns the executor running this engine.
VdfSpeculationExecutorEngine< DataManagerType > SpeculationExecutorEngine
The equivalent speculation executor engine.
VdfVector * _PassOrCopyBufferInternal(const _DataHandle dataHandle, const VdfOutput &output, const VdfOutput &source, const VdfMask &inputMask, const VdfSchedule &schedule) const
Common method for _PrepareReadWriteBuffer and _PassOrCopySourceOutputBuffer that attempts to pass the...
bool _PassThroughNode(const VdfSchedule &schedule, const VdfNode &node, bool absorbLockedCache=false)
Causes the outputs with associated inputs in node to have their data passed through.
DataManagerType::DataHandle _DataHandle
The data handle type from the data manager implementation.
VdfSMBLData holds per-output data that is meant to be consumed by the executor.
void RemoveUncachedMask(VdfMask *lockedCacheMask, const VdfMask &cacheMask, const VdfMask &keepMask)
Make sure that all the bits in the keepMask are provided by the cacheMask.
bool ComputeAffectiveness(const VdfMask &lockedCacheMask, const VdfMask &affectsMask)
Computes the affectiveness of the corresponding output given the accumulated lockedCacheMask and the ...
void ExtendLockedCacheMask(VdfMask *lockedCacheMask, const VdfMask &cacheMask)
Extends the lockedCacheMask by appending the bits stored in the executor cacheMask.
An OutputId is a small key object that, once obtained for a particular VdfOutput, can be used to quer...
bool IsValid() const
Returns whether this OutputId can be used to make queries about an output's scheduling.
Contains a specification of how to execute a particular VdfNetwork.
VDF_API const VdfMask & GetAffectsMask(const OutputId &outputId) const
Returns the affects mask associated with the given OutputId.
const VdfNetwork * GetNetwork() const
Returns the network for this schedule.
VDF_API OutputId GetOutputId(const VdfOutput &output) const
Returns a small, cheap OutputId, which can be passed to other Get* methods in this class to efficient...
VDF_API const VdfMask & GetRequestMask(const OutputId &outputId) const
Returns the request mask associated with the given OutputId.
VDF_API const VdfOutput * GetFromBufferOutput(const OutputId &outputId) const
Returns the "from buffer's" output associated with the given OutputId.
VDF_API InputsRange GetInputs(const VdfNode &node) const
Returns a range of inputs scheduled for the given node.
int GetScheduleNodeIndex(const OutputId &outputId) const
Returns the node index of the schedule node associated with the given outputId.
VDF_API const VdfMask & GetKeepMask(const OutputId &outputId) const
Returns the keep mask associated with the given OutputId.
VDF_API const VdfOutput * GetPassToOutput(const OutputId &outputId) const
Returns the "pass to" output associated with the given OutputId.
VDF_API const VdfNode * GetNode(const OutputId &outputId) const
Returns the VdfNode that owns the VdfOutput associated with the given outputId.
VDF_API const VdfOutput * GetOutputToClear(const VdfNode &node) const
Returns the output whose temporary buffer can be immediately deallocated after node has finished exec...
ScheduleNodeVector & GetScheduleNodeVector()
Returns the vector of schedule nodes in this schedule.
VDF_API bool IsAffective(const OutputId &outputId) const
Returns true if the output is expected to have an effect on its corresponding input,...
VDF_API const VdfOutput * GetOutput(const OutputId &outputId) const
Returns the scheduled VdfOutput associated with the given OutputId.
bool HasSMBL() const
Returns true if this schedule participates in sparse mung buffer locking.
This class provides an executor engine to the speculation executor.
This class is used to abstract away knowledge of the cache data used for each node.
void Copy(const VdfVector &rhs, const VdfMask &mask)
Copies the contents of rhs into this vector.
unsigned int VdfInvalidationTimestamp
Type of the timestamp that identifies the most recent round of invalidation.
#define TF_DEBUG(enumVal)
Evaluate and print debugging message msg if enumVal is enabled for debugging.
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
#define TF_WARN(...)
Issue a warning, but continue execution.
VDF_API const VdfOutput * VdfGetAssociatedSourceOutput(const VdfOutput &output)
Returns the output that is the source of the associated input of output, if any and NULL otherwise.
bool Vdf_IsPoolOutput(const VdfOutput &output)
Returns true if output is a pool output, i.e., an output that has an associated input,...
Scoped event that automatically pushes and pops malloc tags for the given VdfNode.