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