24 #ifndef _GUSD_THREADEDTRAVERSE_H_
25 #define _GUSD_THREADEDTRAVERSE_H_
28 #include <UT/UT_Array.h>
29 #include <UT/UT_Interrupt.h>
30 #include <UT/UT_ParallelUtil.h>
31 #include <UT/UT_Task.h>
32 #include <UT/UT_ThreadSpecificValue.h>
34 #include "gusd/UT_Assert.h"
36 #include "gusd/USD_Utils.h"
39 #include "pxr/base/arch/hints.h"
40 #include "pxr/usd/usd/prim.h"
41 #include "pxr/usd/usdGeom/imageable.h"
43 PXR_NAMESPACE_OPEN_SCOPE
45 namespace GusdUSD_ThreadedTraverse {
48 template <
class Visitor>
49 bool ParallelFindPrims(
const UsdPrim& root,
51 GusdPurposeSet purposes,
52 UT_Array<UsdPrim>& prims,
53 const Visitor& visitor,
56 template <
class Visitor>
57 bool ParallelFindPrims(
const UT_Array<UsdPrim>& roots,
60 UT_Array<GusdUSD_Traverse::PrimIndexPair>& prims,
61 const Visitor& visitor,
68 template <
class Visitor,
bool Recursive=false>
71 bool AcceptPrim(
const UsdPrim& prim,
73 GusdPurposeSet purposes,
76 Usd_PrimFlagsPredicate TraversalPredicate()
const
82 template <
class Visitor,
bool Recursive>
87 GusdPurposeSet purposes,
93 ip.GetPurposeAttr().Get(&purpose);
94 if( GusdPurposeInSet( purpose, purposes )) {
95 if(ARCH_UNLIKELY(Visitor()(prim, time, ctl))) {
110 struct TaskThreadData
112 UT_Array<GusdUSD_Traverse::PrimIndexPair> prims;
115 typedef UT_ThreadSpecificValue<TaskThreadData*> TaskThreadDataTLS;
122 TaskThreadDataTLS threadData;
126 bool GatherPrimsFromThreads(UT_Array<UsdPrim>& prims);
128 bool GatherPrimsFromThreads(
129 UT_Array<GusdUSD_Traverse::PrimIndexPair>& prims);
137 template <
class Visitor>
141 GusdPurposeSet purposes,
142 TaskData& data,
const Visitor& visitor,
bool skipPrim)
143 : UT_Task(), _prim(prim), _idx(idx), _time(time),
144 _purposes(purposes), _data(data),
145 _visited(
false), _visitor(visitor), _skipPrim(skipPrim) {}
147 virtual UT_Task*
run();
153 GusdPurposeSet _purposes;
164 template <
class Visitor>
170 if(ARCH_UNLIKELY(_visited))
return NULL;
178 if(ARCH_UNLIKELY(_visitor.AcceptPrim(_prim, _time, _purposes, ctl))) {
180 auto*& threadData = _data.threadData.get();
182 threadData =
new TaskThreadData;
183 threadData->prims.append(
184 GusdUSD_Traverse::PrimIndexPair(_prim, _idx));
186 if(ARCH_UNLIKELY(!ctl.GetVisitChildren())) {
193 auto children = _prim.GetFilteredChildren(_visitor.TraversalPredicate());
194 for (
auto i = children.begin(); i != children.end(); ++i, ++count) {}
200 recycleAsContinuation();
202 const int last = count - 1;
204 for (
const auto& child :
205 _prim.GetFilteredChildren(_visitor.TraversalPredicate())) {
220 template <
class Visitor>
222 ParallelFindPrims(
const UsdPrim& root,
224 GusdPurposeSet purposes,
225 UT_Array<UsdPrim>& prims,
226 const Visitor& visitor,
232 *
new(UT_Task::allocate_root())
234 data, visitor, skipPrim);
235 UT_Task::spawnRootAndWait(task);
237 if(UTgetInterrupt()->opInterrupt())
240 return data.GatherPrimsFromThreads(prims);
244 template <
class Visitor>
247 RunTasksT(
const UT_Array<UsdPrim>& roots,
250 const Visitor& visitor, TaskData& data,
bool skipRoot)
251 : _roots(roots), _times(times), _purposes(purposes),
252 _visitor(visitor), _data(data), _skipRoot(skipRoot) {}
254 void operator()(
const UT_BlockedRange<std::size_t>& r)
const
256 auto* boss = GusdUTverify_ptr(UTgetInterrupt());
258 for(std::size_t i = r.begin(); i < r.end(); ++i)
260 if(boss->opInterrupt())
263 if(
const UsdPrim& prim = _roots(i)) {
264 bool skipPrim = _skipRoot ||
268 *
new(UT_Task::allocate_root())
269 TraverseTaskT<Visitor>(prim, i, _times(i),
272 UT_Task::spawnRootAndWait(task);
278 const UT_Array<UsdPrim>& _roots;
281 const Visitor& _visitor;
283 const bool _skipRoot;
289 template <
class Visitor>
291 ParallelFindPrims(
const UT_Array<UsdPrim>& roots,
294 UT_Array<GusdUSD_Traverse::PrimIndexPair>& prims,
295 const Visitor& visitor,
299 UTparallelFor(UT_BlockedRange<std::size_t>(0, roots.size()),
300 RunTasksT<Visitor>(roots, times, purposes,
301 visitor, data, skipRoot));
302 if(UTgetInterrupt()->opInterrupt())
305 return data.GatherPrimsFromThreads(prims);
311 PXR_NAMESPACE_CLOSE_SCOPE
SdfPath GetPath() const
Return the complete scene path to this object on its UsdStage, which may (UsdPrim) or may not (all ot...
unspecified UsdPrimIsAbstract
Tests UsdPrim::IsAbstract()
Visitor for default-imageable prims.
Helper to provide control over traversal through children.
unspecified UsdPrimIsActive
Tests UsdPrim::IsActive()
unspecified UsdPrimIsLoaded
Tests UsdPrim::IsLoaded()
Token for efficient comparison, assignment, and hashing of known strings.
Represent a time value, which may be either numeric, holding a double value, or a sentinel value UsdT...
unspecified UsdPrimIsDefined
Tests UsdPrim::IsDefined()
Methods for USD scene traversal.
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
Usd_PrimFlagsPredicate UsdTraverseInstanceProxies(Usd_PrimFlagsPredicate predicate)
This function is used to allow the prim traversal functions listed under Prim predicate flags to trav...
Task for traversing a prim tree in parallel.
static SDF_API const SdfPath & AbsoluteRootPath()
The absolute path representing the top of the namespace hierarchy.
virtual UT_Task * run()
XXX: This parallel recursion pattern follows the 'Recycling Parent as Continuation' pattern from TBB'...
Base class for all prims that may require rendering or visualization of some sort.