4141
4242#include " IECoreScene/ShaderNetwork.h"
4343
44+ #include " IECore/LRUCache.h"
4445#include " IECore/MessageHandler.h"
4546#include " IECore/SimpleTypedData.h"
4647#include " IECore/VectorTypedData.h"
@@ -393,6 +394,62 @@ void populateMaterial( pxr::UsdShadeMaterial &mat, const std::map< const Interne
393394 }
394395}
395396
397+ // / SdfPath is the appropriate cache key for _storage_, but we need a
398+ // / `UsdShadeOutput` for computation. This struct provides the implicit
399+ // / conversion that LRUCache needs to make that possible.
400+ struct ShaderNetworkCacheGetterKey : public pxr ::UsdShadeOutput
401+ {
402+ ShaderNetworkCacheGetterKey ( const pxr::UsdShadeOutput &output )
403+ : pxr::UsdShadeOutput( output )
404+ {
405+ }
406+
407+ operator pxr::SdfPath () const
408+ {
409+ return GetAttr ().GetPath ();
410+ }
411+ };
412+
413+ class ShaderNetworkCache : public LRUCache <pxr::SdfPath, IECoreScene::ConstShaderNetworkPtr, LRUCachePolicy::Parallel, ShaderNetworkCacheGetterKey>
414+ {
415+
416+ public :
417+
418+ ShaderNetworkCache ( size_t maxBytes )
419+ : LRUCache<pxr::SdfPath, IECoreScene::ConstShaderNetworkPtr, LRUCachePolicy::Parallel, ShaderNetworkCacheGetterKey>( getter, maxBytes )
420+ {
421+ }
422+
423+ private :
424+
425+ static IECoreScene::ConstShaderNetworkPtr getter ( const ShaderNetworkCacheGetterKey &key, size_t &cost )
426+ {
427+ IECoreScene::ConstShaderNetworkPtr result;
428+
429+ // / \todo I'm pretty sure that the `readShaderNetwork()` signature is overly complex,
430+ // / and it should just be passed a single `UsdShadeOutput &` like this function.
431+ // / I suspect that `writeShaderNetwork()` could take a single `UsdShadeOutput &` too,
432+ // / for symmetry between the two functions.
433+
434+ pxr::UsdShadeConnectableAPI source;
435+ pxr::TfToken sourceName;
436+ pxr::UsdShadeAttributeType sourceType;
437+ if ( key.GetConnectedSource ( &source, &sourceName, &sourceType ) )
438+ {
439+ pxr::UsdShadeShader s ( source.GetPrim () );
440+ result = ShaderAlgo::readShaderNetwork ( source.GetPrim ().GetParent ().GetPath (), s, sourceName );
441+ }
442+ else
443+ {
444+ result = new IECoreScene::ShaderNetwork ();
445+ }
446+
447+ cost = result->Object ::memoryUsage ();
448+ return result;
449+ }
450+
451+ };
452+
396453} // namespace
397454
398455class USDScene ::Location : public RefCounted
@@ -408,31 +465,16 @@ class USDScene::IO : public RefCounted
408465 public :
409466
410467 IO ( const std::string &fileName, IndexedIO::OpenMode openMode )
411- : m_fileName ( fileName ), m_openMode( openMode )
468+ : IO( fileName, makeStage ( fileName, openMode ), openMode )
412469 {
413- switch ( m_openMode )
414- {
415- case IndexedIO::Read :
416- m_stage = pxr::UsdStage::Open ( fileName );
417- if ( !m_stage )
418- {
419- throw IECore::Exception ( boost::str ( boost::format ( " USDScene : Failed to open USD file: '%1%'" ) % fileName ) );
420- }
421- break ;
422- case IndexedIO::Write :
423- m_stage = pxr::UsdStage::CreateNew ( fileName );
424- break ;
425- default :
426- throw Exception ( " Unsupported OpenMode" );
427- }
428-
429- initStage ();
430470 }
431471
432- IO ( const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
433- : m_fileName( " " ), m_openMode( openMode ), m_stage( stage )
472+ IO ( const std::string &fileName, const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
473+ : m_fileName( fileName ), m_openMode( openMode ), m_stage( stage ),
474+ m_rootPrim ( m_stage->GetPseudoRoot () ),
475+ m_timeCodesPerSecond( m_stage->GetTimeCodesPerSecond () ),
476+ m_shaderNetworkCache( 10 * 1024 * 1024 ) // 10Mb
434477 {
435- initStage ();
436478 }
437479
438480 ~IO () override
@@ -447,12 +489,6 @@ class USDScene::IO : public RefCounted
447489 }
448490 }
449491
450- void initStage ()
451- {
452- m_timeCodesPerSecond = m_stage->GetTimeCodesPerSecond ();
453- m_rootPrim = m_stage->GetPseudoRoot ();
454- }
455-
456492 const std::string &fileName () const
457493 {
458494 return m_fileName;
@@ -515,8 +551,32 @@ class USDScene::IO : public RefCounted
515551 );
516552 }
517553
554+ IECoreScene::ConstShaderNetworkPtr readShaderNetwork ( const pxr::UsdShadeOutput &output )
555+ {
556+ return m_shaderNetworkCache.get ( output );
557+ }
558+
518559 private :
519560
561+ static pxr::UsdStageRefPtr makeStage ( const std::string &fileName, IndexedIO::OpenMode openMode )
562+ {
563+ switch ( openMode )
564+ {
565+ case IndexedIO::Read : {
566+ pxr::UsdStageRefPtr stage = pxr::UsdStage::Open ( fileName );
567+ if ( !stage )
568+ {
569+ throw IECore::Exception ( boost::str ( boost::format ( " USDScene : Failed to open USD file: '%1%'" ) % fileName ) );
570+ }
571+ return stage;
572+ }
573+ case IndexedIO::Write :
574+ return pxr::UsdStage::CreateNew ( fileName );
575+ default :
576+ throw Exception ( " Unsupported OpenMode" );
577+ }
578+ }
579+
520580 std::string m_fileName;
521581 IndexedIO::OpenMode m_openMode;
522582 pxr::UsdStageRefPtr m_stage;
@@ -529,6 +589,8 @@ class USDScene::IO : public RefCounted
529589 pxr::UsdShadeMaterialBindingAPI::BindingsCache m_usdBindingsCache;
530590 pxr::UsdShadeMaterialBindingAPI::CollectionQueryCache m_usdCollectionQueryCache;
531591
592+ ShaderNetworkCache m_shaderNetworkCache;
593+
532594};
533595
534596USDScene::USDScene ( const std::string &fileName, IndexedIO::OpenMode openMode )
@@ -538,7 +600,7 @@ USDScene::USDScene( const std::string &fileName, IndexedIO::OpenMode openMode )
538600}
539601
540602USDScene::USDScene ( const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
541- : m_root( new IO( stage, openMode ) ),
603+ : m_root( new IO( " " , stage, openMode ) ),
542604 m_location( new Location( m_root->root () ) )
543605{
544606}
@@ -917,17 +979,7 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
917979 pxr::UsdShadeOutput o = mat.GetOutput ( n );
918980 if ( o && pxr::UsdAttribute ( o ).IsAuthored () )
919981 {
920- {
921- pxr::UsdShadeConnectableAPI source;
922- pxr::TfToken sourceName;
923- pxr::UsdShadeAttributeType sourceType;
924- if ( o.GetConnectedSource ( &source, &sourceName, &sourceType ) )
925- {
926- pxr::UsdShadeShader s ( source.GetPrim () );
927- return ShaderAlgo::readShaderNetwork ( source.GetPrim ().GetParent ().GetPath (), s, sourceName );
928- }
929- }
930- return new IECoreScene::ShaderNetwork ();
982+ return m_root->readShaderNetwork ( o );
931983 }
932984 }
933985 }
0 commit comments