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_USD_PCP_CACHE_H
25 #define PXR_USD_PCP_CACHE_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/pcp/api.h"
29 #include "pxr/usd/pcp/dependency.h"
30 #include "pxr/usd/pcp/errors.h"
31 #include "pxr/usd/pcp/mapFunction.h"
32 #include "pxr/usd/pcp/primIndex.h"
33 #include "pxr/usd/pcp/propertyIndex.h"
34 #include "pxr/usd/sdf/declareHandles.h"
35 #include "pxr/usd/sdf/path.h"
36 #include "pxr/usd/sdf/pathTable.h"
37 
38 #include "pxr/usd/ar/ar.h"
39 #include "pxr/usd/ar/resolverContext.h"
40 #include "pxr/base/tf/declarePtrs.h"
41 #include "pxr/base/tf/functionRef.h"
42 #include "pxr/base/tf/hashset.h"
43 
44 #include <memory>
45 #include <string>
46 #include <unordered_set>
47 #include <vector>
48 
49 PXR_NAMESPACE_OPEN_SCOPE
50 
51 // Forward declarations:
52 class PcpChanges;
53 class PcpCacheChanges;
54 class Pcp_Dependencies;
55 class PcpLayerStackIdentifier;
56 class PcpLifeboat;
57 class PcpNodeRef;
58 class PcpMapFunction;
59 
60 TF_DECLARE_WEAK_AND_REF_PTRS(PcpLayerStack);
61 TF_DECLARE_WEAK_AND_REF_PTRS(Pcp_LayerStackRegistry);
62 SDF_DECLARE_HANDLES(SdfSpec);
63 
64 /// \class PcpCache
65 ///
66 /// PcpCache is the context required to make requests of the Pcp
67 /// composition algorithm and cache the results.
68 ///
69 /// Because the algorithms are recursive -- making a request typically
70 /// makes other internal requests to solve subproblems -- caching
71 /// subproblem results is required for reasonable performance, and
72 /// so this cache is the only entrypoint to the algorithms.
73 ///
74 /// There is a set of parameters that affect the composition results:
75 ///
76 /// \li variant fallbacks: per named variant set, an ordered list of
77 ///     fallback values to use when composing a prim that defines
78 ///     a variant set but does not specify a selection
79 /// \li payload inclusion set: an SdfPath set used to identify which
80 ///     prims should have their payloads included during composition;
81 ///     this is the basis for explicit control over the "working set"
82 ///     of composition
83 /// \li file format target: the file format target that Pcp will request
84 ///     when opening scene description layers
85 /// \li "USD mode" configures the Pcp composition algorithm to provide
86 ///     only a custom, lighter subset of the full feature set, as needed
87 ///     by the Universal Scene Description system
88 ///
89 /// There are a number of different computations that can be requested.
90 /// These include computing a layer stack from a PcpLayerStackIdentifier,
91 /// computing a prim index or prim stack, and computing a property index.
92 ///
93 class PcpCache
94 {
95     PcpCache(PcpCache const &) = delete;
96     PcpCache &operator=(PcpCache const &) = delete;
97 public:
98     /// Construct a PcpCache to compose results for the layer stack identified
99     /// by \a layerStackIdentifier.
100     ///
101     /// If \p fileFormatTarget is given, Pcp will specify \p fileFormatTarget
102     /// as the file format target when searching for or opening a layer.
103     ///
104     /// If \p usd is true, computation of prim indices and composition of prim
105     /// child names are performed without relocates, inherits, permissions,
106     /// symmetry, or payloads, and without populating the prim stack and
107     /// gathering its dependencies.
108     PCP_API
109     PcpCache(const PcpLayerStackIdentifier & layerStackIdentifier,
110              const std::string& fileFormatTarget = std::string(),
111              bool usd = false);
112     PCP_API ~PcpCache();
113 
114     /// \name Parameters
115     /// @{
116 
117     /// Get the identifier of the layerStack used for composition.
118     PCP_API
119     const PcpLayerStackIdentifier& GetLayerStackIdentifier() const;
120 
121     /// Get the layer stack for GetLayerStackIdentifier().  Note that
122     /// this will neither compute the layer stack nor report errors.
123     /// So if the layer stack has not been computed yet this will
124     /// return \c NULL.  Use ComputeLayerStack() if you need to
125     /// compute the layer stack if it hasn't been computed already
126     /// and/or get errors caused by computing the layer stack.
127     PCP_API
128     PcpLayerStackPtr GetLayerStack() const;
129 
130     /// Return true if the cache is configured in Usd mode.
131     PCP_API
132     bool IsUsd() const;
133 
134     /// Returns the file format target this cache is configured for.
135     PCP_API
136     const std::string& GetFileFormatTarget() const;
137 
138     /// Get the list of fallbacks to attempt to use when evaluating
139     /// variant sets that lack an authored selection.
140     PCP_API
141     PcpVariantFallbackMap GetVariantFallbacks() const;
142 
143     /// Set the list of fallbacks to attempt to use when evaluating
144     /// variant sets that lack an authored selection.
145     ///
146     /// If \p changes is not \c NULL then it's adjusted to reflect the
147     /// changes necessary to see the change in standin preferences,
148     /// otherwise those changes are applied immediately.
149     PCP_API
150     void SetVariantFallbacks( const PcpVariantFallbackMap & map,
151                               PcpChanges* changes = NULL );
152 
153     /// Return true if the payload is included for the given path.
154     PCP_API
155     bool IsPayloadIncluded(const SdfPath &path) const;
156 
157     /// Returns the payloads requested for inclusion.
158     using PayloadSet = std::unordered_set<SdfPath, SdfPath::Hash>;
159     PCP_API
160     PayloadSet const &GetIncludedPayloads() const;
161 
162     /// Request payloads to be included or excluded from composition.
163     /// \param pathsToInclude is a set of paths to add to the set for
164     ///        payload inclusion.
165     /// \param pathsToExclude is a set of paths to remove from the set for
166     ///        payload inclusion.
167     /// \param changes if not \c NULL, is adjusted to reflect the changes
168     ///        necessary to see the change in payloads;  otherwise those
169     ///        changes are applied immediately.
170     /// \note If a path is listed in both pathsToInclude and pathsToExclude,
171     /// it will be treated as an inclusion only.
172     ///
173     PCP_API
174     void RequestPayloads( const SdfPathSet & pathsToInclude,
175                           const SdfPathSet & pathsToExclude,
176                           PcpChanges* changes = NULL );
177 
178     /// Request layers to be muted or unmuted in this cache.  Muted layers
179     /// are ignored during composition and do not appear in any layer
180     /// stacks.  The root layer of this stage may not be muted; attempting
181     /// to do so will generate a coding error.  If the root layer of a
182     /// reference or payload layer stack is muted, the behavior is as if
183     /// the muted layer did not exist, which means a composition error will
184     /// be generated.
185     ///
186 #if AR_VERSION == 1
187     /// A canonical identifier for each layer in \p layersToMute will be
188     /// computed using ArResolver::ComputeRepositoryPath.  Any layer
189     /// encountered during composition with the same repository path will
190     /// be considered muted and ignored.  Relative paths will be assumed to
191     /// be relative to the cache's root layer.  Search paths are immediately
192     /// resolved and the result is used for computing the canonical path.
193 #else
194     /// A canonical identifier for each layer in \p layersToMute will be
195     /// computed using ArResolver::CreateIdentifier using the cache's root
196     /// layer as the anchoring asset. Any layer encountered during composition
197     /// with the same identifier will be considered muted and ignored.
198 #endif
199     ///
200     /// Note that muting a layer will cause this cache to release all
201     /// references to that layer.  If no other client is holding on to
202     /// references to that layer, it will be unloaded.  In this case, if
203     /// there are unsaved edits to the muted layer, those edits are lost.
204     /// Since anonymous layers are not serialized, muting an anonymous
205     /// layer will cause that layer and its contents to be lost in this
206     /// case.
207     ///
208     /// If \p changes is not \c nullptr, it is adjusted to reflect the
209     /// changes necessary to see the change in muted layers.  Otherwise,
210     /// those changes are applied immediately.
211     ///
212     /// \p newLayersMuted and \p newLayersUnmuted contains the pruned vector
213     /// of layers which are muted or unmuted by this call to RequestLayerMuting.
214     ///
215     PCP_API
216     void RequestLayerMuting(const std::vector<std::string>& layersToMute,
217                             const std::vector<std::string>& layersToUnmute,
218                             PcpChanges* changes = nullptr,
219                             std::vector<std::string>* newLayersMuted = nullptr,
220                             std::vector<std::string>* newLayersUnmuted =
221                                 nullptr);
222 
223     /// Returns the list of canonical identifiers for muted layers
224     /// in this cache.  See documentation on RequestLayerMuting for
225     /// more details.
226     PCP_API
227     const std::vector<std::string>& GetMutedLayers() const;
228 
229     /// Returns true if the layer specified by \p layerIdentifier is
230     /// muted in this cache, false otherwise.  If \p layerIdentifier
231     /// is relative, it is assumed to be relative to this cache's
232     /// root layer.  See documentation on RequestLayerMuting for
233     /// more details.
234     PCP_API
235     bool IsLayerMuted(const std::string& layerIdentifier) const;
236 
237     /// Returns true if the layer specified by \p layerIdentifier is
238     /// muted in this cache, false otherwise.  If \p layerIdentifier
239     /// is relative, it is assumed to be relative to \p anchorLayer.
240     /// If \p canonicalMutedLayerIdentifier is supplied, it will be
241     /// populated with the canonical identifier of the muted layer if this
242     /// function returns true.  See documentation on RequestLayerMuting
243     /// for more details.
244     PCP_API
245     bool IsLayerMuted(const SdfLayerHandle& anchorLayer,
246                       const std::string& layerIdentifier,
247                       std::string* canonicalMutedLayerIdentifier
248                           = nullptr) const;
249 
250     /// Returns parameter object containing all inputs for the prim index
251     /// computation used by this cache.
252     PCP_API
253     PcpPrimIndexInputs GetPrimIndexInputs();
254 
255     /// @}
256 
257     /// \name Computations
258     /// @{
259 
260     /// Returns the layer stack for \p identifier if it exists, otherwise
261     /// creates a new layer stack for \p identifier.  This returns \c NULL
262     /// if \p identifier is invalid (i.e. its root layer is \c NULL).
263     /// \p allErrors will contain any errors encountered while creating a
264     /// new layer stack.  It'll be unchanged if the layer stack already existed.
265     PCP_API
266     PcpLayerStackRefPtr
267     ComputeLayerStack(const PcpLayerStackIdentifier &identifier,
268                       PcpErrorVector *allErrors);
269 
270     /// Returns the layer stack for \p identifier if it has been computed
271     /// and cached, otherwise returns \c NULL.
272     PCP_API
273     PcpLayerStackPtr
274     FindLayerStack(const PcpLayerStackIdentifier &identifier) const;
275 
276     /// Return true if \p layerStack is used by this cache in its composition,
277     /// false otherwise.
278     PCP_API
279     bool UsesLayerStack(const PcpLayerStackPtr &layerStack) const;
280 
281     /// Compute and return a reference to the cached result for the
282     /// prim index for the given path. \p allErrors will contain any errors
283     /// encountered while performing this operation.
284     PCP_API
285     const PcpPrimIndex &
286     ComputePrimIndex(const SdfPath &primPath, PcpErrorVector *allErrors);
287 
288     /// Compute PcpPrimIndexes in the subtree rooted at path in parallel,
289     /// recursing to children based on the supplied \p childrenPred.  Also
290     /// include payloads not already in this cache's included payloads (see
291     /// GetIncludedPayloads()) according to \p payloadPred.
292     ///
293     /// This is similar to ComputePrimIndex(), except it computes an entire
294     /// subtree of indexes in parallel so it can be much more efficient.  This
295     /// function invokes both \p childrenPred and \p payloadPred concurrently,
296     /// so it must be safe to do so.
297     ///
298     /// When a PcpPrimIndex computation completes invoke \p childrenPred,
299     /// passing it the PcpPrimIndex.  If \p childrenPred returns true, continue
300     /// indexing children prim indexes.  In this case, \p childrenPred may
301     /// provide a list of names of the children prim indexes to compute.
302     /// If it does not, all children prim indexes will be computed.
303     /// If \p childrenPred returns false, stop indexing in that subtree.
304     ///
305     /// If payloads discovered during indexing do not already appear in this
306     /// cache's set of included payloads, invoke \p payloadPred, passing it the
307     /// path for the prim with the payload.  If \p payloadPred returns true,
308     /// include its payload and add it to the cache's set of included payloads
309     /// upon completion.
310     template <class ChildrenPredicate, class PayloadPredicate>
ComputePrimIndexesInParallel(const SdfPath & path,PcpErrorVector * allErrors,const ChildrenPredicate & childrenPred,const PayloadPredicate & payloadPred)311     void ComputePrimIndexesInParallel(const SdfPath &path,
312                                       PcpErrorVector *allErrors,
313                                       const ChildrenPredicate &childrenPred,
314                                       const PayloadPredicate &payloadPred) {
315         ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors,
316                                      childrenPred, payloadPred,
317                                      "Pcp", "ComputePrimIndexesInParallel");
318     }
319 
320     /// \overload
321     /// XXX Do not add new callers of this method.  It is needed as a workaround
322     /// for bug #132031, which we hope to tackle soon (as of 6/2016)
323     template <class ChildrenPredicate, class PayloadPredicate>
ComputePrimIndexesInParallel(const SdfPath & path,PcpErrorVector * allErrors,const ChildrenPredicate & childrenPred,const PayloadPredicate & payloadPred,const char * mallocTag1,const char * mallocTag2)324     void ComputePrimIndexesInParallel(const SdfPath &path,
325                                       PcpErrorVector *allErrors,
326                                       const ChildrenPredicate &childrenPred,
327                                       const PayloadPredicate &payloadPred,
328                                       const char *mallocTag1,
329                                       const char *mallocTag2) {
330         ComputePrimIndexesInParallel(SdfPathVector(1, path), allErrors,
331                                      childrenPred, payloadPred,
332                                      mallocTag1, mallocTag2);
333     }
334 
335     /// Vectorized form of ComputePrimIndexesInParallel().  Equivalent to
336     /// invoking that method for each path in \p paths, but more efficient.
337     template <class ChildrenPredicate, class PayloadPredicate>
ComputePrimIndexesInParallel(const SdfPathVector & paths,PcpErrorVector * allErrors,const ChildrenPredicate & childrenPred,const PayloadPredicate & payloadPred)338     void ComputePrimIndexesInParallel(const SdfPathVector &paths,
339                                       PcpErrorVector *allErrors,
340                                       const ChildrenPredicate &childrenPred,
341                                       const PayloadPredicate &payloadPred) {
342         _UntypedIndexingChildrenPredicate cp(&childrenPred);
343         _UntypedIndexingPayloadPredicate pp(&payloadPred);
344         _ComputePrimIndexesInParallel(paths, allErrors, cp, pp,
345                                       "Pcp", "ComputePrimIndexesInParallel");
346     }
347 
348     /// \overload
349     /// XXX Do not add new callers of this method.  It is needed as a workaround
350     /// for bug #132031, which we hope to tackle soon (as of 6/2016)
351     template <class ChildrenPredicate, class PayloadPredicate>
ComputePrimIndexesInParallel(const SdfPathVector & paths,PcpErrorVector * allErrors,const ChildrenPredicate & childrenPred,const PayloadPredicate & payloadPred,const char * mallocTag1,const char * mallocTag2)352     void ComputePrimIndexesInParallel(const SdfPathVector &paths,
353                                       PcpErrorVector *allErrors,
354                                       const ChildrenPredicate &childrenPred,
355                                       const PayloadPredicate &payloadPred,
356                                       const char *mallocTag1,
357                                       const char *mallocTag2) {
358         _UntypedIndexingChildrenPredicate cp(&childrenPred);
359         _UntypedIndexingPayloadPredicate pp(&payloadPred);
360         _ComputePrimIndexesInParallel(paths, allErrors, cp, pp,
361                                       mallocTag1, mallocTag2);
362     }
363 
364     /// Returns a pointer to the cached computed prim index for the given
365     /// path, or NULL if it has not been computed.
366     PCP_API
367     const PcpPrimIndex *
368     FindPrimIndex(const SdfPath &primPath) const;
369 
370     /// Run the given \p callback on every prim index in the cache.
371     /// The callback must have the signature: void(const PcpPrimIndex&).
372     template <class Callback>
373     void
ForEachPrimIndex(const Callback & callback)374     ForEachPrimIndex(const Callback& callback) const
375     {
376         TfFunctionRef<void(const PcpPrimIndex&)> fn(callback);
377         _ForEachPrimIndex(fn);
378     }
379 
380     /// Compute and return a reference to the cached result for the
381     /// property index for the given path. \p allErrors will contain any
382     /// errors encountered while performing this operation.
383     PCP_API
384     const PcpPropertyIndex &
385     ComputePropertyIndex(const SdfPath &propPath, PcpErrorVector *allErrors);
386 
387     /// Returns a pointer to the cached computed property index for the given
388     /// path, or NULL if it has not been computed.
389     PCP_API
390     const PcpPropertyIndex *
391     FindPropertyIndex(const SdfPath &propPath) const;
392 
393     /// Compute the relationship target paths for the relationship at
394     /// \p relationshipPath into \p paths.  If \p localOnly is \c true then
395     /// this will compose relationship targets from local nodes only.  If
396     /// \p stopProperty is not \c NULL then this will stop composing
397     /// relationship targets at \p stopProperty, including \p stopProperty
398     /// iff \p includeStopProperty is \c true.  If not \c NULL, \p deletedPaths
399     /// will be populated with target paths whose deletion contributed to
400     /// the computed result.  \p allErrors will contain any errors encountered
401     /// while performing this operation.
402     PCP_API
403     void
404     ComputeRelationshipTargetPaths(const SdfPath &relationshipPath,
405                                    SdfPathVector *paths,
406                                    bool localOnly,
407                                    const SdfSpecHandle &stopProperty,
408                                    bool includeStopProperty,
409                                    SdfPathVector *deletedPaths,
410                                    PcpErrorVector *allErrors);
411 
412     /// Compute the attribute connection paths for the attribute at
413     /// \p attributePath into \p paths.  If \p localOnly is \c true then
414     /// this will compose attribute connections from local nodes only.  If
415     /// \p stopProperty is not \c NULL then this will stop composing
416     /// attribute connections at \p stopProperty, including \p stopProperty
417     /// iff \p includeStopProperty is \c true.  If not \c NULL, \p deletedPaths
418     /// will be populated with connection paths whose deletion contributed to
419     /// the computed result.  \p allErrors will contain any errors encountered
420     /// while performing this operation.
421     PCP_API
422     void
423     ComputeAttributeConnectionPaths(const SdfPath &attributePath,
424                                     SdfPathVector *paths,
425                                     bool localOnly,
426                                     const SdfSpecHandle &stopProperty,
427                                     bool includeStopProperty,
428                                     SdfPathVector *deletedPaths,
429                                     PcpErrorVector *allErrors);
430 
431     /// @}
432     /// \name Dependencies
433     /// @{
434 
435     /// Returns set of all layers used by this cache.
436     PCP_API
437     SdfLayerHandleSet GetUsedLayers() const;
438 
439     /// Return a number that can be used to determine whether or not the set of
440     /// layers used by this cache may have changed or not.  For example, if one
441     /// calls GetUsedLayers() and saves the GetUsedLayersRevision(), and then
442     /// later calls GetUsedLayersRevision() again, if the number is unchanged,
443     /// then GetUsedLayers() is guaranteed to be unchanged as well.
444     PCP_API
445     size_t GetUsedLayersRevision() const;
446 
447     /// Returns set of all root layers used by this cache.
448     PCP_API
449     SdfLayerHandleSet GetUsedRootLayers() const;
450 
451     /// Returns every computed & cached layer stack that includes \p layer.
452     PCP_API
453     const PcpLayerStackPtrVector&
454     FindAllLayerStacksUsingLayer(const SdfLayerHandle& layer) const;
455 
456     /// Run the given \p callbcack on every layer stack used by prim
457     /// indexes in the cache. The callback must have the signature:
458     /// void(const PcpLayerStackPtr&).
459     template <class Callback>
460     void
ForEachLayerStack(const Callback & callback)461     ForEachLayerStack(const Callback& callback) const
462     {
463         TfFunctionRef<void(const PcpLayerStackPtr&)> fn(callback);
464         _ForEachLayerStack(fn);
465     }
466 
467     /// Returns dependencies on the given site of scene description,
468     /// as discovered by the cached index computations.
469     ///
470     /// \param depMask specifies what classes of dependency to include;
471     ///        see PcpDependencyFlags for details
472     /// \param recurseOnSite includes incoming dependencies on
473     ///        children of sitePath
474     /// \param recurseOnIndex extends the result to include all PcpCache
475     ///        child indexes below discovered results
476     /// \param filterForExistingCachesOnly filters the results to only
477     ///        paths representing computed prim and property index caches;
478     ///        otherwise a recursively-expanded result can include
479     ///        un-computed paths that are expected to depend on the site
480     PCP_API
481     PcpDependencyVector
482     FindSiteDependencies(const PcpLayerStackPtr& siteLayerStack,
483                          const SdfPath& sitePath,
484                          PcpDependencyFlags depMask,
485                          bool recurseOnSite,
486                          bool recurseOnIndex,
487                          bool filterForExistingCachesOnly) const;
488 
489     /// Returns dependencies on the given site of scene description,
490     /// as discovered by the cached index computations.
491     ///
492     /// This method overload takes a site layer rather than a layer
493     /// stack.  It will check every layer stack using that layer, and
494     /// apply any relevant sublayer offsets to the map functions in the
495     /// returned PcpDependencyVector.
496     ///
497     /// See the other method for parameter details.
498     PCP_API
499     PcpDependencyVector
500     FindSiteDependencies(const SdfLayerHandle& siteLayer,
501                          const SdfPath& sitePath,
502                          PcpDependencyFlags depMask,
503                          bool recurseOnSite,
504                          bool recurseOnIndex,
505                          bool filterForExistingCachesOnly) const;
506 
507     /// Returns \c true if an opinion for the site at \p localPcpSitePath
508     /// in the cache's layer stack can be provided by an opinion in \p layer,
509     /// \c false otherwise.  If \c true and \p allowedPathInLayer is not
510     /// \c NULL then it's set to a path in \p layer that would provide an
511     /// opinion.
512     ///
513     /// This returns \c false if no prim index has yet been computed for
514     /// \p localPcpSitePath.
515     PCP_API
516     bool CanHaveOpinionForSite(const SdfPath& localPcpSitePath,
517                                const SdfLayerHandle& layer,
518                                SdfPath* allowedPathInLayer) const;
519 
520     /// Returns a vector of sublayer asset paths used in the layer stack
521     /// that didn't resolve to valid assets.
522     PCP_API
523     std::vector<std::string> GetInvalidSublayerIdentifiers() const;
524 
525     /// Returns true if \p identifier was used as a sublayer path in a
526     /// layer stack but did not identify a valid layer. This is functionally
527     /// equivalent to examining the values in the vector returned by
528     /// GetInvalidSublayerIdentifiers, but more efficient.
529     PCP_API
530     bool IsInvalidSublayerIdentifier(const std::string& identifier) const;
531 
532     /// Returns a map of prim paths to asset paths used by that prim
533     /// (e.g. in a reference) that didn't resolve to valid assets.
534     PCP_API
535     std::map<SdfPath, std::vector<std::string>, SdfPath::FastLessThan>
536     GetInvalidAssetPaths() const;
537 
538     /// Returns true if \p resolvedAssetPath was used by a prim (e.g. in
539     /// a reference) but did not resolve to a valid asset. This is
540     /// functionally equivalent to examining the values in the map returned
541     /// by GetInvalidAssetPaths, but more efficient.
542     PCP_API
543     bool IsInvalidAssetPath(const std::string& resolvedAssetPath) const;
544 
545     /// Returns true if any prim index in this cache has a dependency on a
546     /// dynamic file format argument field.
547     PCP_API
548     bool HasAnyDynamicFileFormatArgumentDependencies() const;
549 
550     /// Returns true if the given \p field is the name of a field that
551     /// was composed while generating dynamic file format arguments for any prim
552     /// index in this cache.
553     PCP_API
554     bool IsPossibleDynamicFileFormatArgumentField(const TfToken &field) const;
555 
556     /// Returns the dynamic file format dependency data object for the prim
557     /// index with the given \p primIndexPath. This will return an empty
558     /// dependency data if either there is no cache prim index for the path or
559     /// if the prim index has no dynamic file formats that it depends on.
560     PCP_API
561     const PcpDynamicFileFormatDependencyData &
562     GetDynamicFileFormatArgumentDependencyData(
563         const SdfPath &primIndexPath) const;
564 
565     /// @}
566 
567     /// \name Change handling
568     /// @{
569 
570     /// Apply the changes in \p changes.  This blows caches.  It's up to
571     /// the client to pull on those caches again as needed.
572     ///
573     /// Objects that are no longer needed and would be destroyed are
574     /// retained in \p lifeboat and won't be destroyed until \p lifeboat is
575     /// itself destroyed.  This gives the client control over the timing
576     /// of the destruction of those objects.  Clients may choose to pull
577     /// on the caches before destroying \p lifeboat.  That may cause the
578     /// caches to again retain the objects, meaning they won't be destroyed
579     /// when \p lifeboat is destroyed.
580     ///
581     /// For example, if blowing a cache means an SdfLayer is no longer
582     /// needed then \p lifeboat will hold an SdfLayerRefPtr to that layer.
583     /// The client can then pull on that cache, which could cause the
584     /// cache to hold an SdfLayerRefPtr to the layer again.  If so then
585     /// destroying \p changes will not destroy the layer.  In any case,
586     /// we don't destroy the layer and then read it again.  However, if
587     /// the client destroys \p lifeboat before pulling on the cache then
588     /// we would destroy the layer then read it again.
589     PCP_API
590     void Apply(const PcpCacheChanges& changes, PcpLifeboat* lifeboat);
591 
592     /// Reload the layers of the layer stack, except session layers
593     /// and sublayers of session layers.  This will also try to load
594     /// sublayers in this cache's layer stack that could not be loaded
595     /// previously.  It will also try to load any referenced or payloaded
596     /// layer that could not be loaded previously.  Clients should
597     /// subsequently \c Apply() \p changes to use any now-valid layers.
598     PCP_API
599     void Reload(PcpChanges* changes);
600 
601     /// Reload every layer used by the prim at \p primPath that's across
602     /// a reference or payload.  Clients should subsequently apply the
603     /// changes to use any now valid layers.
604     ///
605     /// Note:  If a reference or payload was to an invalid asset and this
606     /// asset is valid upon reloading then this call will not necessarily
607     /// reload every layer accessible across the reference or payload.
608     /// For example, say prim R has an invalid reference and prim Q has a
609     /// valid reference to layer X with sublayer Y.  If on reload R now
610     /// has a valid reference to layer Z with sublayer Y, we will load Z
611     /// but we will not reload Y.
612     PCP_API
613     void ReloadReferences(PcpChanges* changes, const SdfPath& primPath);
614 
615     /// @}
616 
617     /// \name Diagnostics
618     /// @{
619 
620     /// Prints various statistics about the data stored in this cache.
621     PCP_API
622     void PrintStatistics() const;
623 
624     /// @}
625 
626 private:
627     friend class PcpChanges;
628     friend class Pcp_Statistics;
629 
630     struct _ParallelIndexer;
631 
632     // Helper struct to type-erase a children predicate for the duration of
633     // ComputePrimIndexesInParallel.
634     //
635     // This lets us achieve two goals.  First, clients may pass any arbitrary
636     // type as a predicate (e.g. they do not have to derive some base class).
637     // Second, it lets us keep the parallel indexing implementation in the .cpp
638     // file, avoiding any large template code instantiation.
639     //
640     // The cost we pay is this very thin indirect call.  We instantiate a
641     // function template with the client's predicate type that simply does a
642     // typecast and predicate invocation, and pass that function pointer into
643     // the implementation.  There is no heap allocation, no predicate copy, no
644     // argument marshalling, etc.
645     struct _UntypedIndexingChildrenPredicate {
_UntypedIndexingChildrenPredicate_UntypedIndexingChildrenPredicate646         _UntypedIndexingChildrenPredicate() : pred(nullptr), invoke(nullptr) {}
647         template <class Pred>
_UntypedIndexingChildrenPredicate_UntypedIndexingChildrenPredicate648         explicit _UntypedIndexingChildrenPredicate(const Pred *pred)
649             : pred(pred), invoke(_Invoke<Pred>) {}
650 
operator_UntypedIndexingChildrenPredicate651         inline bool operator()(const PcpPrimIndex &index,
652                                TfTokenVector *childNamesToCompose) const {
653             return invoke(pred, index, childNamesToCompose);
654         }
655     private:
656         template <class Pred>
_Invoke_UntypedIndexingChildrenPredicate657         static bool _Invoke(const void *pred, const PcpPrimIndex &index,
658                             TfTokenVector *namesToCompose) {
659             return (*static_cast<const Pred *>(pred))(index, namesToCompose);
660         }
661         const void *pred;
662         bool (*invoke)(const void *, const PcpPrimIndex &, TfTokenVector *);
663     };
664 
665     // See doc for _UntypedIndexingChildrenPredicate above.  This does the same
666     // for the payload inclusion predicate.
667     struct _UntypedIndexingPayloadPredicate {
668         template <class Pred>
_UntypedIndexingPayloadPredicate_UntypedIndexingPayloadPredicate669         explicit _UntypedIndexingPayloadPredicate(const Pred *pred)
670             : pred(pred), invoke(_Invoke<Pred>) {}
671 
operator_UntypedIndexingPayloadPredicate672         inline bool operator()(const SdfPath &path) const {
673             return invoke(pred, path);
674         }
675     private:
676         template <class Pred>
_Invoke_UntypedIndexingPayloadPredicate677         static bool _Invoke(const void *pred, const SdfPath &path) {
678             return (*static_cast<const Pred *>(pred))(path);
679         }
680         const void *pred;
681         bool (*invoke)(const void *, const SdfPath &);
682     };
683 
684     // Internal helper for recursive indexing.
685     const PcpPrimIndex &
686     _ComputePrimIndexWithCompatibleInputs(
687         const SdfPath & path, const PcpPrimIndexInputs &inputs,
688         PcpErrorVector *allErrors);
689 
690     // Friend to allow low-level indexing code access to the above.
691     friend const PcpPrimIndex &
692     Pcp_ComputePrimIndexWithCompatibleInputs(
693         PcpCache &cache,
694         const SdfPath & path, const PcpPrimIndexInputs &inputs,
695         PcpErrorVector *allErrors);
696 
697     // Parallel indexing implementation.
698     PCP_API
699     void _ComputePrimIndexesInParallel(
700         const SdfPathVector &paths,
701         PcpErrorVector *allErrors,
702         _UntypedIndexingChildrenPredicate childrenPred,
703         _UntypedIndexingPayloadPredicate payloadPred,
704         const char *mallocTag1,
705         const char *mallocTag2);
706 
707     void _RemovePrimCache(const SdfPath& primPath, PcpLifeboat* lifeboat);
708     void _RemovePrimAndPropertyCaches(const SdfPath& root,
709                                       PcpLifeboat* lifeboat);
710     void _RemovePropertyCache(const SdfPath& root, PcpLifeboat* lifeboat);
711     void _RemovePropertyCaches(const SdfPath& root, PcpLifeboat* lifeboat);
712 
713     // Returns the prim index for \p path if it exists, NULL otherwise.
714     PcpPrimIndex* _GetPrimIndex(const SdfPath& path);
715     const PcpPrimIndex* _GetPrimIndex(const SdfPath& path) const;
716 
717     // Returns the property index for \p path if it exists, NULL otherwise.
718     PcpPropertyIndex* _GetPropertyIndex(const SdfPath& path);
719     const PcpPropertyIndex* _GetPropertyIndex(const SdfPath& path) const;
720 
721     PCP_API
722     void _ForEachPrimIndex(
723         const TfFunctionRef<void(const PcpPrimIndex&)>& fn) const;
724 
725     PCP_API
726     void _ForEachLayerStack(
727         const TfFunctionRef<void(const PcpLayerStackPtr&)>& fn) const;
728 
729 private:
730     // Fixed evaluation parameters, set when the cache is created.  Note that
731     // _rootLayer and _sessionLayer are not const because we want to mutate them
732     // to enable parallel teardown in the destructor.
733     SdfLayerRefPtr _rootLayer;
734     SdfLayerRefPtr _sessionLayer;
735     const PcpLayerStackIdentifier _layerStackIdentifier;
736 
737     // Flag that configures PcpCache to use the restricted set of USD features.
738     // Currently it governs whether relocates, inherits, permissions,
739     // symmetry, or payloads are considered, and whether the prim stack
740     // is populated and its depdencies gathered during computation of
741     // prim indices and composition of prim child names.
742     const bool _usd;
743 
744     // File format target for all scene description layers this cache will
745     // find or open during prim index computation.
746     const std::string _fileFormatTarget;
747 
748     // The layer stack for this cache.  Holding this by ref ptr means we
749     // hold all of our local layers by ref ptr (including the root and
750     // session layers, again).
751     PcpLayerStackRefPtr _layerStack;
752 
753     // Modifiable evaluation parameters.
754     // Anything that changes these should also yield a PcpChanges
755     // value describing the necessary cache invalidation.
756     PayloadSet _includedPayloads;
757     PcpVariantFallbackMap _variantFallbackMap;
758 
759     // Cached computation types.
760     typedef Pcp_LayerStackRegistryRefPtr _LayerStackCache;
761     typedef SdfPathTable<PcpPrimIndex> _PrimIndexCache;
762     typedef SdfPathTable<PcpPropertyIndex> _PropertyIndexCache;
763 
764     // Cached computations.
765     _LayerStackCache _layerStackCache;
766     _PrimIndexCache  _primIndexCache;
767     _PropertyIndexCache  _propertyIndexCache;
768     std::unique_ptr<Pcp_Dependencies> _primDependencies;
769 
770     // Parallel indexer state.
771     std::unique_ptr<_ParallelIndexer> _parallelIndexer;
772 };
773 
774 PXR_NAMESPACE_CLOSE_SCOPE
775 
776 #endif // PXR_USD_PCP_CACHE_H
777