Loading...
Searching...
No Matches
schedule.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_SCHEDULE_H
8#define PXR_EXEC_VDF_SCHEDULE_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/exec/vdf/api.h"
15#include "pxr/exec/vdf/countingIterator.h"
16#include "pxr/exec/vdf/node.h"
20#include "pxr/exec/vdf/types.h"
21
22#include "pxr/base/tf/bits.h"
23
24#include <atomic>
25#include <vector>
26
27PXR_NAMESPACE_OPEN_SCOPE
28
29class VdfConnection;
30class VdfNetwork;
31
40
42{
43public:
47 template <typename Iterator>
49 public:
50 template <typename IteratorConvertible>
51 IteratorRange(IteratorConvertible begin, IteratorConvertible end) :
52 _begin(begin), _end(end) {}
53
54 Iterator begin() const { return _begin; }
55 Iterator end() const { return _end; }
56 bool empty() const { return _begin == _end; }
57 size_t size() const { return std::distance(_begin, _end); }
58
59 private:
60 Iterator _begin;
61 Iterator _end;
62 };
63
66 VdfSchedule(const VdfSchedule &) = delete;
67 VdfSchedule &operator=(const VdfSchedule &) = delete;
68
71 using ScheduleNodeVector = std::vector<VdfScheduleNode>;
72
76
81
86
92 class OutputId {
93 public:
98 bool IsValid() const {
99 return _scheduleNodeIndex >= 0 && _secondaryIndex >= 0;
100 }
101
110 _secondaryIndex++;
111 return *this;
112 }
113
116 bool operator==(const OutputId &rhs) const {
117 return _scheduleNodeIndex == rhs._scheduleNodeIndex &&
118 _secondaryIndex == rhs._secondaryIndex;
119 }
120
121 bool operator!=(const OutputId &rhs) const {
122 return !(*this == rhs);
123 }
124
125 private:
126 // Construct an OutputId with a specific schedule node index
127 // and secondary index.
128 //
129 // The scheduleNodeIndex is expected to be one of the possible values
130 // stored in VdfSchedule::_nodesToIndexMap (i.e. [0, _nodes.size()-1])
131 // or a negative value to indicate an invalid id.
132 //
133 // And invalid id signifies that an output is not scheduled.
134 //
135 // The secondaryIndex is an index into the associated
136 // VdfScheduleNode's VdfScheduleOutputs vector, which stores data
137 // about the scheduled node explicitly.
138 //
139 OutputId(int scheduleNodeIndex, int secondaryIndex) :
140 _scheduleNodeIndex(scheduleNodeIndex),
141 _secondaryIndex(secondaryIndex)
142 {}
143
144 // Only VdfSchedule is allowed to construct instances of VdfOuputId.
145 friend class VdfSchedule;
146
147 // Data members
148 int _scheduleNodeIndex;
149 int _secondaryIndex;
150 };
151
154 VDF_API
156
159 VDF_API
161
167 VDF_API
168 void Clear();
169
173 bool IsValid() const {
174 return _isValid.load(std::memory_order_relaxed);
175 }
176
179 const VdfNetwork *GetNetwork() const { return _network; }
180
182
185 VDF_API
186 bool IsScheduled(const VdfNode &node) const;
187
193 VDF_API
194 OutputId GetOutputId(const VdfOutput &output) const;
195
200 VDF_API
202
208 VDF_API
209 void AddInput(const VdfConnection &connection, const VdfMask &mask);
210
218 VDF_API
220
224 VDF_API
225 const VdfNode *GetNode(const OutputId &outputId) const;
226
237 VDF_API
239
251 VDF_API
252 OutputId GetOutputIdsEnd(const VdfNode &node) const;
253
257 VDF_API
258 InputsRange GetInputs(const VdfNode &node) const;
259
266 VDF_API
267 bool IsAffective(const OutputId &outputId) const;
268
270
276
279 VDF_API
280 const VdfOutput *GetOutput(const OutputId &outputId) const;
281
285 VDF_API
286 const VdfOutput *GetOutputToClear(const VdfNode &node) const;
287
290 VDF_API
291 const VdfMask &GetRequestMask(const OutputId &outputId) const;
292
296 const VdfScheduleTaskIndex invocationIndex) const {
297 TF_DEV_AXIOM(!VdfScheduleTaskIsInvalid(invocationIndex));
298 return _nodeInvocations[invocationIndex].requestMask;
299 }
300
305 VDF_API
307 const OutputId &outputId,
308 const VdfMask **requestMask,
309 const VdfMask **affectsMask) const;
310
315 const VdfScheduleTaskIndex invocationIndex,
316 const VdfMask **requestMask,
317 const VdfMask **affectsMask) const {
318 TF_DEV_AXIOM(!VdfScheduleTaskIsInvalid(invocationIndex));
319 *requestMask = &_nodeInvocations[invocationIndex].requestMask;
320 *affectsMask = &_nodeInvocations[invocationIndex].affectsMask;
321 }
322
325 VDF_API
326 const VdfMask &GetAffectsMask(const OutputId &outputId) const;
327
330 VDF_API
331 const VdfMask &GetKeepMask(const OutputId &outputId) const;
332
336 const VdfScheduleTaskIndex invocationIndex) const {
337 TF_DEV_AXIOM(!VdfScheduleTaskIsInvalid(invocationIndex));
338 return _nodeInvocations[invocationIndex].keepMask;
339 }
340
343 VDF_API
344 const VdfOutput *GetPassToOutput(const OutputId &outputId) const;
345
348 VDF_API
349 const VdfOutput *GetFromBufferOutput(const OutputId &outputId) const;
350
354 bool HasSMBL() const {
355 return _hasSMBL;
356 }
357
359
363 VDF_API
365 const VdfNode &node,
366 const VdfScheduledOutputCallback &callback) const;
367
373 return _numUniqueInputDeps;
374 }
375
378 size_t GetNumComputeTasks() const {
379 return _computeTasks.size();
380 }
381
384 size_t GetNumInputsTasks() const {
385 return _inputsTasks.size();
386 }
387
390 size_t GetNumPrepTasks() const {
391 return _numPrepTasks;
392 }
393
396 size_t GetNumKeepTasks() const {
397 return _numKeepTasks;
398 }
399
403 const TaskIdRange GetComputeTaskIds(const VdfNode &node) const {
404 int scheduleNodeIndex = _GetScheduleNodeIndex(node);
405 TF_DEV_AXIOM(scheduleNodeIndex >= 0);
406 return TaskIdRange(
407 _nodesToComputeTasks[scheduleNodeIndex].taskId,
408 _nodesToComputeTasks[scheduleNodeIndex].taskId +
409 _nodesToComputeTasks[scheduleNodeIndex].taskNum);
410 }
411
415 const VdfScheduleInputDependency &input) const {
416 return TaskIdRange(
417 input.computeOrKeepTaskId,
418 input.computeOrKeepTaskId + input.computeTaskNum);
419 }
420
424 int scheduleNodeIndex = _GetScheduleNodeIndex(node);
425 return scheduleNodeIndex >= 0
426 ? _nodesToKeepTasks[scheduleNodeIndex]
427 : VdfScheduleTaskInvalid;
428 }
429
433 const VdfScheduleTaskIndex index) const {
434 TF_DEV_AXIOM(index < _computeTasks.size());
435 return _computeTasks[index];
436 }
437
441 const VdfScheduleTaskIndex index) const {
442 TF_DEV_AXIOM(index < _inputsTasks.size());
443 return _inputsTasks[index];
444 }
445
450 const VdfScheduleInputsTask &task) const {
451 std::vector<VdfScheduleInputDependency>::const_iterator begin =
452 _inputDeps.begin() + task.inputDepIndex;
453 return InputDependencyRange(begin, begin + task.prereqsNum);
454 }
455
460 const VdfScheduleInputsTask &task) const {
461 std::vector<VdfScheduleInputDependency>::const_iterator begin =
462 _inputDeps.begin() + task.inputDepIndex + task.prereqsNum;
463 return InputDependencyRange(begin, begin + task.optionalsNum);
464 }
465
470 const VdfScheduleComputeTask &task) const {
471 std::vector<VdfScheduleInputDependency>::const_iterator begin =
472 _inputDeps.begin() + task.requiredsIndex;
473 return InputDependencyRange(begin, begin + task.requiredsNum);
474 }
475
478 VDF_API
480 const OutputId outputId) const;
481
483
488 bool IsSmallSchedule() const { return _isSmallSchedule; }
489
492 VDF_API
493 void SetRequest(const VdfRequest &request);
494
497 const VdfRequest &GetRequest() const { return _request; }
498
505 return _nodes;
506 }
507
509 return _nodes;
510 }
511
515 int GetScheduleNodeIndex(const OutputId &outputId) const {
516 return outputId._scheduleNodeIndex;
517 }
518
522 const TfBits &GetScheduledNodeBits() const { return _scheduledNodes; }
523
526 VDF_API
527 void SetRequestMask(const OutputId &outputId, const VdfMask &mask);
528
531 VDF_API
532 void SetAffectsMask(const OutputId &outputId, const VdfMask &mask);
533
536 VDF_API
537 void SetKeepMask(const OutputId &outputId, const VdfMask &mask);
538
541 VDF_API
542 void SetPassToOutput(const OutputId &outputId, const VdfOutput *output);
543
546 VDF_API
547 void SetFromBufferOutput(const OutputId &outputId, const VdfOutput *output);
548
552 VDF_API
553 void SetOutputToClear(const VdfNode &node, const VdfOutput *outputToClear);
554
557 VDF_API
558 void InitializeFromNetwork(const VdfNetwork &network);
559
562 void SetHasSMBL(bool enable) {
563 _hasSMBL = enable;
564 }
565
567
568private:
569
570 // The VdfScheduler and its derived classes are the only objects allowed
571 // to set a scheduler as valid.
572 friend class VdfScheduler;
573
574 // The VdfScheduler calls this method to make sure that this schedule
575 // is marked as valid and registered with a particular network.
576 //
577 void _SetIsValidForNetwork(const VdfNetwork *network);
578
579 // Returns the index into _nodes that corresponds to the given VdfNode.
580 // If the node is not scheduled and thus has no corresponding _nodes entry,
581 // this method returns a value less than 0.
582 VDF_API
583 int _GetScheduleNodeIndex(const VdfNode &node) const;
584
585 // Ensures that \p node is in the schedule and returns its scheduleNode
586 // index.
587 //
588 int _EnsureNodeInSchedule(const VdfNode &node);
589
590 // Data Members
591
592 // The total list of nodes that we have to execute. This is where the
593 // schedule nodes are owned.
594 ScheduleNodeVector _nodes;
595
596 // The request for this schedule
597 VdfRequest _request;
598
599 // This is a vector that maps VdfNodes to VdfScheduleNode index in _nodes.
600 std::vector<int> _nodesToIndexMap;
601
602 // The network that we are registered with. All of our scheduled nodes
603 // belong to this network.
604 const VdfNetwork *_network;
605
606 // Bits are set for each schedule node's index.
607 TfBits _scheduledNodes;
608
609 // Flag as to whether or not the schedule is valid.
610 std::atomic_bool _isValid;
611
612 // A flag that determines whether this schedule's query methods will
613 // use the small schedule optimization, which is to assume there is no
614 // _nodesToIndexMap and instead find schedule nodes by searching the
615 // _nodes array directly.
616 bool _isSmallSchedule;
617
618 // This flag indicates whether this schedule participates in sparse mung
619 // buffer locking.
620 bool _hasSMBL;
621
622 // The number of unique input dependencies created for this schedule. Each
623 // unique input dependencies refers to the same output and mask combination.
624 size_t _numUniqueInputDeps;
625
626 // The scheduled tasks for parallel evaluation.
629 size_t _numKeepTasks;
630 size_t _numPrepTasks;
631
632 // Scheduled node invocations for nodes with multiple invocations.
634
635 // The array of input dependencies used to orchestrate task synchronization.
636 std::vector<VdfScheduleInputDependency> _inputDeps;
637
638 // Arrays that map from the scheduled node index to the scheduled tasks
639 // corresponding to that node.
640 std::vector<VdfScheduleNodeTasks> _nodesToComputeTasks;
641 std::vector<VdfScheduleTaskIndex> _nodesToKeepTasks;
642};
643
645
646// Example usage:
647// void MyFunction(const VdfSchedule &schedule, const VdfNode &node) {
648// VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(outputId, schedule, node) {
649// DoThingsWithARequestMask(schedule->GetRequestMask(outputId));
650// }
651// }
652//
653#define VDF_FOR_EACH_SCHEDULED_OUTPUT_ID(OUTPUT_ID_NAME,VDF_SCHEDULE,VDF_NODE) \
654 for (VdfSchedule::OutputId __endId = \
655 (VDF_SCHEDULE).GetOutputIdsEnd(VDF_NODE), \
656 OUTPUT_ID_NAME = (VDF_SCHEDULE).GetOutputIdsBegin(VDF_NODE) ; \
657 OUTPUT_ID_NAME != __endId; ++OUTPUT_ID_NAME)
658
659
661
662PXR_NAMESPACE_CLOSE_SCOPE
663
664#endif
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
Definition bits.h:49
A class that fully represents a connection between two VdfNodes.
Definition connection.h:30
A VdfMask is placed on connections to specify the data flowing through them.
Definition mask.h:37
A VdfNetwork is a collection of VdfNodes and their connections.
Definition network.h:60
This is the base class for all nodes in a VdfNetwork.
Definition node.h:53
A VdfOutput represents an output on a node.
Definition output.h:32
Minimal iterator range that the schedule returns instances of, in order to facilitate iterating over ...
Definition schedule.h:48
An OutputId is a small key object that, once obtained for a particular VdfOutput, can be used to quer...
Definition schedule.h:92
OutputId & operator++()
Increment this OutputId to refer to the next scheduled output on the current output's node.
Definition schedule.h:109
bool IsValid() const
Returns whether this OutputId can be used to make queries about an output's scheduling.
Definition schedule.h:98
bool operator==(const OutputId &rhs) const
Equality operator.
Definition schedule.h:116
Contains a specification of how to execute a particular VdfNetwork.
Definition schedule.h:42
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.
Definition schedule.h:179
void SetHasSMBL(bool enable)
Enables SMBL for this schedule.
Definition schedule.h:562
InputDependencyRange GetRequiredInputDependencies(const VdfScheduleComputeTask &task) const
Returns an iterable range of required (i.e.
Definition schedule.h:469
VDF_API OutputId GetOrCreateOutputId(const VdfOutput &output)
Similar to GetOutputId, but creates an OutptuId if none exists, effectively adding the output to the ...
VDF_API void SetPassToOutput(const OutputId &outputId, const VdfOutput *output)
Registers a "pass to" output for the output indicated by outputId.
const VdfMask & GetKeepMask(const VdfScheduleTaskIndex invocationIndex) const
Returns the keep mask for the given node invocation index.
Definition schedule.h:335
VDF_API VdfSchedule()
Constructs an empty schedule.
VDF_API ~VdfSchedule()
Destructor.
VDF_API void InitializeFromNetwork(const VdfNetwork &network)
Initializes structures based on the size of the network.
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 void SetAffectsMask(const OutputId &outputId, const VdfMask &mask)
Registers an affects mask for the output indicated by outputId.
VDF_API const VdfMask & GetRequestMask(const OutputId &outputId) const
Returns the request mask associated with the given OutputId.
size_t GetNumUniqueInputDependencies() const
Returns the number of unique input dependencies created for the scheduled task graph.
Definition schedule.h:372
VDF_API OutputId GetOutputIdsBegin(const VdfNode &node) const
Gets an OutputId identifying the first scheduled output for the given node, if any.
IteratorRange< std::vector< VdfScheduleInputDependency >::const_iterator > InputDependencyRange
An iterable range of input dependencies.
Definition schedule.h:79
InputDependencyRange GetPrereqInputDependencies(const VdfScheduleInputsTask &task) const
Returns an iterable range of prereq input dependencies for the given inputs task.
Definition schedule.h:449
VDF_API OutputId GetOutputIdsEnd(const VdfNode &node) const
Gets an OutputId identifying the "end" of the scheduled outputs for a node.
VDF_API const VdfOutput * GetFromBufferOutput(const OutputId &outputId) const
Returns the "from buffer's" output associated with the given OutputId.
const VdfScheduleTaskIndex GetKeepTaskIndex(const VdfNode &node) const
Returns an index to the keep task associated with the given node.
Definition schedule.h:423
const VdfScheduleComputeTask & GetComputeTask(const VdfScheduleTaskIndex index) const
Returns the compute task associated with the given task index.
Definition schedule.h:432
VDF_API bool IsScheduled(const VdfNode &node) const
Returns whether this schedule includes node in any way.
size_t GetNumKeepTasks() const
Returns the total number of keep tasks in the schedule.
Definition schedule.h:396
TaskIdRange GetComputeTaskIds(const VdfScheduleInputDependency &input) const
Returns an iterable range of task indices given an input dependency.
Definition schedule.h:414
VDF_API void DeduplicateInputs()
Consolidates scheduled input entries added by AddInput.
VDF_API void ForEachScheduledOutput(const VdfNode &node, const VdfScheduledOutputCallback &callback) const
Loops over each scheduled output of node and calls callback with the output and request mask in an ef...
VDF_API void SetRequest(const VdfRequest &request)
Sets the request that was used to make up this schedule.
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.
Definition schedule.h:515
const VdfRequest & GetRequest() const
Returns the request for this schedule.
Definition schedule.h:497
VDF_API const VdfMask & GetKeepMask(const OutputId &outputId) const
Returns the keep mask associated with the given OutputId.
VDF_API VdfScheduleInputDependencyUniqueIndex GetUniqueIndex(const OutputId outputId) const
Returns the unique index assigned to the output.
VDF_API void SetRequestMask(const OutputId &outputId, const VdfMask &mask)
Registers a request mask for the output indicated by outputId.
VDF_API void AddInput(const VdfConnection &connection, const VdfMask &mask)
Adds the input targeted by the given connection to the schedule.
VDF_API const VdfOutput * GetPassToOutput(const OutputId &outputId) const
Returns the "pass to" output associated with the given OutputId.
std::vector< VdfScheduleNode > ScheduleNodeVector
The type for the vector of schedule nodes in the schedule.
Definition schedule.h:71
const TaskIdRange GetComputeTaskIds(const VdfNode &node) const
Returns a range of ids describing compute tasks associated with the given node.
Definition schedule.h:403
VDF_API void SetKeepMask(const OutputId &outputId, const VdfMask &mask)
Registers a keep mask for the output indicated by outputId.
IteratorRange< Vdf_CountingIterator< VdfScheduleTaskId > > TaskIdRange
An iterable range of task ids.
Definition schedule.h:75
const VdfScheduleInputsTask & GetInputsTask(const VdfScheduleTaskIndex index) const
Returns the inputs task associated with the given task index.
Definition schedule.h:440
VDF_API void GetRequestAndAffectsMask(const OutputId &outputId, const VdfMask **requestMask, const VdfMask **affectsMask) const
Returns pointers to the request and affects masks simultaneously, saving on the overhead of making tw...
const VdfMask & GetRequestMask(const VdfScheduleTaskIndex invocationIndex) const
Returns the request mask for the given node invocation.
Definition schedule.h:295
VDF_API const VdfNode * GetNode(const OutputId &outputId) const
Returns the VdfNode that owns the VdfOutput associated with the given outputId.
VdfSchedule(const VdfSchedule &)=delete
Noncopyable.
const TfBits & GetScheduledNodeBits() const
Returns a set of bits where each set bit's index corresponds to the node index of a node in this sche...
Definition schedule.h:522
VDF_API const VdfOutput * GetOutputToClear(const VdfNode &node) const
Returns the output whose temporary buffer can be immediately deallocated after node has finished exec...
void GetRequestAndAffectsMask(const VdfScheduleTaskIndex invocationIndex, const VdfMask **requestMask, const VdfMask **affectsMask) const
Returns pointers to the request and affects masks for the given node invocation index.
Definition schedule.h:314
bool IsValid() const
Returns whether or not this schedule is valid and can be used for execution.
Definition schedule.h:173
ScheduleNodeVector & GetScheduleNodeVector()
Returns the vector of schedule nodes in this schedule.
Definition schedule.h:504
size_t GetNumInputsTasks() const
Returns the total number of inputs tasks in the schedule.
Definition schedule.h:384
VDF_API void Clear()
Clears the schedule.
bool IsSmallSchedule() const
Returns whether this schedule is small enough to avoid overhead incurred by the _nodesToIndexMap mapp...
Definition schedule.h:488
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.
size_t GetNumPrepTasks() const
Returns the total number of prep tasks in the schedule.
Definition schedule.h:390
VDF_API void SetFromBufferOutput(const OutputId &outputId, const VdfOutput *output)
Registers a "from buffer" for the output indicated by outputId.
InputDependencyRange GetOptionalInputDependencies(const VdfScheduleInputsTask &task) const
Returns an iterable range of optional (i.e.
Definition schedule.h:459
size_t GetNumComputeTasks() const
Returns the total number of compute tasks in the schedule.
Definition schedule.h:378
bool HasSMBL() const
Returns true if this schedule participates in sparse mung buffer locking.
Definition schedule.h:354
VDF_API void SetOutputToClear(const VdfNode &node, const VdfOutput *outputToClear)
Registers an output whose temporary buffer can be eagerly cleared as soon as node has finished execut...
Used to make a VdfSchedule.
Definition scheduler.h:41
std::function< void(const VdfOutput *, const VdfMask &)> VdfScheduledOutputCallback
Function type to be used with ForEachScheduledOutput().
Definition types.h:86
std::vector< T, Vdf_DefaultInitAllocator< T > > Vdf_DefaultInitVector
A std::vector which on resize performs default initialization instead of value initialization.
Definition types.h:122
#define TF_DEV_AXIOM(cond)
The same as TF_AXIOM, but compiled only in dev builds.
Definition diagnostic.h:206
uint32_t VdfScheduleInputDependencyUniqueIndex
A sequential index assigned to the unique output and mask combination of a VdfScheduleInputDependency...
bool VdfScheduleTaskIsInvalid(uint32_t task)
Returns true if the given task index or id is invalid.
uint32_t VdfScheduleTaskIndex
Type describing a task index.
A VdfScheduleComputeTask represents a unit of computation for the parallel evaluation engine.
Describes a single input dependency, i.e.
Structure describing an additional task used to run prereqs and reads concurrently with read/write in...