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