Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
10.6.x.x (relative to 10.6.2.2)
========

Improvements
------------

- ShaderNetworkAlgo : Added render adaptor API, allowing just-in-time modifications to
ShaderNetworks during translation for rendering.

10.6.2.2
========

Expand Down
3 changes: 0 additions & 3 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,12 @@
#
##########################################################################

import SCons
import shutil
import glob
import sys
import os
import re
import subprocess
import platform
import distutils

EnsureSConsVersion( 3, 0, 2 ) # Substfile is a default builder as of 3.0.2
SConsignFile()
Expand Down
32 changes: 32 additions & 0 deletions include/IECoreScene/ShaderNetworkAlgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,38 @@ IECORESCENE_API IECore::ConstCompoundDataPtr collapseSplineParameters( const IEC
/// different spline conventions for different renderers' shader libraries
IECORESCENE_API IECore::ConstCompoundDataPtr expandSplineParameters( const IECore::ConstCompoundDataPtr& parametersData );

/// Render Adaptors
/// ===============
///
/// Render adaptors are functions called to make "just in time" modifications to
/// shader networks prior to rendering. They have access to a fully resolved
/// attribute state, which can be used to drive the modifications. There is currently
/// a single built-in adaptor, which uses `ShaderNetworkAlgo::applySubstitutions()`
/// to allow strings such as texture paths to be substituted in from attributes that
/// define them.
///
/// Adaptors are performance critical, so are deliberately not available via
/// the Python API. They must be implemented in C++ only.

/// A function that adapts the shader network for rendering, given the full
/// inherited `attributes` for an object. Must be threadsafe.
using RenderAdaptorFunction = void (*)( 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 an AdaptorFunction. Particular attention must be paid to
/// the performance of any such function, as it will be called frequently. If an
/// adaptor will be a no-op, then nothing should be appended to the hash.
/// Must be threadsafe.
using RenderAdaptorHashFunction = void (*)( const ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash );

/// Registers an adaptor.
IECORESCENE_API void registerRenderAdaptor( const std::string &name, RenderAdaptorHashFunction hashFunction, RenderAdaptorFunction adaptorFunction );
/// Removes a previously registered adaptor with the specified name.
IECORESCENE_API void deregisterRenderAdaptor( const std::string &name );

/// Hashes all the currently registered adaptors for `shaderNetwork`.
IECORESCENE_API void hashRenderAdaptors( const ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash );
/// Applies all the currently registered adaptors to `shaderNetwork`.
IECORESCENE_API void applyRenderAdaptors( ShaderNetwork *shaderNetwork, IECore::InternedString attributeName, const IECore::CompoundObject *attributes );

} // namespace ShaderNetworkAlgo

Expand Down
89 changes: 89 additions & 0 deletions src/IECoreScene/ShaderNetworkAlgo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1472,3 +1472,92 @@ IECore::ConstCompoundDataPtr ShaderNetworkAlgo::expandSplineParameters( const IE
return parametersData;
}
}


//////////////////////////////////////////////////////////////////////////
// Render Adaptors
//////////////////////////////////////////////////////////////////////////

namespace
{

struct RenderAdaptor
{
std::string name;
IECoreScene::ShaderNetworkAlgo::RenderAdaptorHashFunction hash;
IECoreScene::ShaderNetworkAlgo::RenderAdaptorFunction apply;
};

using RenderAdaptors = std::vector<RenderAdaptor>;
RenderAdaptors &renderAdaptors()
{
static RenderAdaptors g_renderAdaptors;
return g_renderAdaptors;
}

bool g_stringSubstitutionsRegistration = [] () {

IECoreScene::ShaderNetworkAlgo::registerRenderAdaptor(
"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

void ShaderNetworkAlgo::registerRenderAdaptor( const std::string &name, RenderAdaptorHashFunction hashFunction, RenderAdaptorFunction adaptorFunction )
{
// Replace existing adaptor if it exists.
RenderAdaptors &a = renderAdaptors();
for( auto &x : a )
{
if( x.name == name )
{
x.hash = hashFunction;
x.apply = adaptorFunction;
return;
}
}
// Otherwise add new adaptor.
a.push_back( { name, hashFunction, adaptorFunction } );
}

void ShaderNetworkAlgo::deregisterRenderAdaptor( const std::string &name )
{
RenderAdaptors &a = renderAdaptors();
a.erase(
std::remove_if(
a.begin(),
a.end(),
[&] ( const RenderAdaptor &x ) {
return x.name == name;
}
),
a.end()
);
}

void ShaderNetworkAlgo::hashRenderAdaptors( const IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes, IECore::MurmurHash &hash )
{
for( const auto &x : renderAdaptors() )
{
x.hash( shaderNetwork, attributeName, attributes, hash );
}
}

void ShaderNetworkAlgo::applyRenderAdaptors( IECoreScene::ShaderNetwork *shaderNetwork, InternedString attributeName, const IECore::CompoundObject *attributes )
{
for( const auto &x : renderAdaptors() )
{
x.apply( shaderNetwork, attributeName, attributes );
}
}