diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 13409e9f189..48033a2ab4b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -73,7 +73,7 @@ jobs: testRunner: sudo -E -u testUser sconsCacheMegabytes: 400 jobs: 4 - dependenciesURL: https://github.com/ImageEngine/cortex/releases/download/10.5.15.3/cortex-10.5.15.3-linux-gcc11.tar.gz + dependenciesURL: https://github.com/ImageEngine/cortex/releases/download/10.5.16.0/cortex-10.5.16.0-linux-gcc11.tar.gz - name: windows os: windows-2022 diff --git a/.github/workflows/main/installDependencies.py b/.github/workflows/main/installDependencies.py index bf5e91ea03c..f06bc2cccab 100755 --- a/.github/workflows/main/installDependencies.py +++ b/.github/workflows/main/installDependencies.py @@ -49,7 +49,7 @@ # Determine default archive URL. -defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.6.2.1/cortex-10.6.2.1-{platform}{buildEnvironment}.{extension}" +defaultURL = "https://github.com/ImageEngine/cortex/releases/download/10.6.3.0/cortex-10.6.3.0-{platform}{buildEnvironment}.{extension}" # Parse command line arguments. diff --git a/Changes.md b/Changes.md index 25333d2c2e6..2b581661377 100644 --- a/Changes.md +++ b/Changes.md @@ -4,7 +4,9 @@ Improvements ------------ -- RenderMan : Added support for PxrLayer, PxrLayerMixer and PxrLayerSurface shaders (by implementing support for vstruct conditionals). +- RenderMan : + - Added support for PxrLayer, PxrLayerMixer and PxrLayerSurface shaders (by implementing support for vstruct conditionals). + - Added support for `IECoreScene::ShaderNetworkAlgo` render adaptor API. Fixes ----- @@ -12,6 +14,16 @@ Fixes - RenderMan : Fixed interactive denoising when rendering via the `it` display driver. - EditScopeUI : Fixed crash if `childNodesAreReadOnly` metadata was edited while no EditScope was selected. +API +--- + +- Arnold ShaderNetworkAlgo : Deprecated substitutions API. Use IECoreScene's render adaptor API instead. For backwards compatibility until it is removed, the substitutions API forwards to the render adaptor API. + +Build +----- + +- Cortex : Updated to version 10.6.3.0. + 1.6.8.0 (relative to 1.6.7.0) ======= diff --git a/include/IECoreArnold/ShaderNetworkAlgo.h b/include/IECoreArnold/ShaderNetworkAlgo.h index 13294fb1dca..9b16575636b 100644 --- a/include/IECoreArnold/ShaderNetworkAlgo.h +++ b/include/IECoreArnold/ShaderNetworkAlgo.h @@ -96,25 +96,21 @@ IECOREARNOLD_API bool update( std::vector &nodes, const IECoreScene::S /// tests. IECOREARNOLD_API void convertUSDShaders( IECoreScene::ShaderNetwork *shaderNetwork ); -/// A function that performs substitutions on a shader network, given the full -/// inherited `attributes` for an object. Must be threadsafe. +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::RenderAdaptorFunction` instead. using SubstitutionFunction = void (*)( IECoreScene::ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ); -/// A function that appends to `hash` to uniquely identify the work that will be -/// performed by a SubstitutionFunction. Particular attention must be paid to -/// the performance of any such function, as it will be called frequently. If a -/// substitution will be a no-op, then nothing should be appended to the hash. -/// Must be threadsafe. +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::RenderAdaptorHashFunction` instead. using SubstitutionHashFunction = void (*)( const IECoreScene::ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash ); -/// Registers a just-in-time substitution to be performed on shader -/// networks before the shader is translated to Arnold. +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::registerRenderAdaptor()` instead. IECOREARNOLD_API void registerSubstitution( const std::string &name, SubstitutionHashFunction hashFunction, SubstitutionFunction substitutionFunction ); -/// Removes a previously registered substitution with the specified name. + +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::deregisterRenderAdaptor()` instead. IECOREARNOLD_API void deregisterSubstitution( const std::string &name ); -/// Hashes all the currently registered substitutions for `shaderNetwork`. +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::hasRenderAdaptors()` instead. IECOREARNOLD_API void hashSubstitutions( const IECoreScene::ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash ); -/// Applies all the currently registered substitutions to `shaderNetwork`. + +/// \deprecated Use `IECoreScene::ShaderNetworkAlgo::applyRenderAdaptors()` instead. IECOREARNOLD_API void applySubstitutions( IECoreScene::ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ); } // namespace ShaderNetworkAlgo diff --git a/src/IECoreArnold/Renderer.cpp b/src/IECoreArnold/Renderer.cpp index 275e7a069ed..3909e7bfd31 100644 --- a/src/IECoreArnold/Renderer.cpp +++ b/src/IECoreArnold/Renderer.cpp @@ -49,6 +49,7 @@ #include "IECoreScene/MeshPrimitive.h" #include "IECoreScene/PointsPrimitive.h" #include "IECoreScene/Shader.h" +#include "IECoreScene/ShaderNetworkAlgo.h" #include "IECoreScene/SpherePrimitive.h" #include "IECoreVDB/VDBObject.h" @@ -1059,11 +1060,11 @@ class ShaderCache : public IECore::RefCounted ArnoldShaderPtr get( const IECoreScene::ShaderNetwork *shader, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ) { IECore::MurmurHash h = shader->Object::hash(); - IECore::MurmurHash hSubst; + IECore::MurmurHash hAdapted; if( attributes ) { - ShaderNetworkAlgo::hashSubstitutions( shader, attributeName, attributes, hSubst ); - h.append( hSubst ); + IECoreScene::ShaderNetworkAlgo::hashRenderAdaptors( shader, attributeName, attributes, hAdapted ); + h.append( hAdapted ); } Cache::const_accessor readAccessor; @@ -1076,11 +1077,11 @@ class ShaderCache : public IECore::RefCounted if( m_cache.insert( writeAccessor, h ) ) { const std::string nameFormat = "shader:{shaderHandle}:" + writeAccessor->first.toString(); - if( hSubst != IECore::MurmurHash() ) + if( hAdapted != IECore::MurmurHash() ) { - IECoreScene::ShaderNetworkPtr substitutedShader = shader->copy(); - ShaderNetworkAlgo::applySubstitutions( substitutedShader.get(), attributeName, attributes ); - writeAccessor->second = new ArnoldShader( substitutedShader.get(), m_nodeDeleter, m_universe, nameFormat, m_parentNode ); + IECoreScene::ShaderNetworkPtr adaptedShader = shader->copy(); + IECoreScene::ShaderNetworkAlgo::applyRenderAdaptors( adaptedShader.get(), attributeName, attributes ); + writeAccessor->second = new ArnoldShader( adaptedShader.get(), m_nodeDeleter, m_universe, nameFormat, m_parentNode ); } else { diff --git a/src/IECoreArnold/ShaderNetworkAlgo.cpp b/src/IECoreArnold/ShaderNetworkAlgo.cpp index f392ea489d8..b1e7942559f 100644 --- a/src/IECoreArnold/ShaderNetworkAlgo.cpp +++ b/src/IECoreArnold/ShaderNetworkAlgo.cpp @@ -1161,91 +1161,27 @@ void IECoreArnold::ShaderNetworkAlgo::convertUSDShaders( ShaderNetwork *shaderNe // Substitutions ////////////////////////////////////////////////////////////////////////// -namespace -{ - -struct Substitution -{ - std::string name; - IECoreArnold::ShaderNetworkAlgo::SubstitutionHashFunction hash; - IECoreArnold::ShaderNetworkAlgo::SubstitutionFunction apply; -}; - -using Substitutions = std::vector; -Substitutions &substitutions() -{ - static Substitutions g_substitutions; - return g_substitutions; -} - -bool g_textureSubstitutionsRegistration = [] () { - - IECoreArnold::ShaderNetworkAlgo::registerSubstitution( - "stringSubstitution", - // Hash - [] ( const IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash ) { - shaderNetwork->hashSubstitutions( attributes, hash ); - }, - // Apply - [] ( IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes ) { - shaderNetwork->applySubstitutions( attributes ); - } - ); - - return true; -} (); - -} // namespace - namespace IECoreArnold::ShaderNetworkAlgo { void registerSubstitution( const std::string &name, SubstitutionHashFunction hashFunction, SubstitutionFunction substitutionFunction ) { - // Replace existing substitution if it exists. - Substitutions &s = substitutions(); - for( auto &x : s ) - { - if( x.name == name ) - { - x.hash = hashFunction; - x.apply = substitutionFunction; - return; - } - } - // Otherwise add new substitution. - s.push_back( { name, hashFunction, substitutionFunction } ); + IECoreScene::ShaderNetworkAlgo::registerRenderAdaptor( name, hashFunction, substitutionFunction ); } void deregisterSubstitution( const std::string &name ) { - Substitutions &s = substitutions(); - s.erase( - std::remove_if( - s.begin(), - s.end(), - [&] ( const Substitution &x ) { - return x.name == name; - } - ), - s.end() - ); + IECoreScene::ShaderNetworkAlgo::deregisterRenderAdaptor( name ); } void hashSubstitutions( const IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash ) { - for( const auto &x : substitutions() ) - { - x.hash( shaderNetwork, attributeName, attributes, hash ); - } + IECoreScene::ShaderNetworkAlgo::hashRenderAdaptors( shaderNetwork, attributeName, attributes, hash ); } void applySubstitutions( IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes ) { - for( const auto &x : substitutions() ) - { - x.apply( shaderNetwork, attributeName, attributes ); - } + IECoreScene::ShaderNetworkAlgo::applyRenderAdaptors( shaderNetwork, attributeName, attributes ); } } // namespace IECoreArnold::ShaderNetworkAlgo diff --git a/src/IECoreRenderMan/Attributes.cpp b/src/IECoreRenderMan/Attributes.cpp index 9f4db85668c..c91b5b7dc3e 100644 --- a/src/IECoreRenderMan/Attributes.cpp +++ b/src/IECoreRenderMan/Attributes.cpp @@ -110,18 +110,15 @@ boost::container::flat_map g_prototypeAttributes = { const string g_renderManPrefix( "ri:" ); const IECore::InternedString g_automaticInstancingAttributeName( "gaffer:automaticInstancing" ); -const InternedString g_displacementAttributeName( "displacement" ); const InternedString g_doubleSidedAttributeName( "doubleSided" ); const InternedString g_lightMuteAttributeName( "light:mute" ); -const InternedString g_lightShaderAttributeName( "light" ); -const InternedString g_oslDisplacementAttributeName( "osl:displacement" ); -const InternedString g_renderManDisplacementAttributeName( "ri:displacement" ); -const InternedString g_renderManLightShaderAttributeName( "ri:light" ); -const InternedString g_renderManSurfaceAttributeName( "ri:surface" ); const InternedString g_renderManLightFilterAttributeName( "ri:lightFilter" ); -const InternedString g_surfaceAttributeName( "surface" ); const RtUString g_userMaterialId( "user:__materialid" ); +const vector g_displacementAttributeNames = { "ri:displacement", "osl:displacement", "displacement" }; +const vector g_lightAttributeNames = { "ri:light", "light" }; +const vector g_surfaceAttributeNames = { "ri:surface", "surface" }; + template T *attributeCast( const IECore::RunTimeTyped *v, const IECore::InternedString &name ) { @@ -168,6 +165,18 @@ T attributeValue( const CompoundObject::ObjectMap &attributes, IECore::InternedS return data ? data->readable() : defaultValue; } +pair shaderNetworkAttribute( const CompoundObject::ObjectMap &attributes, const vector &attributeNames ) +{ + for( const auto &name : attributeNames ) + { + if( const auto *shaderNetwork = attribute( attributes, name ) ) + { + return { name, shaderNetwork }; + } + } + return { InternedString(), nullptr }; +} + bool isMeshLight( const IECoreScene::ShaderNetwork *lightShader ) { const IECoreScene::Shader *outputShader = lightShader->outputShader(); @@ -217,26 +226,22 @@ Attributes::Attributes( const IECore::CompoundObject *attributes, MaterialCache { // Convert shaders. - const ShaderNetwork *surface = attribute( attributes->members(), g_renderManSurfaceAttributeName ); - surface = surface ? surface : attribute( attributes->members(), g_surfaceAttributeName ); - m_surfaceMaterial = materialCache->getMaterial( surface ? surface : g_facingRatio.get(), attributes ); + const auto [surfaceName, surface] = shaderNetworkAttribute( attributes->members(), g_surfaceAttributeNames ); + m_surfaceMaterial = materialCache->getMaterial( surface ? surface : g_facingRatio.get(), surface ? surfaceName : InternedString(), attributes ); - const ShaderNetwork *displacement = attribute( attributes->members(), g_renderManDisplacementAttributeName ); - displacement = displacement ? displacement : attribute( attributes->members(), g_oslDisplacementAttributeName ); - displacement = displacement ? displacement : attribute( attributes->members(), g_displacementAttributeName ); + const auto [displacementName, displacement] = shaderNetworkAttribute( attributes->members(), g_displacementAttributeNames ); if( displacement ) { - m_displacement = materialCache->getDisplacement( displacement, attributes ); + m_displacement = materialCache->getDisplacement( displacement, displacementName, attributes ); } - m_lightShader = attribute( attributes->members(), g_renderManLightShaderAttributeName ); - m_lightShader = m_lightShader ? m_lightShader : attribute( attributes->members(), g_lightShaderAttributeName ); + m_lightShader = shaderNetworkAttribute( attributes->members(), g_lightAttributeNames ).second; if( m_lightShader && isMeshLight( m_lightShader.get() ) ) { // Mesh lights default to having a black material so they don't appear // in indirect rays, but the user can override with a surface assignment // if they want further control. Other lights don't have materials. - m_lightMaterial = materialCache->getMaterial( surface ? surface : g_black.get(), attributes ); + m_lightMaterial = materialCache->getMaterial( surface ? surface : g_black.get(), surface ? surfaceName : InternedString(), attributes ); } if( surface ) diff --git a/src/IECoreRenderMan/MaterialCache.cpp b/src/IECoreRenderMan/MaterialCache.cpp index 22eef880536..375e046d0c2 100644 --- a/src/IECoreRenderMan/MaterialCache.cpp +++ b/src/IECoreRenderMan/MaterialCache.cpp @@ -36,6 +36,8 @@ #include "MaterialCache.h" +#include "IECoreScene/ShaderNetworkAlgo.h" + #include "IECoreRenderMan/ShaderNetworkAlgo.h" using namespace std; @@ -55,23 +57,23 @@ MaterialCache::MaterialCache( Session *session ) { } -ConstMaterialPtr MaterialCache::getMaterial( const IECoreScene::ShaderNetwork *network, const IECore::CompoundObject *attributes ) +ConstMaterialPtr MaterialCache::getMaterial( const IECoreScene::ShaderNetwork *network, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ) { IECore::MurmurHash hash = network->Object::hash(); - IECore::MurmurHash substitutionsHash; - network->hashSubstitutions( attributes, substitutionsHash ); - hash.append( substitutionsHash ); + IECore::MurmurHash adaptorHash; + IECoreScene::ShaderNetworkAlgo::hashRenderAdaptors( network, attributeName, attributes, adaptorHash ); + hash.append( adaptorHash ); Cache::accessor a; m_cache.insert( a, hash ); if( !a->second ) { - IECoreScene::ShaderNetworkPtr substitutedNetwork; - if( substitutionsHash != IECore::MurmurHash() ) + IECoreScene::ShaderNetworkPtr adaptedNetwork; + if( adaptorHash != IECore::MurmurHash() ) { - substitutedNetwork = network->copy(); - substitutedNetwork->applySubstitutions( attributes ); - network = substitutedNetwork.get(); + adaptedNetwork = network->copy(); + IECoreScene::ShaderNetworkAlgo::applyRenderAdaptors( adaptedNetwork.get(), attributeName, attributes ); + network = adaptedNetwork.get(); } std::vector nodes = ShaderNetworkAlgo::convert( network ); @@ -81,23 +83,23 @@ ConstMaterialPtr MaterialCache::getMaterial( const IECoreScene::ShaderNetwork *n return a->second; } -ConstDisplacementPtr MaterialCache::getDisplacement( const IECoreScene::ShaderNetwork *network, const IECore::CompoundObject *attributes ) +ConstDisplacementPtr MaterialCache::getDisplacement( const IECoreScene::ShaderNetwork *network, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ) { IECore::MurmurHash hash = network->Object::hash(); - IECore::MurmurHash substitutionsHash; - network->hashSubstitutions( attributes, substitutionsHash ); - hash.append( substitutionsHash ); + IECore::MurmurHash adaptorHash; + IECoreScene::ShaderNetworkAlgo::hashRenderAdaptors( network, attributeName, attributes, adaptorHash ); + hash.append( adaptorHash ); DisplacementCache::accessor a; m_displacementCache.insert( a, hash ); if( !a->second ) { - IECoreScene::ShaderNetworkPtr substitutedNetwork; - if( substitutionsHash != IECore::MurmurHash() ) + IECoreScene::ShaderNetworkPtr adaptedNetwork; + if( adaptorHash != IECore::MurmurHash() ) { - substitutedNetwork = network->copy(); - substitutedNetwork->applySubstitutions( attributes ); - network = substitutedNetwork.get(); + adaptedNetwork = network->copy(); + IECoreScene::ShaderNetworkAlgo::applyRenderAdaptors( adaptedNetwork.get(), attributeName, attributes ); + network = adaptedNetwork.get(); } std::vector nodes = ShaderNetworkAlgo::convert( network ); diff --git a/src/IECoreRenderMan/MaterialCache.h b/src/IECoreRenderMan/MaterialCache.h index 7da82afbae2..e972c8b936e 100644 --- a/src/IECoreRenderMan/MaterialCache.h +++ b/src/IECoreRenderMan/MaterialCache.h @@ -63,8 +63,8 @@ class MaterialCache MaterialCache( Session *session ); // Can be called concurrently with other calls to `get()` - ConstMaterialPtr getMaterial( const IECoreScene::ShaderNetwork *network, const IECore::CompoundObject *attributes ); - ConstDisplacementPtr getDisplacement( const IECoreScene::ShaderNetwork *network, const IECore::CompoundObject *attributes ); + ConstMaterialPtr getMaterial( const IECoreScene::ShaderNetwork *network, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ); + ConstDisplacementPtr getDisplacement( const IECoreScene::ShaderNetwork *network, IECore::InternedString attributeName, const IECore::CompoundObject *attributes ); ConstLightShaderPtr getLightShader( const IECoreScene::ShaderNetwork *network, const IECoreScene::ShaderNetwork *lightFilter, RtUString shadowSubset ); // Must not be called concurrently with anything.