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;
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,
340 VdfRequest::IndexedView requestView(computeRequest);
341 for (
size_t i = 0; i < requestView.GetSize(); ++i) {
353 if (_GetExecutor().GetOutputValue(output, mask)) {
354 callback(*maskedOutput, i);
358 VDF_PBEE_TRACE_SCOPE(
359 "VdfPullBasedExecutorEngine<T>::RunSchedule (executing output)");
360 _ExecuteOutput(state, output, &executedNodes);
363 if (_GetExecutor().HasBeenInterrupted()) {
370 callback(*maskedOutput, i);
375template<
typename DataManagerType>
390 _executor.GetOutputValue(fromOutput, fromMask);
394 VDF_FATAL_ERROR(fromOutput.
GetNode(),
399 VdfVector *result = _dataManager->CreateOutputCache(toOutput, toBuffer);
400 result->
Copy(*sourceVector, fromMask);
404 VdfExecutionStats::ElementsCopiedEvent,
413template<
typename DataManagerType>
422 VDF_PBEE_TRACE_FUNCTION();
433 while (betweenOutput && betweenOutput != &source) {
434 _GetExecutor()._TouchOutput(*betweenOutput);
438 return _PassOrCopyBufferInternal(
439 dataHandle, output, source, inputMask, schedule);
442template<
typename DataManagerType>
456 _dataManager->GetDataHandle(source.
GetId());
463 if (_dataManager->IsValidDataHandle(sourceHandle) &&
468 _dataManager->GetBufferData(sourceHandle);
483 if (_dataManager->HasInvalidationTimestampMismatch(
484 sourceHandle, dataHandle)) {
486 .Msg(
"Mung buffer locking between outputs "
510 result = _dataManager->PassBuffer(
511 source, sourceBuffer,
512 output, _dataManager->GetBufferData(dataHandle),
516 _executor.GetExecutionStats()) {
518 VdfExecutionStats::ElementsCopiedEvent,
532 VDF_PBEE_TRACE_SCOPE(
533 "VdfPullBasedExecutorEngine<T>::_PassOrCopyBufferInternal "
536 output, _dataManager->GetBufferData(dataHandle), source, inputMask);
542template<
typename DataManagerType>
558 if (numInputNodes == 1 && !input[0].GetMask().IsAllZeros()) {
559 _PassOrCopyBufferInternal(
560 dataHandle, *output, input[0].GetSourceOutput(), mask, schedule);
565 _dataManager->CreateOutputCache(
566 *output, _dataManager->GetBufferData(dataHandle));
569template<
typename DataManagerType>
572 std::vector< _OutputToExecute > *outputs,
573 const VdfMask& lockedCacheMask,
595template<
typename DataManagerType>
599 _OutputToExecute *stackEntry,
602 VDF_PBEE_TRACE_FUNCTION();
605 const _DataHandle dataHandle = _dataManager->GetDataHandle(output.
GetId());
606 if (!_dataManager->IsValidDataHandle(dataHandle)) {
612 _dataManager->GetInvalidationTimestamp(dataHandle);
615 if (!invalidationTs) {
627 if (invalidationTs != _dataManager->GetInvalidationTimestamp()) {
628 if (!stackEntry->lockedCacheMask.IsEmpty()) {
629 stackEntry->lockedCacheMask =
VdfMask();
636 bool updated =
false;
642 _dataManager->GetBufferData(dataHandle);
643 VdfSMBLData *smblData = _dataManager->GetOrCreateSMBLData(dataHandle);
650 &stackEntry->lockedCacheMask,
652 stackEntry->absorbLockedCache =
true;
657 if (stackEntry->lockedCacheMask.IsEmpty()) {
668 &stackEntry->lockedCacheMask,
678 if (stackEntry->affective &&
680 stackEntry->lockedCacheMask,
682 stackEntry->affective =
false;
690template<
typename DataManagerType>
698 "----------------- _ExecuteOutput --------- \n");
710 const bool enableSMBL =
711 schedule.
HasSMBL() && !_GetExecutor().GetInterruptionFlag();
714 std::vector< _OutputToExecute > outputsStack;
717 _PushBackOutput(&outputsStack,
VdfMask(), output, schedule);
719 while (!outputsStack.empty()) {
722 if (_GetExecutor().HasBeenInterrupted()) {
728 bool affective = outputsStack.back().affective;
729 VdfMask lockedCacheMask = outputsStack.back().lockedCacheMask;
730 bool absorbLockedCache = outputsStack.back().absorbLockedCache;
733 const VdfMask *requestMask = NULL;
738 switch (outputsStack.back().stage) {
740 case ExecutionStageStart:
743 .Msg(
"{ BeginNode(\"%s\");\n", node.
GetDebugName().c_str());
754 _GetExecutor().GetOutputValue(*output, *requestMask)) {
757 outputsStack.pop_back();
759 TF_DEBUG(VDF_PBEE_TRACE).Msg(
" EndNodeFoundCache(); }\n");
770 _OutputToExecute *stackTop = &outputsStack.back();
771 if (_UpdateOutputForSMBL(*output, stackTop, schedule)) {
772 affective = stackTop->affective;
773 lockedCacheMask = stackTop->lockedCacheMask;
774 absorbLockedCache = stackTop->absorbLockedCache;
783 outputsStack.back().stage = ExecutionStagePreRequisitesDone;
788 if (input.input->GetSpec().IsPrerequisite()) {
789 added |= _PushBackOutput(
790 &outputsStack,
VdfMask(), *input.source, schedule);
802 case ExecutionStagePreRequisitesDone:
810 outputsStack.back().stage = ExecutionStageCompute;
831 added |= _PushBackOutput(
833 *input.source, schedule);
843 input.input->GetAssociatedOutput();
854 added |= _PushBackOutput(
855 &outputsStack, lockedCacheMask,
856 *fromBufferOutput, schedule);
864 added |= _PushBackOutput(
865 &outputsStack, lockedCacheMask, *input.source, schedule);
882 _ComputeNode(state, node, absorbLockedCache);
885 "ComputedNode(\"%s\"); }\n", node.
GetDebugName().c_str());
891 _PassThroughNode(schedule, node, absorbLockedCache);
894 .Msg(
"ComputedNodeInaffective(\"%s\"); }\n",
899 outputsStack.pop_back();
904template<
typename DataManagerType>
909 bool absorbLockedCache)
911 VDF_PBEE_TRACE_FUNCTION();
916 compute(stats, node, VdfExecutionStats::NodeEvaluateEvent);
919 stats->
LogTimestamp(VdfExecutionStats::NodeDidComputeEvent, node);
927 _dataHandleCache.clear();
929 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
934 _dataManager->GetOrCreateDataHandle(output.
GetId());
935 _dataHandleCache.push_back(dataHandle);
939 _dataManager->GetBufferData(dataHandle);
944 if (absorbLockedCache ||
946 _IsNotPassing(output, outputId, schedule))) {
949 _dataManager->GetOrCreateSMBLData(dataHandle));
958 _dataManager->Touch(dataHandle);
967 _PrepareReadWriteBuffer(dataHandle, *ai, requestMask, schedule);
968 _dataManager->SetComputedOutputMask(bufferData, requestMask);
974 VDF_PBEE_TRACE_SCOPE(
975 "VdfPullBasedExecutorEngine<T>::_ComputeNode "
982 const bool hasBeenInterrupted = _GetExecutor().HasBeenInterrupted();
992 _dataManager->GetDataHandle(ctd->GetId());
993 if (_dataManager->IsValidDataHandle(dataHandle)) {
994 _dataManager->GetBufferData(dataHandle)->Reset();
999 size_t outputIndex = 0;
1000 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
1005 const _DataHandle dataHandle = _dataHandleCache[outputIndex++];
1009 _dataManager->GetBufferData(dataHandle);
1014 if (!hasBeenInterrupted &&
1037 _dataManager->GetOrCreateOutputValueForWriting(
1038 output, dataHandle));
1043 _FinalizeComputedOutput(
1047 _IsNotPassing(output, outputId, schedule));
1054 VdfExecutionStats::ElementsProcessedEvent,
1061template<
typename DataManagerType>
1066 bool absorbLockedCache)
1068 VDF_PBEE_TRACE_FUNCTION();
1070 bool passedThrough =
false;
1074 compute(stats, node, VdfExecutionStats::NodeEvaluateEvent);
1076 VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
1082 _dataManager->GetOrCreateDataHandle(output.
GetId());
1086 _dataManager->GetBufferData(dataHandle);
1091 if (absorbLockedCache ||
1093 && _IsNotPassing(output, outputId, schedule))) {
1096 _dataManager->GetOrCreateSMBLData(dataHandle));
1106 _dataManager->Touch(dataHandle);
1111 _PassOrCopySourceOutputBuffer(
1112 dataHandle, output, *fromBufferOutput, requestMask, schedule);
1114 passedThrough =
true;
1123 _PrepareReadWriteBuffer(dataHandle, *ai, requestMask, schedule);
1124 passedThrough =
true;
1129 _FinalizeComputedOutput(
1133 _IsNotPassing(output, outputId, schedule));
1136 return passedThrough;
1139template<
typename DataManagerType>
1142 const _DataHandle dataHandle,
1144 const bool hasBeenInterrupted,
1145 const bool extendRequestMask)
1157 if (hasBeenInterrupted) {
1158 _dataManager->SetComputedOutputMask(bufferData,
VdfMask());
1166 _dataManager->SetComputedOutputMask(
1168 extendRequestMask && !lockedMask.
IsEmpty() ?
1169 lockedMask | requestMask :
1176PXR_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.
std::string const & GetString() const
Return the string that this token represents.
TF_API const std::string & GetTypeName() const
Return the machine-independent name for this type.
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.
VDF_API const VdfOutputSpec & GetSpec() const
Returns the connector specification object for this output.
VDF_API const TfToken & GetName() const
Returns the name of this output.
const VdfInput * GetAssociatedInput() const
Returns the in/out connector associated with this output.
TfType GetType() const
Returns the type of this spec.
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.
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.
VdfSpeculationExecutorEngine< DataManagerType > SpeculationExecutorEngine
The equivalent speculation executor engine.
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.