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 // \file LayerStack.cpp
25 
26 #include "pxr/pxr.h"
27 #include "pxr/usd/pcp/layerStack.h"
28 #include "pxr/usd/pcp/changes.h"
29 #include "pxr/usd/pcp/layerStackRegistry.h"
30 #include "pxr/usd/pcp/layerPrefetchRequest.h"
31 #include "pxr/usd/pcp/utils.h"
32 #include "pxr/usd/sdf/layer.h"
33 #include "pxr/usd/sdf/layerUtils.h"
34 #include "pxr/usd/sdf/primSpec.h"
35 #include "pxr/usd/ar/resolverContextBinder.h"
36 #include "pxr/base/trace/trace.h"
37 #include "pxr/base/tf/envSetting.h"
38 #include "pxr/base/tf/mallocTag.h"
39 
40 #include <algorithm>
41 #include <iterator>
42 #include <map>
43 #include <unordered_set>
44 
45 using std::string;
46 using std::vector;
47 
48 PXR_NAMESPACE_OPEN_SCOPE
49 
50 ////////////////////////////////////////////////////////////////////////
51 // Computing layer stacks
52 
53 // XXX Parallel layer prefetch is disabled until Sd thread-safety issues
54 // can be fixed, specifically plugin loading:
55 // - FileFormat plugins
56 // - value type plugins for parsing AnimSplines
57 TF_DEFINE_ENV_SETTING(
58     PCP_ENABLE_PARALLEL_LAYER_PREFETCH, false,
59     "Enables parallel, threaded pre-fetch of sublayers.");
60 
61 TF_DEFINE_ENV_SETTING(
62     PCP_DISABLE_TIME_SCALING_BY_LAYER_TCPS, false,
63     "Disables automatic layer offset scaling from time codes per second "
64     "metadata in layers.");
65 
66 bool
PcpIsTimeScalingForLayerTimeCodesPerSecondDisabled()67 PcpIsTimeScalingForLayerTimeCodesPerSecondDisabled()
68 {
69     return TfGetEnvSetting(PCP_DISABLE_TIME_SCALING_BY_LAYER_TCPS);
70 }
71 
72 struct Pcp_SublayerInfo {
Pcp_SublayerInfoPcp_SublayerInfo73     Pcp_SublayerInfo(const SdfLayerRefPtr& layer_, const SdfLayerOffset& offset_,
74                      double timeCodesPerSecond_)
75         : layer(layer_)
76         , offset(offset_)
77         , timeCodesPerSecond(timeCodesPerSecond_) {}
78     SdfLayerRefPtr layer;
79     SdfLayerOffset offset;
80     double timeCodesPerSecond;
81 };
82 typedef std::vector<Pcp_SublayerInfo> Pcp_SublayerInfoVector;
83 
84 // Desired strict weak ordering.
85 class Pcp_SublayerOrdering {
86 public:
Pcp_SublayerOrdering(const std::string & sessionOwner)87     Pcp_SublayerOrdering(const std::string& sessionOwner) :
88         _sessionOwner(sessionOwner)
89     {
90         // Do nothing
91     }
92 
93     // Returns true if a's layer has an owner equal to _sessionOwner.
IsOwned(const Pcp_SublayerInfo & a) const94     bool IsOwned(const Pcp_SublayerInfo& a) const
95     {
96         return a.layer->HasOwner() &&
97                a.layer->GetOwner() == _sessionOwner;
98     }
99 
100     // If one layer has the owner and the other does not then the one with
101     // the owner is less than the other.  Otherwise the layers are equivalent.
operator ()(const Pcp_SublayerInfo & a,const Pcp_SublayerInfo & b) const102     bool operator()(const Pcp_SublayerInfo& a,
103                     const Pcp_SublayerInfo& b) const
104     {
105         return IsOwned(a) && !IsOwned(b);
106     }
107 
108 private:
109     std::string _sessionOwner;
110 };
111 
112 static void
_ApplyOwnedSublayerOrder(const PcpLayerStackIdentifier & identifier,const SdfLayerHandle & layer,const std::string & sessionOwner,Pcp_SublayerInfoVector * subtrees,PcpErrorVector * errors)113 _ApplyOwnedSublayerOrder(
114     const PcpLayerStackIdentifier &identifier,
115     const SdfLayerHandle & layer,
116     const std::string& sessionOwner,
117     Pcp_SublayerInfoVector* subtrees,
118     PcpErrorVector *errors)
119 {
120     // Reorder the given sublayers to give (opinion) priority to the sublayer
121     // belonging to the session owner, if any.
122     //
123     // When the following conditions are met:
124     //
125     //     1. The session layer specifies a session owner
126     //        (this should always be the case in an interactive session)
127     //
128     //     2. A layer specifies that its sublayers can be "owned"
129     //        (e.g., the "anim" layer of a shot)
130     //
131     //     3. A sublayer of that layer belongs to the session owner
132     //        (e.g., an animator's personal sublayer in a shared shot)
133     //
134     // ... then that sublayer will be moved to the front of the list of
135     // sublayers, guaranteeing that it will have the strongest opinions among
136     // its sibling layers.
137     //
138     // Note that this means the effective order of these sublayers will be
139     // different between interactive sessions run by different users, which is
140     // the intended result.
141 
142     // Sort if conditions 1 and 2 are met.
143     if (!sessionOwner.empty() && layer->GetHasOwnedSubLayers()) {
144         // Stable sort against owned layer.
145         Pcp_SublayerOrdering ordering(sessionOwner);
146         std::stable_sort(subtrees->begin(), subtrees->end(), ordering);
147 
148         // Complain if there was more than one owned layer.  This is not
149         // a problem for our algorithm but, for now, it's cause for
150         // concern to the user.
151         if (!subtrees->empty() && ordering.IsOwned(subtrees->front())) {
152             // The first layer is owned.  Get the range of layers that are
153             // owned.
154             Pcp_SublayerInfoVector::iterator first = subtrees->begin();
155             Pcp_SublayerInfoVector::iterator last  =
156                 std::upper_bound(first, subtrees->end(), *first, ordering);
157 
158             // Report an error if more than one layer is owned.
159             if (std::distance(first, last) > 1) {
160                 PcpErrorInvalidSublayerOwnershipPtr error =
161                     PcpErrorInvalidSublayerOwnership::New();
162                 error->rootSite = PcpSiteStr(identifier,
163                                              SdfPath::AbsoluteRootPath());
164                 error->owner = sessionOwner;
165                 error->layer = layer;
166                 for (; first != last; ++first) {
167                     error->sublayers.push_back(first->layer);
168                 }
169                 errors->push_back(error);
170             }
171         }
172     }
173 }
174 
175 void
Pcp_ComputeRelocationsForLayerStack(const SdfLayerRefPtrVector & layers,SdfRelocatesMap * relocatesSourceToTarget,SdfRelocatesMap * relocatesTargetToSource,SdfRelocatesMap * incrementalRelocatesSourceToTarget,SdfRelocatesMap * incrementalRelocatesTargetToSource,SdfPathVector * relocatesPrimPaths)176 Pcp_ComputeRelocationsForLayerStack(
177     const SdfLayerRefPtrVector & layers,
178     SdfRelocatesMap *relocatesSourceToTarget,
179     SdfRelocatesMap *relocatesTargetToSource,
180     SdfRelocatesMap *incrementalRelocatesSourceToTarget,
181     SdfRelocatesMap *incrementalRelocatesTargetToSource,
182     SdfPathVector *relocatesPrimPaths)
183 {
184     TRACE_FUNCTION();
185 
186     // Compose authored relocation arcs per prim path.
187     std::map<SdfPath, SdfRelocatesMap> relocatesPerPrim;
188     static const TfToken field = SdfFieldKeys->Relocates;
189     TF_REVERSE_FOR_ALL(layer, layers) {
190         if (!(*layer)->GetHints().mightHaveRelocates) {
191             continue;
192         }
193 
194         // Check for relocation arcs in this layer.
195         SdfPrimSpecHandleVector stack;
196         stack.push_back( (*layer)->GetPseudoRoot() );
197         while (!stack.empty()) {
198             SdfPrimSpecHandle prim = stack.back();
199             stack.pop_back();
200             // Push back any children.
201             TF_FOR_ALL(child, prim->GetNameChildren()) {
202                 stack.push_back(*child);
203             }
204             // Check for relocations.
205             if (!prim->HasField(field)) {
206                 // No opinion in this layer.
207                 continue;
208             }
209             const VtValue& fieldValue = prim->GetField(field);
210             if (!fieldValue.IsHolding<SdfRelocatesMap>()) {
211                 TF_CODING_ERROR("Field '%s' in <%s> in layer @%s@"
212                                 "does not contain an SdfRelocatesMap",
213                                 field.GetText(), prim->GetPath().GetText(),
214                                 (*layer)->GetIdentifier().c_str());
215                 continue;
216             }
217             const SdfPath & primPath = prim->GetPath();
218             const SdfRelocatesMap & relocMap =
219                 fieldValue.UncheckedGet<SdfRelocatesMap>();
220             TF_FOR_ALL(reloc, relocMap) {
221                 // Absolutize source/target paths.
222                 SdfPath source = reloc->first .MakeAbsolutePath(primPath);
223                 SdfPath target = reloc->second.MakeAbsolutePath(primPath);
224                 if (source == target || source.HasPrefix(target)) {
225                     // Skip relocations from a path P back to itself and
226                     // relocations from a path P to an ancestor of P.
227                     // (The authoring code in Csd should never create these,
228                     // but they can be introduced by hand-editing.)
229                     //
230                     // Including them in the composed table would complicate
231                     // life downstream, since all consumers of this table
232                     // would have to be aware of this weird edge-case
233                     // scenario.
234                     //
235                     // XXX: Although Csd already throws a warning
236                     //      when this happens, we should also add a
237                     //      formal PcpError for this case.  Perhaps
238                     //      we can do this when removing the
239                     //      non-Pcp-mode composition code from Csd.
240                 }
241                 else {
242                     relocatesPerPrim[primPath][source] = target;
243                 }
244             }
245 
246             relocatesPrimPaths->push_back(prim->GetPath());
247         }
248     }
249 
250     // Compose the final set of relocation arcs for this layer stack,
251     // taking into account the cumulative effect of relocations down
252     // namespace.
253     TF_FOR_ALL(relocatesForPath, relocatesPerPrim) {
254         TF_FOR_ALL(reloc, relocatesForPath->second) {
255             SdfPath source = reloc->first;
256             const SdfPath & target = reloc->second;
257 
258             (*incrementalRelocatesTargetToSource)[target] = source;
259             (*incrementalRelocatesSourceToTarget)[source] = target;
260 
261             // Check for ancestral relocations.  The source path may have
262             // ancestors that were themselves the target of an ancestral
263             // relocate.
264             for (SdfPath p = source; !p.IsEmpty(); p = p.GetParentPath()) {
265                 // We rely on the fact that relocatesPerPrim is stored
266                 // and traversed in namespace order to ensure that we
267                 // have already incoporated ancestral arcs into
268                 // relocatesTargetToSource.
269                 SdfRelocatesMap::const_iterator i =
270                     relocatesTargetToSource->find(p);
271                 if (i != relocatesTargetToSource->end()) {
272                     // Ancestral source path p was itself a relocation
273                     // target.  Follow back to the ancestral source.
274                     source = source.ReplacePrefix(i->first, i->second);
275                     // Continue the traversal at the ancestral source.
276                     p = i->second;
277                 }
278             }
279 
280             // Establish a bi-directional mapping: source <-> target.
281             (*relocatesTargetToSource)[target] = source;
282             (*relocatesSourceToTarget)[source] = target;
283         }
284     }
285 }
286 
287 static PcpMapFunction
_FilterRelocationsForPath(const PcpLayerStack & layerStack,const SdfPath & path)288 _FilterRelocationsForPath(const PcpLayerStack& layerStack,
289                           const SdfPath& path)
290 {
291     // Gather the relocations that affect this path.
292     PcpMapFunction::PathMap siteRelocates;
293 
294     // If this layer stack has relocates nested in namespace, the combined
295     // and incremental relocates map will both have an entry with the same
296     // target. We cannot include both in the map function, since that would
297     // make it non-invertible. In this case, we use the entry from the
298     // combined map since that's what consumers are expecting.
299     std::unordered_set<SdfPath, SdfPath::Hash> seenTargets;
300 
301     const SdfRelocatesMap& relocates = layerStack.GetRelocatesSourceToTarget();
302     for (SdfRelocatesMap::const_iterator
303          i = relocates.lower_bound(path), n = relocates.end();
304          (i != n) && (i->first.HasPrefix(path)); ++i) {
305         siteRelocates.insert(*i);
306         seenTargets.insert(i->second);
307     }
308 
309     const SdfRelocatesMap& incrementalRelocates =
310         layerStack.GetIncrementalRelocatesSourceToTarget();
311     for (SdfRelocatesMap::const_iterator
312          i = incrementalRelocates.lower_bound(path),
313          n = incrementalRelocates.end();
314          (i != n) && (i->first.HasPrefix(path)); ++i) {
315 
316         if (seenTargets.find(i->second) == seenTargets.end()) {
317             siteRelocates.insert(*i);
318             seenTargets.insert(i->second);
319         }
320     }
321 
322     siteRelocates[SdfPath::AbsoluteRootPath()] = SdfPath::AbsoluteRootPath();
323 
324     // Return a map function representing the relocates.
325     return PcpMapFunction::Create(siteRelocates, SdfLayerOffset());
326 }
327 
328 ////////////////////////////////////////////////////////////////////////
329 
330 bool
Pcp_NeedToRecomputeDueToAssetPathChange(const PcpLayerStackPtr & layerStack)331 Pcp_NeedToRecomputeDueToAssetPathChange(const PcpLayerStackPtr& layerStack)
332 {
333     ArResolverContextBinder binder(
334         layerStack->GetIdentifier().pathResolverContext);
335 
336     // Iterate through _sublayerSourceInfo to see if recomputing the
337     // asset paths used to open sublayers would result in different
338     // sublayers being opened.
339     for (const auto& sourceInfo : layerStack->_sublayerSourceInfo) {
340         const std::string& assetPath = SdfComputeAssetPathRelativeToLayer(
341             sourceInfo.layer, sourceInfo.authoredSublayerPath);
342         if (assetPath != sourceInfo.computedSublayerPath) {
343             return true;
344         }
345     }
346 
347     return false;
348 }
349 
350 // Helper for determining whether the session layer's computed TCPS should
351 // be used instead of the root layer's computed TCPS as the overall TCPS of
352 // layer stack. This is according to the strength order of:
353 // 1. Authored session timeCodesPerSecond
354 // 2. Authored root timeCodesPerSecond
355 // 3. Authored session framesPerSecond
356 // 4. Authored root framesPerSecond
357 // 5. SdfSchema fallback.
358 static
359 bool
_ShouldUseSessionTcps(const SdfLayerHandle & sessionLyr,const SdfLayerHandle & rootLyr)360 _ShouldUseSessionTcps(const SdfLayerHandle &sessionLyr,
361                       const SdfLayerHandle &rootLyr)
362 {
363     return sessionLyr && (
364         sessionLyr->HasTimeCodesPerSecond() ||
365         (!rootLyr->HasTimeCodesPerSecond() && sessionLyr->HasFramesPerSecond())
366     );
367 }
368 
369 bool
Pcp_NeedToRecomputeLayerStackTimeCodesPerSecond(const PcpLayerStackPtr & layerStack,const SdfLayerHandle & changedLayer)370 Pcp_NeedToRecomputeLayerStackTimeCodesPerSecond(
371     const PcpLayerStackPtr& layerStack, const SdfLayerHandle &changedLayer)
372 {
373     const SdfLayerHandle &sessionLayer =
374         layerStack->GetIdentifier().sessionLayer;
375     const SdfLayerHandle &rootLayer =
376         layerStack->GetIdentifier().rootLayer;
377 
378     // The changed layer is only relevant to the overall layer stack TCPS if
379     // it's the stack's root or session layer.
380     if (changedLayer != sessionLayer && changedLayer != rootLayer) {
381         return false;
382     }
383 
384     // The new layer stack TCPS, when its computed, will come
385     // from either the session or root layer depending on what's
386     // authored. We use the same logic here as we do in
387     // PcpLayerStack::_Compute.
388     const double newLayerStackTcps =
389         _ShouldUseSessionTcps(sessionLayer, rootLayer) ?
390             sessionLayer->GetTimeCodesPerSecond() :
391             rootLayer->GetTimeCodesPerSecond();
392 
393     // The layer stack's overall TCPS is cached so if it doesn't match, we
394     // need to recompute the layer stack.
395     return newLayerStackTcps != layerStack->GetTimeCodesPerSecond();
396 }
397 
398 ////////////////////////////////////////////////////////////////////////
399 // PcpLayerStack
400 
PcpLayerStack(const PcpLayerStackIdentifier & identifier,const std::string & fileFormatTarget,const Pcp_MutedLayers & mutedLayers,bool isUsd)401 PcpLayerStack::PcpLayerStack(
402     const PcpLayerStackIdentifier& identifier,
403     const std::string &fileFormatTarget,
404     const Pcp_MutedLayers &mutedLayers,
405     bool isUsd) :
406     _identifier(identifier),
407     _isUsd(isUsd)
408 {
409     TfAutoMallocTag2 tag("Pcp", "PcpLayerStack::PcpLayerStack");
410     TRACE_FUNCTION();
411 
412     if (!TF_VERIFY(_identifier)) {
413         return;
414     }
415 
416     _Compute(fileFormatTarget, mutedLayers);
417 
418     if (!_isUsd) {
419         Pcp_ComputeRelocationsForLayerStack(_layers,
420                                             &_relocatesSourceToTarget,
421                                             &_relocatesTargetToSource,
422                                             &_incrementalRelocatesSourceToTarget,
423                                             &_incrementalRelocatesTargetToSource,
424                                             &_relocatesPrimPaths);
425     }
426 }
427 
~PcpLayerStack()428 PcpLayerStack::~PcpLayerStack()
429 {
430     // Update layer-stack-to-layer maps in the registry.
431     _BlowLayers();
432     if (_registry) {
433         _registry->_SetLayersAndRemove(_identifier, this);
434     }
435 }
436 
437 void
Apply(const PcpLayerStackChanges & changes,PcpLifeboat * lifeboat)438 PcpLayerStack::Apply(const PcpLayerStackChanges& changes, PcpLifeboat* lifeboat)
439 {
440     // Invalidate the layer stack as necessary, recomputing immediately.
441     // Recomputing immediately assists optimal change processing --
442     // e.g. it lets us examine the before/after chagnge to relocations.
443 
444     // Blow layer tree/offsets if necessary.
445     if (changes.didChangeLayers || changes.didChangeLayerOffsets) {
446         // The following comment applies to didChangeLayerOffsets:
447         // XXX: We should just blow the layer offsets but for now
448         //      now it's easier to just blow the whole layer stack.
449         //      When we blow just the offsets we won't retain layers.
450 
451         // Retain prior set of layers.
452         TF_FOR_ALL(i, _layers) {
453             lifeboat->Retain(*i);
454         }
455         _BlowLayers();
456         _Compute(_registry->_GetFileFormatTarget(), _registry->_GetMutedLayers());
457     }
458 
459     // Update relocations if necessary.
460     if (!_isUsd &&
461         (changes.didChangeSignificantly || changes.didChangeRelocates)) {
462         // Blow the relocations if they changed specifically, or if there's been
463         // a significant change.
464         // A significant change means the composed opinions of the layer stack
465         // has changed in arbitrary ways, so we need to recompute the relocation
466         // table.
467         _BlowRelocations();
468         if (changes.didChangeSignificantly) {
469             // Recompute relocations from scratch.
470             Pcp_ComputeRelocationsForLayerStack(
471                 _layers,
472                 &_relocatesSourceToTarget,
473                 &_relocatesTargetToSource,
474                 &_incrementalRelocatesSourceToTarget,
475                 &_incrementalRelocatesTargetToSource,
476                 &_relocatesPrimPaths);
477         } else {
478             // Change processing has provided a specific new set of
479             // relocations to use.
480             _relocatesSourceToTarget = changes.newRelocatesSourceToTarget;
481             _relocatesTargetToSource = changes.newRelocatesTargetToSource;
482             _incrementalRelocatesSourceToTarget =
483                 changes.newIncrementalRelocatesSourceToTarget;
484             _incrementalRelocatesTargetToSource =
485                 changes.newIncrementalRelocatesTargetToSource;
486             _relocatesPrimPaths = changes.newRelocatesPrimPaths;
487         }
488 
489         // Recompute the derived relocation variables.
490         TF_FOR_ALL(i, _relocatesVariables) {
491             i->second->SetValue(_FilterRelocationsForPath(*this, i->first));
492         }
493     }
494 }
495 
496 const PcpLayerStackIdentifier&
GetIdentifier() const497 PcpLayerStack::GetIdentifier() const
498 {
499     return _identifier;
500 }
501 
502 const SdfLayerRefPtrVector&
GetLayers() const503 PcpLayerStack::GetLayers() const
504 {
505     return _layers;
506 }
507 
508 SdfLayerHandleVector
GetSessionLayers() const509 PcpLayerStack::GetSessionLayers() const
510 {
511     SdfLayerHandleVector sessionLayers;
512     if (_identifier.sessionLayer) {
513         // Session layers will always be the strongest layers in the
514         // layer stack. So, we can just take all of the layers stronger
515         // than the root layer.
516         SdfLayerRefPtrVector::const_iterator rootLayerIt =
517             std::find(_layers.begin(), _layers.end(), _identifier.rootLayer);
518         if (TF_VERIFY(rootLayerIt != _layers.end())) {
519             sessionLayers.insert(
520                 sessionLayers.begin(), _layers.begin(), rootLayerIt);
521         }
522     }
523 
524     return sessionLayers;
525 }
526 
527 const SdfLayerTreeHandle&
GetLayerTree() const528 PcpLayerStack::GetLayerTree() const
529 {
530     return _layerTree;
531 }
532 
533 // We have this version so that we can avoid weakptr/refptr conversions on the
534 // \p layer arg.
535 template <class LayerPtr>
536 static inline const SdfLayerOffset *
_GetLayerOffsetForLayer(LayerPtr const & layer,SdfLayerRefPtrVector const & layers,std::vector<PcpMapFunction> const & mapFunctions)537 _GetLayerOffsetForLayer(
538     LayerPtr const &layer,
539     SdfLayerRefPtrVector const &layers,
540     std::vector<PcpMapFunction> const &mapFunctions)
541 {
542     // XXX: Optimization: store a flag if all offsets are identity
543     //      and just return NULL if it's set.
544     for (size_t i = 0, n = layers.size(); i != n; ++i) {
545         if (layers[i] == layer) {
546             const SdfLayerOffset& layerOffset = mapFunctions[i].GetTimeOffset();
547             return layerOffset.IsIdentity() ? NULL : &layerOffset;
548         }
549     }
550     return NULL;
551 }
552 
553 const SdfLayerOffset*
GetLayerOffsetForLayer(const SdfLayerHandle & layer) const554 PcpLayerStack::GetLayerOffsetForLayer(const SdfLayerHandle& layer) const
555 {
556     return _GetLayerOffsetForLayer(layer, _layers, _mapFunctions);
557 }
558 
559 const SdfLayerOffset*
GetLayerOffsetForLayer(const SdfLayerRefPtr & layer) const560 PcpLayerStack::GetLayerOffsetForLayer(const SdfLayerRefPtr& layer) const
561 {
562     return _GetLayerOffsetForLayer(layer, _layers, _mapFunctions);
563 }
564 
565 const SdfLayerOffset*
GetLayerOffsetForLayer(size_t layerIdx) const566 PcpLayerStack::GetLayerOffsetForLayer(size_t layerIdx) const
567 {
568     // XXX: Optimization: store a flag if all offsets are identity
569     //      and just return NULL if it's set.
570     if (!TF_VERIFY(layerIdx < _mapFunctions.size())) {
571         return NULL;
572     }
573 
574     const SdfLayerOffset& layerOffset = _mapFunctions[layerIdx].GetTimeOffset();
575     return layerOffset.IsIdentity() ? NULL : &layerOffset;
576 }
577 
578 const std::set<std::string>&
GetMutedLayers() const579 PcpLayerStack::GetMutedLayers() const
580 {
581     return _mutedAssetPaths;
582 }
583 
584 bool
HasLayer(const SdfLayerHandle & layer) const585 PcpLayerStack::HasLayer(const SdfLayerHandle& layer) const
586 {
587     // Avoid doing refcount operations here.
588     SdfLayer const *layerPtr = get_pointer(layer);
589     for (SdfLayerRefPtr const &layerRefPtr: _layers) {
590         if (get_pointer(layerRefPtr) == layerPtr) {
591             return true;
592         }
593     }
594     return false;
595 }
596 
597 bool
HasLayer(const SdfLayerRefPtr & layer) const598 PcpLayerStack::HasLayer(const SdfLayerRefPtr& layer) const
599 {
600     return std::find(_layers.begin(), _layers.end(), layer) != _layers.end();
601 }
602 
603 const SdfRelocatesMap&
GetRelocatesSourceToTarget() const604 PcpLayerStack::GetRelocatesSourceToTarget() const
605 {
606     return _relocatesSourceToTarget;
607 }
608 
609 const SdfRelocatesMap&
GetRelocatesTargetToSource() const610 PcpLayerStack::GetRelocatesTargetToSource() const
611 {
612     return _relocatesTargetToSource;
613 }
614 
615 const SdfRelocatesMap&
GetIncrementalRelocatesSourceToTarget() const616 PcpLayerStack::GetIncrementalRelocatesSourceToTarget() const
617 {
618     return _incrementalRelocatesSourceToTarget;
619 }
620 
621 const SdfRelocatesMap&
GetIncrementalRelocatesTargetToSource() const622 PcpLayerStack::GetIncrementalRelocatesTargetToSource() const
623 {
624     return _incrementalRelocatesTargetToSource;
625 }
626 
627 const SdfPathVector&
GetPathsToPrimsWithRelocates() const628 PcpLayerStack::GetPathsToPrimsWithRelocates() const
629 {
630     return _relocatesPrimPaths;
631 }
632 
633 PcpMapExpression
GetExpressionForRelocatesAtPath(const SdfPath & path)634 PcpLayerStack::GetExpressionForRelocatesAtPath(const SdfPath &path)
635 {
636     const PcpMapExpression::Variable *var = nullptr;
637     {
638         tbb::spin_mutex::scoped_lock lock{_relocatesVariablesMutex};
639         _RelocatesVarMap::const_iterator i = _relocatesVariables.find(path);
640         if (i != _relocatesVariables.end()) {
641             var = i->second.get();
642         }
643     }
644 
645     if (var) {
646         return var->GetExpression();
647     }
648 
649     // Create a Variable representing the relocations that affect this path.
650     PcpMapExpression::VariableUniquePtr newVar =
651         PcpMapExpression::NewVariable(_FilterRelocationsForPath(*this, path));
652 
653     {
654         // Retain the variable so that we can update it if relocations change.
655         tbb::spin_mutex::scoped_lock lock{_relocatesVariablesMutex};
656         _RelocatesVarMap::const_iterator i =
657             _relocatesVariables.emplace(path, std::move(newVar)).first;
658         var = i->second.get();
659     }
660 
661     return var->GetExpression();
662 }
663 
664 void
_BlowLayers()665 PcpLayerStack::_BlowLayers()
666 {
667     // Blow all of the members that get recomputed during _Compute.
668     // Note this does not include relocations, which are maintained
669     // separately for efficiency.
670     _layers.clear();
671     _mapFunctions.clear();
672     _layerTree = TfNullPtr;
673     _sublayerSourceInfo.clear();
674     _mutedAssetPaths.clear();
675 }
676 
677 void
_BlowRelocations()678 PcpLayerStack::_BlowRelocations()
679 {
680     _relocatesSourceToTarget.clear();
681     _relocatesTargetToSource.clear();
682     _incrementalRelocatesSourceToTarget.clear();
683     _incrementalRelocatesTargetToSource.clear();
684     _relocatesPrimPaths.clear();
685 }
686 
687 void
_Compute(const std::string & fileFormatTarget,const Pcp_MutedLayers & mutedLayers)688 PcpLayerStack::_Compute(const std::string &fileFormatTarget,
689                         const Pcp_MutedLayers &mutedLayers)
690 {
691     // Builds the composed layer stack for \p result by recursively
692     // resolving sublayer asset paths and reading in the sublayers.
693     // In addition, this populates the result data with:
694     //
695     // - \c layerStack with a strength-ordered list of layers
696     //   (as ref-pointers, to keep the layers open)
697     // - \c mapFunctions with the corresponding full layer offset from
698     //   the root layer to each sublayer in layerStack
699     // - \c layerAssetPaths with the resolved asset path of every sublayer
700     // - \c errors with a precise description of any errors encountered
701     //
702     TRACE_FUNCTION();
703 
704     // Bind the resolver context.
705     ArResolverContextBinder binder(_identifier.pathResolverContext);
706 
707     // Get any special file format arguments we need to use when finding
708     // or opening sublayers.
709     const SdfLayer::FileFormatArguments layerArgs =
710         Pcp_GetArgumentsForFileFormatTarget(fileFormatTarget);
711 
712     // Do a parallel pre-fetch request of the shot layer stack. This
713     // resolves and parses the layers, retaining them until we do a
714     // serial pass below to stitch them into a layer tree. The post-pass
715     // is serial in order to get deterministic ordering of errors,
716     // and to keep the layer stack composition algorithm as simple as
717     // possible while doing the high-latency work up front in parallel.
718     PcpLayerPrefetchRequest prefetch;
719     if (TfGetEnvSetting(PCP_ENABLE_PARALLEL_LAYER_PREFETCH)) {
720         if (_identifier.sessionLayer) {
721             prefetch.RequestSublayerStack(_identifier.sessionLayer, layerArgs);
722         }
723         prefetch.RequestSublayerStack(_identifier.rootLayer, layerArgs);
724         prefetch.Run(mutedLayers);
725     }
726 
727     // The session owner.  This will be empty if there is no session owner
728     // in the session layer.
729     std::string sessionOwner;
730 
731     PcpErrorVector errors;
732 
733     // Build the layer stack.
734     std::set<SdfLayerHandle> seenLayers;
735 
736     // Env setting for disabling TCPS scaling.
737     const bool scaleLayerOffsetByTcps =
738         !PcpIsTimeScalingForLayerTimeCodesPerSecondDisabled();
739 
740     const double rootTcps = _identifier.rootLayer->GetTimeCodesPerSecond();
741     SdfLayerOffset rootLayerOffset;
742 
743     // The layer stack's time codes per second initially comes from the root
744     // layer. An opinion in the session layer may override it below.
745     _timeCodesPerSecond = rootTcps;
746 
747     // Add the layer stack due to the session layer.  We *don't* apply
748     // the sessionOwner to this stack.  We also skip this if the session
749     // layer has been muted; in this case, the stack will not include the
750     // session layer specified in the identifier.
751     if (_identifier.sessionLayer) {
752         std::string canonicalMutedPath;
753         if (mutedLayers.IsLayerMuted(_identifier.sessionLayer,
754                                      _identifier.sessionLayer->GetIdentifier(),
755                                      &canonicalMutedPath)) {
756             _mutedAssetPaths.insert(canonicalMutedPath);
757         }
758         else {
759             // The session layer has its own time codes per second.
760             const double sessionTcps =
761                 _identifier.sessionLayer->GetTimeCodesPerSecond();
762             SdfLayerOffset sessionLayerOffset;
763 
764             // The time codes per second of the entire layer stack may come
765             // from the session layer or the root layer depending on which
766             // metadata is authored where. We'll use the session layer's TCPS
767             // only if the session layer has an authored timeCodesPerSecond or
768             // if the root layer has no timeCodesPerSecond opinion but the
769             // session layer has a framesPerSecond opinion.
770             //
771             // Note that both the session and root layers still have their own
772             // computed TCPS for just the layer itself, so either layer may end
773             // up with a layer offset scale in its map function to map from the
774             // layer stack TCPS to the layer.
775             if (_ShouldUseSessionTcps(_identifier.sessionLayer,
776                                       _identifier.rootLayer)) {
777                 _timeCodesPerSecond = sessionTcps;
778                 if (scaleLayerOffsetByTcps) {
779                     rootLayerOffset.SetScale(_timeCodesPerSecond / rootTcps);
780                 }
781             } else {
782                 if (scaleLayerOffsetByTcps) {
783                     sessionLayerOffset.SetScale(_timeCodesPerSecond / sessionTcps);
784                 }
785             }
786 
787             SdfLayerTreeHandle sessionLayerTree =
788                 _BuildLayerStack(_identifier.sessionLayer, sessionLayerOffset,
789                                  sessionTcps,
790                                  _identifier.pathResolverContext, layerArgs,
791                                  std::string(), mutedLayers, &seenLayers,
792                                  &errors);
793 
794             // Get the session owner.
795             struct _Helper {
796                 static bool FindSessionOwner(const SdfLayerTreeHandle& tree,
797                                              std::string* sessionOwner)
798                 {
799                     if (tree->GetLayer()->HasField(SdfPath::AbsoluteRootPath(),
800                                                    SdfFieldKeys->SessionOwner,
801                                                    sessionOwner)) {
802                         return true;
803                     }
804                     TF_FOR_ALL(subtree, tree->GetChildTrees()) {
805                         if (FindSessionOwner(*subtree, sessionOwner)) {
806                             return true;
807                         }
808                     }
809                     return false;
810                 }
811             };
812 
813             _Helper::FindSessionOwner(sessionLayerTree, &sessionOwner);
814         }
815     }
816 
817     // Add the layer stack due to the root layer.  We do apply the
818     // sessionOwner, if any, to this stack.  Unlike session layers, we
819     // don't allow muting a layer stack's root layer since that would
820     // lead to empty layer stacks.
821     _layerTree =
822         _BuildLayerStack(_identifier.rootLayer, rootLayerOffset, rootTcps,
823                          _identifier.pathResolverContext, layerArgs,
824                          sessionOwner, mutedLayers, &seenLayers, &errors);
825 
826     // Update layer-stack-to-layer maps in the registry, if we're installed in a
827     // registry.
828     if (_registry)
829         _registry->_SetLayers(this);
830 
831     if (errors.empty()) {
832         _localErrors.reset();
833     } else {
834         _localErrors.reset(new PcpErrorVector);
835         _localErrors->swap(errors);
836     }
837 }
838 
839 SdfLayerTreeHandle
_BuildLayerStack(const SdfLayerHandle & layer,const SdfLayerOffset & offset,double layerTcps,const ArResolverContext & pathResolverContext,const SdfLayer::FileFormatArguments & defaultLayerArgs,const std::string & sessionOwner,const Pcp_MutedLayers & mutedLayers,SdfLayerHandleSet * seenLayers,PcpErrorVector * errors)840 PcpLayerStack::_BuildLayerStack(
841     const SdfLayerHandle & layer,
842     const SdfLayerOffset & offset,
843     double layerTcps,
844     const ArResolverContext & pathResolverContext,
845     const SdfLayer::FileFormatArguments & defaultLayerArgs,
846     const std::string & sessionOwner,
847     const Pcp_MutedLayers & mutedLayers,
848     SdfLayerHandleSet *seenLayers,
849     PcpErrorVector *errors)
850 {
851     seenLayers->insert(layer);
852 
853     // Accumulate layer into results.
854     _layers.push_back(layer);
855 
856     const PcpMapFunction::PathMap &identity = PcpMapFunction::IdentityPathMap();
857     PcpMapFunction mapFunction = PcpMapFunction::Create(identity, offset);
858     _mapFunctions.push_back(mapFunction);
859 
860     // Recurse over sublayers to build subtrees.
861     Pcp_SublayerInfoVector sublayerInfo;
862     const vector<string> &sublayers = layer->GetSubLayerPaths();
863     const SdfLayerOffsetVector &sublayerOffsets = layer->GetSubLayerOffsets();
864     for(size_t i=0, numSublayers = sublayers.size(); i<numSublayers; i++) {
865         string canonicalMutedPath;
866         if (mutedLayers.IsLayerMuted(layer, sublayers[i],
867                                      &canonicalMutedPath)) {
868             _mutedAssetPaths.insert(canonicalMutedPath);
869             continue;
870         }
871 
872         // Resolve and open sublayer.
873         TfErrorMark m;
874 
875         SdfLayer::FileFormatArguments localArgs;
876         const SdfLayer::FileFormatArguments& layerArgs =
877             Pcp_GetArgumentsForFileFormatTarget(
878                 sublayers[i], &defaultLayerArgs, &localArgs);
879 
880         // This is equivalent to SdfLayer::FindOrOpenRelativeToLayer, but we
881         // want to keep track of the final sublayer path after anchoring it
882         // to the layer.
883         string sublayerPath = SdfComputeAssetPathRelativeToLayer(
884             layer, sublayers[i]);
885         SdfLayerRefPtr sublayer = SdfLayer::FindOrOpen(sublayerPath, layerArgs);
886 
887         _sublayerSourceInfo.emplace_back(layer, sublayers[i], sublayerPath);
888 
889         if (!sublayer) {
890             PcpErrorInvalidSublayerPathPtr err =
891                 PcpErrorInvalidSublayerPath::New();
892             err->rootSite = PcpSite(_identifier, SdfPath::AbsoluteRootPath());
893             err->layer = layer;
894             err->sublayerPath = sublayerPath;
895             if (!m.IsClean()) {
896                 vector<string> commentary;
897                 for (auto const &err: m) {
898                     commentary.push_back(err.GetCommentary());
899                 }
900                 m.Clear();
901                 err->messages = TfStringJoin(commentary.begin(),
902                                              commentary.end(), "; ");
903             }
904             errors->push_back(err);
905             continue;
906         }
907 
908         // Check for cycles.
909         if (seenLayers->count(sublayer)) {
910             PcpErrorSublayerCyclePtr err = PcpErrorSublayerCycle::New();
911             err->rootSite = PcpSite(_identifier, SdfPath::AbsoluteRootPath());
912             err->layer = layer;
913             err->sublayer = sublayer;
914             errors->push_back(err);
915             continue;
916         }
917 
918         // Check sublayer offset.
919         SdfLayerOffset sublayerOffset = sublayerOffsets[i];
920         if (!sublayerOffset.IsValid()
921             || !sublayerOffset.GetInverse().IsValid()) {
922             // Report error, but continue with an identity layer offset.
923             PcpErrorInvalidSublayerOffsetPtr err =
924                 PcpErrorInvalidSublayerOffset::New();
925             err->rootSite = PcpSite(_identifier, SdfPath::AbsoluteRootPath());
926             err->layer       = layer;
927             err->sublayer    = sublayer;
928             err->offset      = sublayerOffset;
929             errors->push_back(err);
930             sublayerOffset = SdfLayerOffset();
931         }
932 
933         // Apply the scale from computed layer TCPS to sublayer TCPS to sublayer
934         // layer offset.
935         const double sublayerTcps = sublayer->GetTimeCodesPerSecond();
936         if (!PcpIsTimeScalingForLayerTimeCodesPerSecondDisabled() &&
937             layerTcps != sublayerTcps) {
938             sublayerOffset.SetScale(sublayerOffset.GetScale() *
939                                     layerTcps / sublayerTcps);
940         }
941 
942         // Combine the sublayerOffset with the cumulative offset
943         // to find the absolute offset of this layer.
944         sublayerOffset = offset * sublayerOffset;
945 
946         // Store the info for later recursion.
947         sublayerInfo.push_back(Pcp_SublayerInfo(
948             sublayer, sublayerOffset, sublayerTcps));
949     }
950 
951     // Reorder sublayers according to sessionOwner.
952     _ApplyOwnedSublayerOrder(_identifier, layer, sessionOwner, &sublayerInfo,
953                              errors);
954 
955     // Recurse over sublayers to build subtrees.  We must do this after
956     // applying the sublayer order, otherwise _layers and
957     // _mapFunctions will not appear in the right order.
958     // XXX: We might want the tree nodes themselves to own the layers.
959     //      Then we can construct the subtree nodes in the loop above
960     //      and reorder them afterwards.  After building the tree we
961     //      can preorder traverse it to collect the layers and offsets.
962     SdfLayerTreeHandleVector subtrees;
963     TF_FOR_ALL(i, sublayerInfo) {
964         if (SdfLayerTreeHandle subtree =
965             _BuildLayerStack(i->layer, i->offset, i->timeCodesPerSecond,
966                              pathResolverContext,
967                              defaultLayerArgs, sessionOwner,
968                              mutedLayers, seenLayers, errors)) {
969             subtrees.push_back(subtree);
970         }
971     }
972 
973     // Remove the layer from seenLayers.  We want to detect cycles, but
974     // do not prohibit the same layer from appearing multiple times.
975     seenLayers->erase(layer);
976 
977     return SdfLayerTree::New(layer, subtrees, offset);
978 }
979 
980 std::ostream&
operator <<(std::ostream & s,const PcpLayerStackPtr & x)981 operator<<(std::ostream& s, const PcpLayerStackPtr& x)
982 {
983     if (x) {
984         return s << x->GetIdentifier();
985     }
986     else {
987         return s << "@<expired>@";
988     }
989 }
990 
991 std::ostream&
operator <<(std::ostream & s,const PcpLayerStackRefPtr & x)992 operator<<(std::ostream& s, const PcpLayerStackRefPtr& x)
993 {
994     if (x) {
995         return s << x->GetIdentifier();
996     }
997     else {
998         return s << "@NULL@";
999     }
1000 }
1001 
1002 PXR_NAMESPACE_CLOSE_SCOPE
1003