From 3fbc7816aecf2bfe4e294fd96a6e6c606b02f58d Mon Sep 17 00:00:00 2001 From: krickw Date: Thu, 21 May 2020 15:36:08 -0400 Subject: [PATCH 1/4] Use separate UsdStageCache's for stages that loadAll or loadNone. Rename forcePopulate to loadAll to match the enum name. Remove the default parameter value for loadAll so future callers have to make a choice, they will be more likely to choose correctly. --- lib/mayaUsd/fileio/jobs/readJob.cpp | 3 ++- lib/mayaUsd/nodes/proxyShapeBase.cpp | 9 +++++++-- lib/mayaUsd/nodes/stageNode.cpp | 3 ++- lib/mayaUsd/python/wrapStageCache.cpp | 2 +- lib/mayaUsd/utils/stageCache.cpp | 8 ++++---- lib/mayaUsd/utils/stageCache.h | 2 +- plugin/pxr/maya/lib/usdMaya/referenceAssembly.cpp | 6 ++++-- plugin/pxr/maya/lib/usdMaya/translatorModelAssembly.cpp | 3 ++- 8 files changed, 23 insertions(+), 13 deletions(-) diff --git a/lib/mayaUsd/fileio/jobs/readJob.cpp b/lib/mayaUsd/fileio/jobs/readJob.cpp index f28a0c50b7..f7bd363b32 100644 --- a/lib/mayaUsd/fileio/jobs/readJob.cpp +++ b/lib/mayaUsd/fileio/jobs/readJob.cpp @@ -101,16 +101,17 @@ UsdMaya_ReadJob::Read(std::vector* addedDagPaths) varSelsVec); // Layer and Stage used to Read in the USD file - UsdStageCacheContext stageCacheContext(UsdMayaStageCache::Get()); UsdStageRefPtr stage; if (mImportData.hasPopulationMask()) { + // OpenMasked doesn't use the UsdStageCache, so don't create a UsdStageCacheContext stage = UsdStage::OpenMasked(rootLayer, sessionLayer, mImportData.stagePopulationMask(), mImportData.stageInitialLoadSet()); } else { + UsdStageCacheContext stageCacheContext(UsdMayaStageCache::Get(mImportData.stageInitialLoadSet() == UsdStage::InitialLoadSet::LoadAll)); stage = UsdStage::Open(rootLayer, sessionLayer, mImportData.stageInitialLoadSet()); } diff --git a/lib/mayaUsd/nodes/proxyShapeBase.cpp b/lib/mayaUsd/nodes/proxyShapeBase.cpp index 768a783bff..189ee985ca 100644 --- a/lib/mayaUsd/nodes/proxyShapeBase.cpp +++ b/lib/mayaUsd/nodes/proxyShapeBase.cpp @@ -481,7 +481,7 @@ MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock) } if (SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(fileString)) { - UsdStageCacheContext ctx(UsdMayaStageCache::Get()); + UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadSet == UsdStage::InitialLoadSet::LoadAll)); SdfLayerRefPtr sessionLayer = computeSessionLayer(dataBlock); if (sessionLayer) { usdStage = UsdStage::Open(rootLayer, @@ -498,7 +498,7 @@ MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock) } else if (!usdStage) { // Create a new stage in memory with an anonymous root layer. - UsdStageCacheContext ctx(UsdMayaStageCache::Get()); + UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadSet == UsdStage::InitialLoadSet::LoadAll)); usdStage = UsdStage::CreateInMemory("", loadSet); } @@ -755,6 +755,8 @@ MayaUsdProxyShapeBase::isStageValid() const MStatus MayaUsdProxyShapeBase::preEvaluation(const MDGContext& context, const MEvaluationNode& evaluationNode) { + // Any logic here should have an equivalent implementation in MayaUsdProxyShapeBase::setDependentsDirty(). + if (evaluationNode.dirtyPlugExists(excludePrimPathsAttr)) { _IncreaseExcludePrimPathsVersion(); } @@ -765,6 +767,7 @@ MayaUsdProxyShapeBase::preEvaluation(const MDGContext& context, const MEvaluatio evaluationNode.dirtyPlugExists(loadPayloadsAttr) || evaluationNode.dirtyPlugExists(inStageDataAttr)) { _IncreaseUsdStageVersion(); + MayaUsdProxyStageInvalidateNotice(*this).Send(); } return MStatus::kSuccess; @@ -786,6 +789,8 @@ MayaUsdProxyShapeBase::postEvaluation(const MDGContext& context, const MEvaluat MStatus MayaUsdProxyShapeBase::setDependentsDirty(const MPlug& plug, MPlugArray& plugArray) { + // Any logic here should have an equivalent implementation in MayaUsdProxyShapeBase::preEvaluation() or postEvaluation(). + // If/when the MPxDrawOverride for the proxy shape specifies // isAlwaysDirty=false to improve performance, we must be sure to notify // the Maya renderer that the geometry is dirty and needs to be redrawn diff --git a/lib/mayaUsd/nodes/stageNode.cpp b/lib/mayaUsd/nodes/stageNode.cpp index 58c706b0e0..6004d045c9 100644 --- a/lib/mayaUsd/nodes/stageNode.cpp +++ b/lib/mayaUsd/nodes/stageNode.cpp @@ -123,7 +123,8 @@ UsdMayaStageNode::compute(const MPlug& plug, MDataBlock& dataBlock) UsdStageRefPtr usdStage; if (SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(usdFile)) { - UsdStageCacheContext ctx(UsdMayaStageCache::Get()); + const bool loadAll = true; + UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadAll)); usdStage = UsdStage::Open(rootLayer, ArGetResolver().GetCurrentContext()); diff --git a/lib/mayaUsd/python/wrapStageCache.cpp b/lib/mayaUsd/python/wrapStageCache.cpp index f74a641c7e..e2fc4132bd 100644 --- a/lib/mayaUsd/python/wrapStageCache.cpp +++ b/lib/mayaUsd/python/wrapStageCache.cpp @@ -33,7 +33,7 @@ void wrapStageCache() class_("StageCache") .def("Get", &UsdMayaStageCache::Get, - (args("forcePopulate") = true), + args("loadAll"), return_value_policy()) .staticmethod("Get") .def("Clear", &UsdMayaStageCache::Clear) diff --git a/lib/mayaUsd/utils/stageCache.cpp b/lib/mayaUsd/utils/stageCache.cpp index 4a707b338c..7d1eecac6b 100644 --- a/lib/mayaUsd/utils/stageCache.cpp +++ b/lib/mayaUsd/utils/stageCache.cpp @@ -61,13 +61,13 @@ struct _OnSceneResetListener : public TfWeakBase { /* static */ UsdStageCache& -UsdMayaStageCache::Get(const bool forcePopulate) +UsdMayaStageCache::Get(const bool loadAll) { - static UsdStageCache theCacheForcePopulate; - static UsdStageCache theCache; + static UsdStageCache theCacheLoadAll; // used when UsdStage::Open() will be called with UsdStage::InitialLoadSet::LoadAll + static UsdStageCache theCache; // used when UsdStage::Open() will be called with UsdStage::InitialLoadSet::LoadNode static _OnSceneResetListener onSceneResetListener; - return forcePopulate ? theCacheForcePopulate : theCache; + return loadAll ? theCacheLoadAll : theCache; } /* static */ diff --git a/lib/mayaUsd/utils/stageCache.h b/lib/mayaUsd/utils/stageCache.h index 897dc88507..3c61c5468b 100644 --- a/lib/mayaUsd/utils/stageCache.h +++ b/lib/mayaUsd/utils/stageCache.h @@ -34,7 +34,7 @@ class UsdMayaStageCache /// 2 stage caches are maintained; 1 for stages that have been /// force-populated, and 1 for stages that have not been force-populated. MAYAUSD_CORE_PUBLIC - static UsdStageCache& Get(const bool forcePopulate=true); + static UsdStageCache& Get(const bool loadAll); /// Clear the cache MAYAUSD_CORE_PUBLIC diff --git a/plugin/pxr/maya/lib/usdMaya/referenceAssembly.cpp b/plugin/pxr/maya/lib/usdMaya/referenceAssembly.cpp index 06252c3a69..bd1e06d73e 100644 --- a/plugin/pxr/maya/lib/usdMaya/referenceAssembly.cpp +++ b/plugin/pxr/maya/lib/usdMaya/referenceAssembly.cpp @@ -732,7 +732,8 @@ UsdMayaReferenceAssembly::computeInStageDataCached(MDataBlock& dataBlock) sessionLayer = unsharedSessionLayer; } - UsdStageCacheContext ctx(UsdMayaStageCache::Get()); + const bool loadAll = true; + UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadAll)); usdStage = UsdStage::Open(rootLayer, sessionLayer, ArGetResolver().GetCurrentContext()); @@ -899,7 +900,8 @@ UsdMayaReferenceAssembly::computeOutStageData(MDataBlock& dataBlock) sessionLayer->TransferContent(oldLayer); sessionLayer->TransferContent(newLayer); - UsdStageCacheContext ctx(UsdMayaStageCache::Get()); + const bool loadAll = true; + UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadAll)); usdStage = UsdStage::Open(usdPrim.GetStage()->GetRootLayer(), sessionLayer, ArGetResolver().GetCurrentContext()); diff --git a/plugin/pxr/maya/lib/usdMaya/translatorModelAssembly.cpp b/plugin/pxr/maya/lib/usdMaya/translatorModelAssembly.cpp index c90ba7ca48..7fe3ce67eb 100644 --- a/plugin/pxr/maya/lib/usdMaya/translatorModelAssembly.cpp +++ b/plugin/pxr/maya/lib/usdMaya/translatorModelAssembly.cpp @@ -375,7 +375,8 @@ UsdMayaTranslatorModelAssembly::Read( return false; } - UsdStageCacheContext stageCacheContext(UsdMayaStageCache::Get()); + const bool loadAll = true; + UsdStageCacheContext stageCacheContext(UsdMayaStageCache::Get(loadAll)); UsdStageRefPtr usdStage = UsdStage::Open(assetIdentifier); if (!usdStage) { TF_RUNTIME_ERROR("Cannot open USD file %s", assetIdentifier.c_str()); From 193aadb2723fd642e248df4490f7fbd11af83a4e Mon Sep 17 00:00:00 2001 From: krickw Date: Fri, 22 May 2020 11:13:13 -0400 Subject: [PATCH 2/4] Update python script that uses the stage cache. --- test/lib/testMayaUsdPythonImport.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/testMayaUsdPythonImport.py b/test/lib/testMayaUsdPythonImport.py index 4b038a4740..ca8b7caf62 100644 --- a/test/lib/testMayaUsdPythonImport.py +++ b/test/lib/testMayaUsdPythonImport.py @@ -32,5 +32,5 @@ def testImportModule(self): # mayaUsd library also loaded its dependencies (i.e. the core USD # libraries). We test the type name as a string to ensure that we're # not causing USD libraries to be loaded any other way. - stageCache = mayaUsdLib.StageCache.Get() + stageCache = mayaUsdLib.StageCache.Get(True) self.assertEqual(type(stageCache).__name__, 'StageCache') From 77acb553c4c640b4d3b9ce7149b5020a0144d41d Mon Sep 17 00:00:00 2001 From: krickw Date: Fri, 22 May 2020 14:39:09 -0400 Subject: [PATCH 3/4] Cleanup from the code review. Don't use the cache when creating anonymous layer. Improve documentation for UsdMayaStageCache. --- lib/mayaUsd/nodes/proxyShapeBase.cpp | 3 +-- lib/mayaUsd/utils/stageCache.h | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mayaUsd/nodes/proxyShapeBase.cpp b/lib/mayaUsd/nodes/proxyShapeBase.cpp index 189ee985ca..ea514ff900 100644 --- a/lib/mayaUsd/nodes/proxyShapeBase.cpp +++ b/lib/mayaUsd/nodes/proxyShapeBase.cpp @@ -496,9 +496,8 @@ MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock) usdStage->SetEditTarget(usdStage->GetSessionLayer()); } - else if (!usdStage) { + else { // Create a new stage in memory with an anonymous root layer. - UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadSet == UsdStage::InitialLoadSet::LoadAll)); usdStage = UsdStage::CreateInMemory("", loadSet); } diff --git a/lib/mayaUsd/utils/stageCache.h b/lib/mayaUsd/utils/stageCache.h index 3c61c5468b..7b32d5a157 100644 --- a/lib/mayaUsd/utils/stageCache.h +++ b/lib/mayaUsd/utils/stageCache.h @@ -31,8 +31,9 @@ class UsdMayaStageCache public: /// Return the singleton stage cache for use by all USD clients within Maya. - /// 2 stage caches are maintained; 1 for stages that have been - /// force-populated, and 1 for stages that have not been force-populated. + /// 2 stage caches are maintained; 1 for stages that have been opened with + /// UsdStage::InitialLoadSet::LoadAll, and 1 for stages that have been + /// opened with UsdStage::InitialLoadSet::LoadNode. MAYAUSD_CORE_PUBLIC static UsdStageCache& Get(const bool loadAll); From 4af6c19ba9a4e4984730ee096792d48d196b7b24 Mon Sep 17 00:00:00 2001 From: krickw Date: Tue, 26 May 2020 14:40:05 -0400 Subject: [PATCH 4/4] When opening or creating stages we must have a stage cache to hold a strong reference to the stage. --- lib/mayaUsd/nodes/proxyShapeBase.cpp | 41 ++++++++++++++++------------ lib/mayaUsd/nodes/stageData.h | 2 ++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/lib/mayaUsd/nodes/proxyShapeBase.cpp b/lib/mayaUsd/nodes/proxyShapeBase.cpp index ea514ff900..a3dbc4f070 100644 --- a/lib/mayaUsd/nodes/proxyShapeBase.cpp +++ b/lib/mayaUsd/nodes/proxyShapeBase.cpp @@ -480,25 +480,32 @@ MayaUsdProxyShapeBase::computeInStageDataCached(MDataBlock& dataBlock) loadSet = UsdStage::InitialLoadSet::LoadNone; } - if (SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(fileString)) { + { + // When opening or creating stages we must have an active UsdStageCache. + // The stage cache is the only one who holds a strong reference to the + // UsdStage. See https://github.com/Autodesk/maya-usd/issues/528 for + // more information. UsdStageCacheContext ctx(UsdMayaStageCache::Get(loadSet == UsdStage::InitialLoadSet::LoadAll)); - SdfLayerRefPtr sessionLayer = computeSessionLayer(dataBlock); - if (sessionLayer) { - usdStage = UsdStage::Open(rootLayer, - sessionLayer, - ArGetResolver().GetCurrentContext(), - loadSet); - } else { - usdStage = UsdStage::Open(rootLayer, - ArGetResolver().GetCurrentContext(), - loadSet); + + if (SdfLayerRefPtr rootLayer = SdfLayer::FindOrOpen(fileString)) { + SdfLayerRefPtr sessionLayer = computeSessionLayer(dataBlock); + if (sessionLayer) { + usdStage = UsdStage::Open(rootLayer, + sessionLayer, + ArGetResolver().GetCurrentContext(), + loadSet); + } else { + usdStage = UsdStage::Open(rootLayer, + ArGetResolver().GetCurrentContext(), + loadSet); + } + + usdStage->SetEditTarget(usdStage->GetSessionLayer()); + } + else { + // Create a new stage in memory with an anonymous root layer. + usdStage = UsdStage::CreateInMemory("", loadSet); } - - usdStage->SetEditTarget(usdStage->GetSessionLayer()); - } - else { - // Create a new stage in memory with an anonymous root layer. - usdStage = UsdStage::CreateInMemory("", loadSet); } if (usdStage) { diff --git a/lib/mayaUsd/nodes/stageData.h b/lib/mayaUsd/nodes/stageData.h index 015d54322e..da7f4edebe 100644 --- a/lib/mayaUsd/nodes/stageData.h +++ b/lib/mayaUsd/nodes/stageData.h @@ -104,6 +104,8 @@ class MayaUsdStageData : public MPxGeometryData // weak_ptr worked around this issue. Basically if we use a shared // pointer here, the only way to reload a scene, would be to restart // Maya." + // + // Logged as https://github.com/Autodesk/maya-usd/issues/528 UsdStageWeakPtr stage; SdfPath primPath;