7 #ifndef PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
8 #define PXR_EXEC_VDF_SPECULATION_EXECUTOR_ENGINE_H
37 template <
typename DataManagerType>
52 DataManagerType *dataManager) :
54 speculationExecutor, dataManager),
56 speculationExecutor.GetNonSpeculationParentExecutor())) {
57 TF_VERIFY(_writeBackExecutor);
68 schedule, computeRequest, errorLogger,
96 struct _OutputToExecute {
101 stage(_ExecutionStageStart),
103 inputsSpeculate(false)
116 bool inputsSpeculate;
122 bool _PushBackOutputForSpeculation(
123 std::vector< _OutputToExecute > *outputs,
130 void _ExecuteOutputForSpeculation(
137 void _WriteBackComputedOutput(
149 template <
typename DataManagerType>
152 std::vector< _OutputToExecute > *outputs,
159 outputs->push_back(_OutputToExecute(outputId));
169 template <
typename DataManagerType>
170 template <
typename F>
181 Base::_GetDataManager()->Resize(*schedule.
GetNetwork());
186 TfBits executedNodes(numNodes);
189 TfBits speculatedNodes(numNodes);
196 for (
size_t i = 0; i < requestView.
GetSize(); ++i) {
208 if (Base::_GetExecutor().GetOutputValue(output, mask)) {
209 callback(*maskedOutput, i);
213 _ExecuteOutputForSpeculation(
214 state, output, &executedNodes, &speculatedNodes);
217 if (Base::_GetExecutor().HasBeenInterrupted()) {
224 callback(*maskedOutput, i);
229 template <
typename DataManagerType>
237 TF_DEBUG(VDF_SEE_TRACE).Msg(
"{ SpeculationOutputExecuteBegin();\n");
243 std::vector< _OutputToExecute > outputsStack;
250 std::vector< bool > speculated;
254 _PushBackOutputForSpeculation(&outputsStack, output, schedule);
256 bool hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
258 while (!outputsStack.empty() && !hasBeenInterrupted) {
263 typename Base::_ExecutionStage stage = outputsStack.back().stage;
264 const size_t outputIndex = outputsStack.size() - 1;
271 bool previousStageSpeculated =
false;
272 while (outputsStack.back().numPushed) {
273 outputsStack.back().numPushed--;
274 previousStageSpeculated |= speculated.back();
275 speculated.pop_back();
280 case Base::ExecutionStageStart:
283 .Msg(
"{ SpeculationBeginNode(%p, \"%s\");\n",
290 if (static_cast<const VdfSpeculationExecutorBase &>(
291 Base::_GetExecutor()).IsSpeculatingNode(&node)) {
292 speculated.push_back(
true);
293 outputsStack.pop_back();
296 .Msg(
"SpeculationEndNodeSpeculationNode(); (cycle) }\n");
305 if (executedNodes->
IsSet(scheduleNodeIndex)) {
306 speculated.push_back(
307 speculatedNodes->
IsSet(scheduleNodeIndex));
308 outputsStack.pop_back();
311 .Msg(
"SpeculationEndNodeRedundantCompute(); }\n");
318 if (Base::_GetExecutor().GetOutputValue(
321 speculated.push_back(
false);
322 outputsStack.pop_back();
325 .Msg(
"SpeculationEndNodeFoundCache(); }\n");
334 outputsStack.back().stage = Base::ExecutionStagePreRequisitesDone;
339 if (input.input->GetSpec().IsPrerequisite()) {
340 const bool pushed = _PushBackOutputForSpeculation(
341 &outputsStack, *input.source, schedule);
342 outputsStack[outputIndex].numPushed += pushed;
349 if (outputsStack[outputIndex].numPushed > 0) {
354 case Base::ExecutionStagePreRequisitesDone:
361 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
368 outputsStack.back().stage = Base::ExecutionStageReadsDone;
372 if (affective && !previousStageSpeculated) {
387 const bool pushed = _PushBackOutputForSpeculation(
388 &outputsStack, *input.source, schedule);
389 outputsStack[outputIndex].numPushed += pushed;
397 if (outputsStack[outputIndex].numPushed > 0) {
401 case Base::ExecutionStageReadsDone:
404 outputsStack.back().stage = Base::ExecutionStageCompute;
407 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
412 input.input->GetAssociatedOutput();
423 const bool pushed = _PushBackOutputForSpeculation(
424 &outputsStack, *fromBufferOutput, schedule);
425 outputsStack[outputIndex].numPushed += pushed;
433 const bool pushed = _PushBackOutputForSpeculation(
434 &outputsStack, *input.source, schedule);
435 outputsStack[outputIndex].numPushed += pushed;
440 if (outputsStack[outputIndex].numPushed > 0) {
449 outputsStack.back().inputsSpeculate |= previousStageSpeculated;
452 executedNodes->
Set(scheduleNodeIndex);
456 if (outputsStack.back().inputsSpeculate) {
459 .Msg(
"SpeculationSkipNode (cycle) (\"%s\"); }\n",
463 speculatedNodes->
Set(scheduleNodeIndex);
464 speculated.push_back(
true);
468 }
else if (affective) {
471 Base::_ComputeNode(state, node);
472 speculated.push_back(
false);
475 .Msg(
"SpeculationComputedNode(\"%s\"); }\n",
487 .Msg(
"SpeculationPassThrough(\"%s\"); }\n",
490 Base::_PassThroughNode(schedule, node);
491 speculated.push_back(
false);
496 hasBeenInterrupted = Base::_GetExecutor().HasBeenInterrupted();
512 if (_writeBackExecutor &&
513 !hasBeenInterrupted &&
514 !outputsStack.back().inputsSpeculate) {
515 _WriteBackComputedOutput(output, outputId, schedule);
517 Base::_GetExecutor()._TouchOutput(output);
520 outputsStack.pop_back();
524 TF_DEBUG(VDF_SEE_TRACE).Msg(
"SpeculationOutputExecuteEnd(); }\n");
527 template <
typename DataManagerType>
535 const typename Base::_DataHandle dataHandle =
536 Base::_GetDataManager()->GetDataHandle(output.
GetId());
537 if (!Base::_GetDataManager()->IsValidDataHandle(dataHandle)) {
543 Base::_GetDataManager()->GetBufferData(dataHandle);
567 _writeBackExecutor->SetOutputValue(output, *value, computedMask);
594 const VdfMask *writeBackMask = &computedMask;
597 !_writeBackExecutor->HasInvalidationTimestampMismatch(
598 output, *passToOutput)) {
602 if (!writeBackMask->
IsEmpty()) {
603 _writeBackExecutor->SetOutputValue(output, *value, *writeBackMask);
VDF_API bool IsAffective(const OutputId &outputId) const
virtual VDF_API VdfRequiredInputsPredicate GetRequiredInputsPredicate(const VdfContext &context) const
VDF_API const VdfMask & GetKeepMask(const OutputId &outputId) const
void RunSchedule(const VdfSchedule &schedule, const VdfRequest &computeRequest, VdfExecutorErrorLogger *errorLogger)
VDF_API const VdfOutput * GetPassToOutput(const OutputId &outputId) const
const VdfNetwork * GetNetwork() const
ScheduleNodeVector & GetScheduleNodeVector()
#define VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(OUTPUT_ID_NAME, VDF_SCHEDULE, VDF_NODE)
VDF_API const VdfOutput * GetFromBufferOutput(const OutputId &outputId) const
#define PXR_NAMESPACE_OPEN_SCOPE
GLsizei const GLfloat * value
VDF_API OutputId GetOutputId(const VdfOutput &output) const
VDF_API const std::string GetDebugName() const
const VdfMask & GetMask() const
A VdfMask is placed on connections to specify the data flowing through them.
VdfSpeculationExecutorEngine(const VdfSpeculationExecutorBase &speculationExecutor, DataManagerType *dataManager)
VDF_API InputsRange GetInputs(const VdfNode &node) const
const VdfInput * GetAssociatedInput() const
VDF_API const VdfOutput * GetOutput(const OutputId &outputId) const
#define TF_DEV_AXIOM(cond)
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
void ResetExecutorCache(const VdfMask &mask)
int GetScheduleNodeIndex(const OutputId &outputId) const
Contains a specification of how to execute a particular VdfNetwork.
const VdfMaskedOutput * Get(const size_t i) const
VDF_API const VdfNode * GetNode(const OutputId &outputId) const
const VdfSchedule & GetSchedule() const
This object is responsible for storing the executor buffer data, comprised of the executor cache vect...
#define TF_DEBUG(enumVal)
Class to hold on to an externally owned output and a mask.
const VdfMask & GetExecutorCacheMask() const
VDF_API const VdfMask & GetRequestMask(const OutputId &outputId) const
#define PXR_NAMESPACE_CLOSE_SCOPE
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...
VdfVector * GetExecutorCache() const
bool IsSet(size_t index) const
VdfOutput * GetOutput() const