HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
USD_ThreadedTraverse.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 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 _GUSD_THREADEDTRAVERSE_H_
25 #define _GUSD_THREADEDTRAVERSE_H_
26 
27 
28 #include <UT/UT_Array.h>
29 #include <UT/UT_Interrupt.h>
30 #include <UT/UT_ParallelUtil.h>
31 #include <UT/UT_TaskGroup.h>
33 #include <SYS/SYS_Deprecated.h>
34 
35 #include "gusd/UT_Assert.h"
36 #include "gusd/USD_Traverse.h"
37 #include "gusd/USD_Utils.h"
38 
39 #include "pxr/pxr.h"
40 #include "pxr/base/arch/hints.h"
41 #include "pxr/usd/usd/prim.h"
43 
45 
46 namespace GusdUSD_ThreadedTraverse {
47 
48 
49 template <class Visitor>
50 bool ParallelFindPrims(const UsdPrim& root,
52  GusdPurposeSet purposes,
53  UT_Array<UsdPrim>& prims,
54  const Visitor& visitor,
55  bool skipRoot=true);
56 
57 template <class Visitor>
58 bool ParallelFindPrims(const UT_Array<UsdPrim>& roots,
59  const GusdDefaultArray<UsdTimeCode>& times,
60  const GusdDefaultArray<GusdPurposeSet>& purposes,
62  const Visitor& visitor,
63  bool skipRoot=true);
64 
65 
66 /** Visitor for default-imageable prims.
67  This takes @a Visitor as a child visitor to exec on each
68  default-imageable prim.*/
69 template <class Visitor, bool Recursive=false>
71 {
72  bool AcceptPrim(const UsdPrim& prim,
73  UsdTimeCode time,
74  GusdPurposeSet purposes,
75  GusdUSD_TraverseControl& ctl) const;
76 
77  Usd_PrimFlagsPredicate TraversalPredicate(bool allow_abstract) const
78  {
79  return allow_abstract
81  UsdPrimIsActive &&
82  UsdPrimIsDefined &&
83  UsdPrimIsLoaded)
85  UsdPrimIsActive &&
86  UsdPrimIsDefined &&
87  UsdPrimIsLoaded &&
88  !UsdPrimIsAbstract);
89  }
90 };
91 
92 
93 template <class Visitor, bool Recursive>
94 bool
96  const UsdPrim& prim,
97  UsdTimeCode time,
98  GusdPurposeSet purposes,
99  GusdUSD_TraverseControl& ctl) const
100 {
101  UsdGeomImageable ip(prim);
102  if(ip) {
103  TfToken purpose;
104  ip.GetPurposeAttr().Get(&purpose);
105  if( GusdPurposeInSet( purpose, purposes )) {
106  if(ARCH_UNLIKELY(Visitor()(prim, time, ctl))) {
107  if(!Recursive)
108  ctl.PruneChildren();
109  return true;
110  }
111  } else {
112  ctl.PruneChildren();
113  }
114  } else {
115  ctl.PruneChildren();
116  }
117  return false;
118 }
119 
120 
122 {
124 };
125 
127 
128 
130 {
131  TaskData() = default;
132  ~TaskData();
133 
134  TaskData(const TaskData &) = delete;
135  TaskData &operator=(const TaskData &) = delete;
136 
138 
139  /** Collect all of the prims from the numerous threads.
140  The resulting prims are sorted (for determinism) */
141  bool GatherPrimsFromThreads(UT_Array<UsdPrim>& prims);
142 
143  bool GatherPrimsFromThreads(
145 };
146 
147 
148 /** Task for traversing a prim tree in parallel.
149 
150  See DefaultImageablePrimVisitorT<> for an example of the structure
151  expected for visitors. */
152 template <class Visitor>
154 {
156  const UsdPrim& prim, exint idx, UsdTimeCode time,
157  GusdPurposeSet purposes,
158  TaskData& data, const Visitor& visitor, bool skipPrim)
159  : _taskgroup(taskgroup), _prim(prim), _idx(idx), _time(time),
160  _purposes(purposes), _data(data),
161  _visitor(visitor), _skipPrim(skipPrim) {}
162 
163  void operator()() const;
164 
165 private:
166  UT_TaskGroup& _taskgroup;
167  UsdPrim _prim;
168  exint _idx;
169  UsdTimeCode _time;
170  GusdPurposeSet _purposes;
171  TaskData& _data;
172  // _visitor is ok to be modified in operator() because we make copies of it
173  // at each step. Unfortunately, functors passed into UT_TaskGroup must be
174  // const so we mark it as mutable.
175  mutable Visitor _visitor;
176  bool _skipPrim;
177 };
178 
179 
180 template <class Visitor>
181 void
183 {
184  UT_ASSERT_P(_prim);
185 
186  if(!_skipPrim) {
187 
189  if(ARCH_UNLIKELY(_visitor.AcceptPrim(_prim, _time, _purposes, ctl))) {
190  /* Matched. Add it to the thread-specific list.*/
191  auto*& threadData = _data.threadData.get();
192  if(!threadData)
193  threadData = new TaskThreadData;
194  threadData->prims.append(
195  GusdUSD_Traverse::PrimIndexPair(_prim, _idx));
196  }
197  if(ARCH_UNLIKELY(!ctl.GetVisitChildren())) {
198  return;
199  }
200  }
201 
202  auto predicate = _visitor.TraversalPredicate(_prim.IsAbstract());
203  for (const auto& child : _prim.GetFilteredChildren(predicate)) {
204  _taskgroup.run(TraverseTaskT(
205  _taskgroup, child, _idx, _time, _purposes, _data, _visitor,
206  /*skip prim*/ false));
207  }
208 }
209 
210 
211 template <class Visitor>
212 bool
214  UsdTimeCode time,
215  GusdPurposeSet purposes,
216  UT_Array<UsdPrim>& prims,
217  const Visitor& visitor,
218  bool skipRoot)
219 {
220  TaskData data;
221  bool skipPrim = skipRoot || root.GetPath() == SdfPath::AbsoluteRootPath();
222  UT_TaskGroup tg;
223  tg.runAndWait(TraverseTaskT<Visitor>(tg, root, -1, time, purposes,
224  data, visitor, skipPrim));
225 
226  if(UTgetInterrupt()->opInterrupt())
227  return false;
228 
229  return data.GatherPrimsFromThreads(prims);
230 }
231 
232 
233 template <class Visitor>
234 struct RunTasksT
235 {
237  const GusdDefaultArray<UsdTimeCode>& times,
238  const GusdDefaultArray<GusdPurposeSet>& purposes,
239  const Visitor& visitor, TaskData& data, bool skipRoot)
240  : _roots(roots), _times(times), _purposes(purposes),
241  _visitor(visitor), _data(data), _skipRoot(skipRoot) {}
242 
244  {
245  auto* boss = GusdUTverify_ptr(UTgetInterrupt());
246 
247  for(std::size_t i = r.begin(); i < r.end(); ++i)
248  {
249  if(boss->opInterrupt())
250  return;
251 
252  if(const UsdPrim& prim = _roots(i)) {
253  bool skipPrim = _skipRoot ||
254  prim.GetPath() == SdfPath::AbsoluteRootPath();
255 
256  UT_TaskGroup tg;
258  tg, prim, i, _times(i), _purposes(i), _data,
259  _visitor, skipPrim));
260  }
261  }
262  }
263 
264 private:
265  const UT_Array<UsdPrim>& _roots;
266  const GusdDefaultArray<UsdTimeCode>& _times;
267  const GusdDefaultArray<GusdPurposeSet>& _purposes;
268  const Visitor& _visitor;
269  TaskData& _data;
270  const bool _skipRoot;
271 };
272 
273 
274 
275 
276 template <class Visitor>
277 bool
279  const GusdDefaultArray<UsdTimeCode>& times,
280  const GusdDefaultArray<GusdPurposeSet>& purposes,
282  const Visitor& visitor,
283  bool skipRoot)
284 {
285  TaskData data;
287  RunTasksT<Visitor>(roots, times, purposes,
288  visitor, data, skipRoot));
289  if(UTgetInterrupt()->opInterrupt())
290  return false;
291 
292  return data.GatherPrimsFromThreads(prims);
293 }
294 
295 
296 } /*namespace GusdUSD_ThreadedTraverse*/
297 
299 
300 #endif /*_GUSD_THREADEDTRAVERSE_H_*/
void UTparallelFor(const Range &range, const Body &body, const int subscribe_ratio=2, const int min_grain_size=1, const bool force_use_task_scope=true)
static SDF_API const SdfPath & AbsoluteRootPath()
bool Get(T *value, UsdTimeCode time=UsdTimeCode::Default()) const
Definition: attribute.h:436
GLboolean * data
Definition: glcorearb.h:131
GT_API const UT_StringHolder time
int64 exint
Definition: SYS_Types.h:125
Usd_PrimFlagsPredicate TraversalPredicate(bool allow_abstract) const
bool GetVisitChildren() const
Definition: USD_Traverse.h:139
PXR_NAMESPACE_OPEN_SCOPE T * GusdUTverify_ptr(T *ptr)
Definition: UT_Assert.h:41
exint size() const
Definition: UT_Array.h:646
void operator()(const UT_BlockedRange< std::size_t > &r) const
int opInterrupt(int percent=-1)
#define ARCH_UNLIKELY(x)
Definition: hints.h:47
void runAndWait(const F &f)
Definition: UT_TaskGroup.h:115
Definition: token.h:87
USDGEOM_API UsdAttribute GetPurposeAttr() const
TraverseTaskT(UT_TaskGroup &taskgroup, const UsdPrim &prim, exint idx, UsdTimeCode time, GusdPurposeSet purposes, TaskData &data, const Visitor &visitor, bool skipPrim)
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
Methods for USD scene traversal.
std::pair< UsdPrim, exint > PrimIndexPair
Definition: USD_Traverse.h:60
UT_ThreadSpecificValue< TaskThreadData * > TaskThreadDataTLS
Definition: prim.h:133
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
Definition: primFlags.h:577
exint append()
Definition: UT_Array.h:142
bool GatherPrimsFromThreads(UT_Array< UsdPrim > &prims)
SdfPath GetPath() const
Definition: object.h:203
UT_Array< GusdUSD_Traverse::PrimIndexPair > prims
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
LeafData & operator=(const LeafData &)=delete
UT_API UT_Interrupt * UTgetInterrupt()
Obtain global UT_Interrupt singleton.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
GUSD_API bool GusdPurposeInSet(const TfToken &name, GusdPurposeSet set)
Definition: purpose.h:82
bool ParallelFindPrims(const UsdPrim &root, UsdTimeCode time, GusdPurposeSet purposes, UT_Array< UsdPrim > &prims, const Visitor &visitor, bool skipRoot=true)
#define GUSD_API
Definition: api.h:40
GLboolean r
Definition: glcorearb.h:1222
RunTasksT(const UT_Array< UsdPrim > &roots, const GusdDefaultArray< UsdTimeCode > &times, const GusdDefaultArray< GusdPurposeSet > &purposes, const Visitor &visitor, TaskData &data, bool skipRoot)
GusdPurposeSet
Definition: purpose.h:39
Declare prior to use.
bool AcceptPrim(const UsdPrim &prim, UsdTimeCode time, GusdPurposeSet purposes, GusdUSD_TraverseControl &ctl) const
Definition: format.h:895