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 
129 struct TaskData
130 {
131  ~TaskData();
132 
134 
135  /** Collect all of the prims from the numerous threads.
136  The resulting prims are sorted (for determinism) */
138 
141 };
142 
143 
144 /** Task for traversing a prim tree in parallel.
145 
146  See DefaultImageablePrimVisitorT<> for an example of the structure
147  expected for visitors. */
148 template <class Visitor>
150 {
152  const UsdPrim& prim, exint idx, UsdTimeCode time,
153  GusdPurposeSet purposes,
154  TaskData& data, const Visitor& visitor, bool skipPrim)
155  : _taskgroup(taskgroup), _prim(prim), _idx(idx), _time(time),
156  _purposes(purposes), _data(data),
157  _visitor(visitor), _skipPrim(skipPrim) {}
158 
159  void operator()() const;
160 
161 private:
162  UT_TaskGroup& _taskgroup;
163  UsdPrim _prim;
164  exint _idx;
165  UsdTimeCode _time;
166  GusdPurposeSet _purposes;
167  TaskData& _data;
168  // _visitor is ok to be modified in operator() because we make copies of it
169  // at each step. Unfortunately, functors passed into UT_TaskGroup must be
170  // const so we mark it as mutable.
171  mutable Visitor _visitor;
172  bool _skipPrim;
173 };
174 
175 
176 template <class Visitor>
177 void
179 {
180  UT_ASSERT_P(_prim);
181 
182  if(!_skipPrim) {
183 
185  if(ARCH_UNLIKELY(_visitor.AcceptPrim(_prim, _time, _purposes, ctl))) {
186  /* Matched. Add it to the thread-specific list.*/
187  auto*& threadData = _data.threadData.get();
188  if(!threadData)
189  threadData = new TaskThreadData;
190  threadData->prims.append(
191  GusdUSD_Traverse::PrimIndexPair(_prim, _idx));
192  }
193  if(ARCH_UNLIKELY(!ctl.GetVisitChildren())) {
194  return;
195  }
196  }
197 
198  auto predicate = _visitor.TraversalPredicate(_prim.IsAbstract());
199  for (const auto& child : _prim.GetFilteredChildren(predicate)) {
200  _taskgroup.run(TraverseTaskT(
201  _taskgroup, child, _idx, _time, _purposes, _data, _visitor,
202  /*skip prim*/ false));
203  }
204 }
205 
206 
207 template <class Visitor>
208 bool
210  UsdTimeCode time,
211  GusdPurposeSet purposes,
212  UT_Array<UsdPrim>& prims,
213  const Visitor& visitor,
214  bool skipRoot)
215 {
216  TaskData data;
217  bool skipPrim = skipRoot || root.GetPath() == SdfPath::AbsoluteRootPath();
218  UT_TaskGroup tg;
219  tg.runAndWait(TraverseTaskT<Visitor>(tg, root, -1, time, purposes,
220  data, visitor, skipPrim));
221 
222  if(UTgetInterrupt()->opInterrupt())
223  return false;
224 
225  return data.GatherPrimsFromThreads(prims);
226 }
227 
228 
229 template <class Visitor>
230 struct RunTasksT
231 {
233  const GusdDefaultArray<UsdTimeCode>& times,
234  const GusdDefaultArray<GusdPurposeSet>& purposes,
235  const Visitor& visitor, TaskData& data, bool skipRoot)
236  : _roots(roots), _times(times), _purposes(purposes),
237  _visitor(visitor), _data(data), _skipRoot(skipRoot) {}
238 
240  {
241  auto* boss = GusdUTverify_ptr(UTgetInterrupt());
242 
243  for(std::size_t i = r.begin(); i < r.end(); ++i)
244  {
245  if(boss->opInterrupt())
246  return;
247 
248  if(const UsdPrim& prim = _roots(i)) {
249  bool skipPrim = _skipRoot ||
250  prim.GetPath() == SdfPath::AbsoluteRootPath();
251 
252  UT_TaskGroup tg;
254  tg, prim, i, _times(i), _purposes(i), _data,
255  _visitor, skipPrim));
256  }
257  }
258  }
259 
260 private:
261  const UT_Array<UsdPrim>& _roots;
262  const GusdDefaultArray<UsdTimeCode>& _times;
263  const GusdDefaultArray<GusdPurposeSet>& _purposes;
264  const Visitor& _visitor;
265  TaskData& _data;
266  const bool _skipRoot;
267 };
268 
269 
270 
271 
272 template <class Visitor>
273 bool
275  const GusdDefaultArray<UsdTimeCode>& times,
276  const GusdDefaultArray<GusdPurposeSet>& purposes,
278  const Visitor& visitor,
279  bool skipRoot)
280 {
281  TaskData data;
283  RunTasksT<Visitor>(roots, times, purposes,
284  visitor, data, skipRoot));
285  if(UTgetInterrupt()->opInterrupt())
286  return false;
287 
288  return data.GatherPrimsFromThreads(prims);
289 }
290 
291 
292 } /*namespace GusdUSD_ThreadedTraverse*/
293 
295 
296 #endif /*_GUSD_THREADEDTRAVERSE_H_*/
static SDF_API const SdfPath & AbsoluteRootPath()
bool Get(T *value, UsdTimeCode time=UsdTimeCode::Default()) const
Definition: attribute.h:431
GT_API const UT_StringHolder time
int64 exint
Definition: SYS_Types.h:125
Usd_PrimFlagsPredicate TraversalPredicate(bool allow_abstract) const
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=false)
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:479
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:113
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:170
Methods for USD scene traversal.
std::pair< UsdPrim, exint > PrimIndexPair
Definition: USD_Traverse.h:60
UT_ThreadSpecificValue< TaskThreadData * > TaskThreadDataTLS
Definition: prim.h:132
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
Definition: primFlags.h:578
exint append()
Definition: UT_Array.h:95
bool GatherPrimsFromThreads(UT_Array< UsdPrim > &prims)
GLboolean * data
Definition: glcorearb.h:130
SdfPath GetPath() const
Definition: object.h:194
UT_Array< GusdUSD_Traverse::PrimIndexPair > prims
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1375
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)
RunTasksT(const UT_Array< UsdPrim > &roots, const GusdDefaultArray< UsdTimeCode > &times, const GusdDefaultArray< GusdPurposeSet > &purposes, const Visitor &visitor, TaskData &data, bool skipRoot)
GLboolean r
Definition: glcorearb.h:1221
GusdPurposeSet
Definition: purpose.h:39
Declare prior to use.
bool AcceptPrim(const UsdPrim &prim, UsdTimeCode time, GusdPurposeSet purposes, GusdUSD_TraverseControl &ctl) const