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