HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
task.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 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_IMAGING_HD_TASK_H
8 #define PXR_IMAGING_HD_TASK_H
9 
10 #include "pxr/pxr.h"
11 #include "pxr/imaging/hd/api.h"
12 #include "pxr/imaging/hd/driver.h"
13 #include "pxr/imaging/hd/version.h"
14 
16 
17 #include "pxr/usd/sdf/path.h"
18 #include "pxr/base/tf/hashmap.h"
19 #include "pxr/base/vt/value.h"
20 #include "pxr/base/vt/dictionary.h"
21 
22 #include <memory>
23 #include <vector>
24 #include <unordered_map>
25 
27 
28 
29 using HdTaskSharedPtr = std::shared_ptr<class HdTask>;
30 using HdTaskSharedPtrVector = std::vector<HdTaskSharedPtr>;
31 
32 // We want to use token as a key not std::string, so use an unordered_map over
33 // VtDictionary
34 using HdTaskContext =
35  std::unordered_map<TfToken, VtValue, TfToken::HashFunctor>;
36 
37 /// \class HdTask
38 ///
39 /// HdTask represents a unit of work to perform during a Hydra render.
40 /// Developers can subclass HdTask to prepare resources, run 3d renderpasses,
41 /// run 2d renderpasses such as compositing or color correction, or coordinate
42 /// integration with the application or other renderers.
43 class HdTask {
44 public:
45  /// Construct a new task.
46  /// If the task is going to be added to the render index, id
47  /// should be an absolute scene path.
48  /// If the task isn't going to be added to the render index
49  /// an empty path should be used for id.
50  HD_API
51  HdTask(SdfPath const& id);
52 
53  HD_API
54  virtual ~HdTask();
55 
56  /// Sync Phase: Obtain task state from Scene delegate based on
57  /// change processing.
58  ///
59  /// This function might only be called if dirtyBits is not 0,
60  /// so isn't guaranteed to be called every time HdEngine::Execute() is run
61  /// with this task.
62  ///
63  /// However, this is the only time when the task should communicate with
64  /// with the scene delegate responsible for the task and should be
65  /// used to pull all changed data. As outside the Sync phase, the scene
66  /// delegate may not have the data available.
67  ///
68  /// Tasks maybe synced in parallel and out of order.
69  ///
70  /// The ctx parameter is present for legacy reason and shouldn't be used
71  /// once the task has moved to using the 3-phase mechanism.
72  ///
73  /// After a task has been synced, it is expected that it produces a
74  /// collection identifying the prims that are important to the task. This
75  /// collection is used to filter the prims in the scene so only the
76  /// Relevant prims get synced.
77  ///
78  /// Note about inter-prim dependencies:
79  /// Quite often tasks need to access other prims, such as a camera prim
80  /// for example. These other prims have not been synced yet when sync is
81  /// called. Therefore, it is not recommended to access these prims during
82  /// the sync phase. Instead a task should store the path to the prim
83  /// to be resolved to an actual prim during the "prepare" phase.
84 
85  virtual void Sync(HdSceneDelegate* delegate,
86  HdTaskContext* ctx,
87  HdDirtyBits* dirtyBits) = 0;
88 
89  /// Prepare Phase: Resolve bindings and manage resources.
90  ///
91  /// The Prepare phase happens before the Data Commit phase.
92  /// All tasks in the task list get called for every execute.
93  /// At this time all Tasks and other prims have completed the phase synced.
94  ///
95  /// This is an opportunity for the task to pull data from other prims
96  /// (such as a camera prim) by querying the render index.
97  ///
98  /// The task can also use the phase to create, register and update temporary
99  /// resources with the resource registry or other render delegate
100  /// specific mechanism.
101  ///
102  /// Tasks are always "Prepared" in execution order.
103  ///
104  /// Inter-task communication is achievable via the task context.
105  /// The same task context is used for the prepare and execution phases.
106  /// Data in the task context isn't guaranteed to persist across calls
107  /// to HdEngine::Execute().
108  virtual void Prepare(HdTaskContext* ctx,
109  HdRenderIndex* renderIndex) = 0;
110 
111  /// Execute Phase: Runs the task.
112  ///
113  /// The execution phase should trigger render delegate processing,
114  /// such as issuing draw commands.
115  ///
116  /// Task execution is non-parallel and ordered.
117  ///
118  /// The task context is the same as used by the prepare step and is used
119  /// for inter-task communication.
120  virtual void Execute(HdTaskContext* ctx) = 0;
121 
122  /// Render Tag Gather.
123  ///
124  /// Is called during the Sync phase after the task has been sync'ed.
125  ///
126  /// The task should return the render tags it wants to be appended to the
127  /// active set.
128  ///
129  /// Hydra prims are marked up with a render tag and only prims
130  /// marked with the render tags in the current active set are Sync'ed.
131  ///
132  /// Hydra's core will combine the sets from each task and deduplicate the
133  /// result. So tasks don't need to co-ordinate with each other to
134  /// optimize the set.
135  ///
136  /// For those tasks that use HdRenderPass, this set is passed
137  /// to HdRenderPass's Execute method.
138  ///
139  /// The default implementation returns an empty set
140  HD_API
141  virtual const TfTokenVector &GetRenderTags() const;
142 
143  SdfPath const& GetId() const { return _id; }
144 
145  /// Returns the minimal set of dirty bits to place in the
146  /// change tracker for use in the first sync of this prim.
147  /// Typically this would be all dirty bits.
148  HD_API
149  virtual HdDirtyBits GetInitialDirtyBitsMask() const;
150 
151 
152 protected:
153  /// Check if the shared context contains a value for the given id.
154  HD_API
155  static bool _HasTaskContextData(HdTaskContext const* ctx,
156  TfToken const& id);
157 
158  /// Extracts a typed value out of the task context at the given id.
159  /// If the id is missing or of the wrong type, the code will
160  /// throw a verify error, return false and outValue will be unmodified.
161  /// in case of success, the return value is true and the value is
162  /// copied into outValue.
163  ///
164  /// outValue must not be null.
165  template <class T>
166  static bool _GetTaskContextData(HdTaskContext const* ctx,
167  TfToken const& id,
168  T* outValue);
169 
170  /// Extracts a typed value out of the task context at the given id.
171  /// If the id is missing or of the wrong type, the code will
172  /// throw a verify error, return false and outValue will be unmodified.
173  /// in case of success, the return value is true and the value is
174  /// copied into outValue.
175  ///
176  /// outValue must not be null.
177  template <class T>
178  bool _GetTaskParams(HdSceneDelegate* delegate,
179  T* outValue);
180 
181  HD_API
183 
184  /// Extract an object from a HdDriver inside the task context.
185  /// Returns nullptr if driver was not found.
186  template <class T>
187  static T _GetDriver(
188  HdTaskContext const* ctx,
189  TfToken const& driverName);
190 
191 private:
192  SdfPath _id;
193 
194  HdTask() = delete;
195  HdTask(const HdTask &) = delete;
196  HdTask &operator =(const HdTask &) = delete;
197 };
198 
199 // Inline template body
200 template <class T>
201 bool
203  TfToken const& id,
204  T* outValue)
205 {
206  TF_DEV_AXIOM(outValue != nullptr);
207 
208  if (!ctx) {
209  return false;
210  }
211 
212  HdTaskContext::const_iterator valueIt = ctx->find(id);
213  if (valueIt == ctx->cend()) {
214  TF_CODING_ERROR("Token %s missing from task context", id.GetText());
215  return false;
216  }
217 
218  const VtValue &valueVt = (valueIt->second);
219  if (!valueVt.IsHolding<T>()) {
220  TF_CODING_ERROR("Token %s in task context is of mismatched type",
221  id.GetText());
222  return false;
223  }
224 
225  *outValue = valueVt.UncheckedGet<T>();
226 
227  return true;
228 }
229 
230 template <class T>
231 bool
233  T* outValue)
234 {
235  TF_DEV_AXIOM(outValue != nullptr);
236 
237  SdfPath const& taskId = GetId();
238 
239  VtValue valueVt = delegate->Get(taskId, HdTokens->params);
240  if (!valueVt.IsHolding<T>()) {
241  TF_CODING_ERROR("Task params for %s is of unexpected type",
242  taskId.GetText());
243  return false;
244  }
245 
246  *outValue = valueVt.UncheckedGet<T>();
247 
248  return true;
249 }
250 
251 template <class T>
252 T
254  HdTaskContext const* ctx,
255  TfToken const& driverName)
256 {
257  auto it = ctx->find(HdTokens->drivers);
258  if (it != ctx->end()) {
259  VtValue const& value = it->second;
260  if (value.IsHolding<HdDriverVector>()) {
261  HdDriverVector const& drivers= value.UncheckedGet<HdDriverVector>();
262  for (HdDriver* hdDriver : drivers) {
263  if (hdDriver->name == driverName) {
264  if (hdDriver->driver.IsHolding<T>()) {
265  return hdDriver->driver.UncheckedGet<T>();
266  }
267  }
268  }
269  }
270  }
271 
272  return nullptr;
273 }
274 
276 
277 #endif // PXR_IMAGING_HD_TASK_H
SDF_API const char * GetText() const
SdfPath const & GetId() const
Definition: task.h:143
T const & UncheckedGet() const &
Definition: value.h:1104
uint32_t HdDirtyBits
Definition: types.h:143
GLsizei const GLfloat * value
Definition: glcorearb.h:824
#define TF_CODING_ERROR
#define HD_API
Definition: api.h:23
std::vector< HdTaskSharedPtr > HdTaskSharedPtrVector
Definition: renderIndex.h:58
static T _GetDriver(HdTaskContext const *ctx, TfToken const &driverName)
Definition: task.h:253
virtual HD_API ~HdTask()
std::shared_ptr< class HdTask > HdTaskSharedPtr
#define TF_DEV_AXIOM(cond)
Definition: token.h:70
std::vector< HdDriver * > HdDriverVector
virtual HD_API HdDirtyBits GetInitialDirtyBitsMask() const
std::vector< TfToken > TfTokenVector
Convenience types.
Definition: token.h:440
virtual void Prepare(HdTaskContext *ctx, HdRenderIndex *renderIndex)=0
virtual void Sync(HdSceneDelegate *delegate, HdTaskContext *ctx, HdDirtyBits *dirtyBits)=0
Definition: task.h:43
Definition: path.h:273
std::unordered_map< TfToken, VtValue, TfToken::HashFunctor > HdTaskContext
Definition: renderIndex.h:61
HD_API TfTokenVector _GetTaskRenderTags(HdSceneDelegate *delegate)
virtual HD_API const TfTokenVector & GetRenderTags() const
virtual void Execute(HdTaskContext *ctx)=0
virtual HD_API VtValue Get(SdfPath const &id, TfToken const &key)
Returns a named value.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
bool IsHolding() const
Definition: value.h:1064
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
bool _GetTaskParams(HdSceneDelegate *delegate, T *outValue)
Definition: task.h:232
static HD_API bool _HasTaskContextData(HdTaskContext const *ctx, TfToken const &id)
Check if the shared context contains a value for the given id.
Definition: value.h:146
static bool _GetTaskContextData(HdTaskContext const *ctx, TfToken const &id, T *outValue)
Definition: task.h:202