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