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"
@@ -389,6 +390,62 @@ void populateMaterial( pxr::UsdShadeMaterial &mat, const std::map< const Interne
389390 }
390391}
391392
393+ // / SdfPath is the appropriate cache key for _storage_, but we need a
394+ // / `UsdShadeOutput` for computation. This struct provides the implicit
395+ // / conversion that LRUCache needs to make that possible.
396+ struct ShaderNetworkCacheGetterKey : public pxr ::UsdShadeOutput
397+ {
398+ ShaderNetworkCacheGetterKey ( const pxr::UsdShadeOutput &output )
399+ : pxr::UsdShadeOutput( output )
400+ {
401+ }
402+
403+ operator pxr::SdfPath () const
404+ {
405+ return GetAttr ().GetPath ();
406+ }
407+ };
408+
409+ class ShaderNetworkCache : public LRUCache <pxr::SdfPath, IECoreScene::ConstShaderNetworkPtr, LRUCachePolicy::Parallel, ShaderNetworkCacheGetterKey>
410+ {
411+
412+ public :
413+
414+ ShaderNetworkCache ( size_t maxBytes )
415+ : LRUCache<pxr::SdfPath, IECoreScene::ConstShaderNetworkPtr, LRUCachePolicy::Parallel, ShaderNetworkCacheGetterKey>( getter, maxBytes )
416+ {
417+ }
418+
419+ private :
420+
421+ static IECoreScene::ConstShaderNetworkPtr getter ( const ShaderNetworkCacheGetterKey &key, size_t &cost )
422+ {
423+ IECoreScene::ConstShaderNetworkPtr result;
424+
425+ // / \todo I'm pretty sure that the `readShaderNetwork()` signature is overly complex,
426+ // / and it should just be passed a single `UsdShadeOutput &` like this function.
427+ // / I suspect that `writeShaderNetwork()` could take a single `UsdShadeOutput &` too,
428+ // / for symmetry between the two functions.
429+
430+ pxr::UsdShadeConnectableAPI source;
431+ pxr::TfToken sourceName;
432+ pxr::UsdShadeAttributeType sourceType;
433+ if ( key.GetConnectedSource ( &source, &sourceName, &sourceType ) )
434+ {
435+ pxr::UsdShadeShader s ( source.GetPrim () );
436+ result = ShaderAlgo::readShaderNetwork ( source.GetPrim ().GetParent ().GetPath (), s, sourceName );
437+ }
438+ else
439+ {
440+ result = new IECoreScene::ShaderNetwork ();
441+ }
442+
443+ cost = result->Object ::memoryUsage ();
444+ return result;
445+ }
446+
447+ };
448+
392449} // namespace
393450
394451class USDScene ::Location : public RefCounted
@@ -404,31 +461,16 @@ class USDScene::IO : public RefCounted
404461 public :
405462
406463 IO ( const std::string &fileName, IndexedIO::OpenMode openMode )
407- : m_fileName ( fileName ), m_openMode( openMode )
464+ : IO( fileName, makeStage ( fileName, openMode ), openMode )
408465 {
409- switch ( m_openMode )
410- {
411- case IndexedIO::Read :
412- m_stage = pxr::UsdStage::Open ( fileName );
413- if ( !m_stage )
414- {
415- throw IECore::Exception ( boost::str ( boost::format ( " USDScene : Failed to open USD file: '%1%'" ) % fileName ) );
416- }
417- break ;
418- case IndexedIO::Write :
419- m_stage = pxr::UsdStage::CreateNew ( fileName );
420- break ;
421- default :
422- throw Exception ( " Unsupported OpenMode" );
423- }
424-
425- initStage ();
426466 }
427467
428- IO ( const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
429- : m_fileName( " " ), m_openMode( openMode ), m_stage( stage )
468+ IO ( const std::string &fileName, const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
469+ : m_fileName( fileName ), m_openMode( openMode ), m_stage( stage ),
470+ m_rootPrim ( m_stage->GetPseudoRoot () ),
471+ m_timeCodesPerSecond( m_stage->GetTimeCodesPerSecond () ),
472+ m_shaderNetworkCache( 10 * 1024 * 1024 ) // 10Mb
430473 {
431- initStage ();
432474 }
433475
434476 ~IO () override
@@ -443,12 +485,6 @@ class USDScene::IO : public RefCounted
443485 }
444486 }
445487
446- void initStage ()
447- {
448- m_timeCodesPerSecond = m_stage->GetTimeCodesPerSecond ();
449- m_rootPrim = m_stage->GetPseudoRoot ();
450- }
451-
452488 const std::string &fileName () const
453489 {
454490 return m_fileName;
@@ -511,8 +547,32 @@ class USDScene::IO : public RefCounted
511547 );
512548 }
513549
550+ IECoreScene::ConstShaderNetworkPtr readShaderNetwork ( const pxr::UsdShadeOutput &output )
551+ {
552+ return m_shaderNetworkCache.get ( output );
553+ }
554+
514555 private :
515556
557+ static pxr::UsdStageRefPtr makeStage ( const std::string &fileName, IndexedIO::OpenMode openMode )
558+ {
559+ switch ( openMode )
560+ {
561+ case IndexedIO::Read : {
562+ pxr::UsdStageRefPtr stage = pxr::UsdStage::Open ( fileName );
563+ if ( !stage )
564+ {
565+ throw IECore::Exception ( boost::str ( boost::format ( " USDScene : Failed to open USD file: '%1%'" ) % fileName ) );
566+ }
567+ return stage;
568+ }
569+ case IndexedIO::Write :
570+ return pxr::UsdStage::CreateNew ( fileName );
571+ default :
572+ throw Exception ( " Unsupported OpenMode" );
573+ }
574+ }
575+
516576 std::string m_fileName;
517577 IndexedIO::OpenMode m_openMode;
518578 pxr::UsdStageRefPtr m_stage;
@@ -525,6 +585,8 @@ class USDScene::IO : public RefCounted
525585 pxr::UsdShadeMaterialBindingAPI::BindingsCache m_usdBindingsCache;
526586 pxr::UsdShadeMaterialBindingAPI::CollectionQueryCache m_usdCollectionQueryCache;
527587
588+ ShaderNetworkCache m_shaderNetworkCache;
589+
528590};
529591
530592USDScene::USDScene ( const std::string &fileName, IndexedIO::OpenMode openMode )
@@ -534,7 +596,7 @@ USDScene::USDScene( const std::string &fileName, IndexedIO::OpenMode openMode )
534596}
535597
536598USDScene::USDScene ( const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode )
537- : m_root( new IO( stage, openMode ) ),
599+ : m_root( new IO( " " , stage, openMode ) ),
538600 m_location( new Location( m_root->root () ) )
539601{
540602}
@@ -913,17 +975,7 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
913975 pxr::UsdShadeOutput o = mat.GetOutput ( n );
914976 if ( o && pxr::UsdAttribute ( o ).IsAuthored () )
915977 {
916- {
917- pxr::UsdShadeConnectableAPI source;
918- pxr::TfToken sourceName;
919- pxr::UsdShadeAttributeType sourceType;
920- if ( o.GetConnectedSource ( &source, &sourceName, &sourceType ) )
921- {
922- pxr::UsdShadeShader s ( source.GetPrim () );
923- return ShaderAlgo::readShaderNetwork ( source.GetPrim ().GetParent ().GetPath (), s, sourceName );
924- }
925- }
926- return new IECoreScene::ShaderNetwork ();
978+ return m_root->readShaderNetwork ( o );
927979 }
928980 }
929981 }
0 commit comments