Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parallelised SceneNode child bound computations. #4

Closed
wants to merge 1 commit into from
Closed
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
156 changes: 127 additions & 29 deletions src/GafferScene/SceneNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@
//
//////////////////////////////////////////////////////////////////////////

#include "tbb/parallel_reduce.h"
#include "tbb/blocked_range.h"

#include "Gaffer/Context.h"

#include "GafferScene/SceneNode.h"

using namespace std;
using namespace tbb;
using namespace Imath;
using namespace IECore;
using namespace GafferScene;
Expand Down Expand Up @@ -342,6 +346,61 @@ GafferScene::ConstPathMatcherDataPtr SceneNode::computeSet( const IECore::Intern
throw IECore::NotImplementedException( string( typeName() ) + "::computeSet" );
}

namespace
{

struct BoundHash
{

BoundHash( const ScenePlug::ScenePath &path, const vector<InternedString> &childNames, const ScenePlug *scene, const Context *context )
: m_path( path ), m_childNames( childNames ), m_scene( scene ), m_context( context )
{
}

BoundHash( const BoundHash &rhs, split )
: m_path( rhs.m_path ), m_childNames( rhs.m_childNames ), m_scene( rhs.m_scene ), m_context( rhs.m_context ), m_hash()
{
}

void operator() ( const blocked_range<size_t> &r )
{
ContextPtr context = new Context( *m_context, Context::Borrowed );
Context::Scope scopedContext( context.get() );

ScenePlug::ScenePath childPath( m_path );
childPath.push_back( InternedString() ); // room for the child name

for( size_t i=r.begin(); i!=r.end(); ++i )
{
childPath.back() = m_childNames[i];
context->set( ScenePlug::scenePathContextName, childPath );
m_scene->boundPlug()->hash( m_hash );
m_scene->transformPlug()->hash( m_hash );
}
}

void join( const BoundHash &rhs )
{
m_hash.append( rhs.m_hash );
}

const MurmurHash &result()
{
return m_hash;
}

private :

const ScenePlug::ScenePath &m_path;
const vector<InternedString> &m_childNames;
const ScenePlug *m_scene;
const Context *m_context;
MurmurHash m_hash;

};

} // namespace

IECore::MurmurHash SceneNode::hashOfTransformedChildBounds( const ScenePath &path, const ScenePlug *out, const IECore::InternedStringVectorData *childNamesData ) const
{
ConstInternedStringVectorDataPtr computedChildNames;
Expand All @@ -355,18 +414,12 @@ IECore::MurmurHash SceneNode::hashOfTransformedChildBounds( const ScenePath &pat
IECore::MurmurHash result;
if( childNames.size() )
{
ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed );
Context::Scope scopedContext( tmpContext.get() );

ScenePath childPath( path );
childPath.push_back( InternedString() ); // room for the child name
for( vector<InternedString>::const_iterator it = childNames.begin(); it != childNames.end(); it++ )
{
childPath[path.size()] = *it;
tmpContext->set( ScenePlug::scenePathContextName, childPath );
out->boundPlug()->hash( result );
out->transformPlug()->hash( result );
}
BoundHash hasher( path, childNames, out, Context::current() );
parallel_deterministic_reduce(
blocked_range<size_t>( 0, childNames.size(), 10 ),
hasher
);
result = hasher.result();
}
else
{
Expand All @@ -376,6 +429,62 @@ IECore::MurmurHash SceneNode::hashOfTransformedChildBounds( const ScenePath &pat
return result;
}

namespace
{

struct BoundUnion
{

BoundUnion( const ScenePlug::ScenePath &path, const vector<InternedString> &childNames, const ScenePlug *scene, const Context *context )
: m_path( path ), m_childNames( childNames ), m_scene( scene ), m_context( context )
{
}

BoundUnion( const BoundUnion &rhs, split )
: m_path( rhs.m_path ), m_childNames( rhs.m_childNames ), m_scene( rhs.m_scene ), m_context( rhs.m_context )
{
}

void operator() ( const blocked_range<size_t> &r )
{
ContextPtr context = new Context( *m_context, Context::Borrowed );
Context::Scope scopedContext( context.get() );

ScenePlug::ScenePath childPath( m_path );
childPath.push_back( InternedString() ); // room for the child name

for( size_t i=r.begin(); i!=r.end(); ++i )
{
childPath.back() = m_childNames[i];
context->set( ScenePlug::scenePathContextName, childPath );
Box3f childBound = m_scene->boundPlug()->getValue();
childBound = transform( childBound, m_scene->transformPlug()->getValue() );
m_union.extendBy( childBound );
}
}

void join( const BoundUnion &rhs )
{
m_union.extendBy( rhs.m_union );
}

const Box3f &result()
{
return m_union;
}

private :

const ScenePlug::ScenePath &m_path;
const vector<InternedString> &m_childNames;
const ScenePlug *m_scene;
const Context *m_context;
Box3f m_union;

};

} // namespace

Imath::Box3f SceneNode::unionOfTransformedChildBounds( const ScenePath &path, const ScenePlug *out, const IECore::InternedStringVectorData *childNamesData ) const
{
ConstInternedStringVectorDataPtr computedChildNames;
Expand All @@ -386,22 +495,11 @@ Imath::Box3f SceneNode::unionOfTransformedChildBounds( const ScenePath &path, co
}
const vector<InternedString> &childNames = childNamesData->readable();

Box3f result;
if( childNames.size() )
{
ContextPtr tmpContext = new Context( *Context::current(), Context::Borrowed );
Context::Scope scopedContext( tmpContext.get() );
BoundUnion unioner( path, childNames, out, Context::current() );
parallel_reduce(
blocked_range<size_t>( 0, childNames.size() ),
unioner
);

ScenePath childPath( path );
childPath.push_back( InternedString() ); // room for the child name
for( vector<InternedString>::const_iterator it = childNames.begin(); it != childNames.end(); it++ )
{
childPath[path.size()] = *it;
tmpContext->set( ScenePlug::scenePathContextName, childPath );
Box3f childBound = out->boundPlug()->getValue();
childBound = transform( childBound, out->transformPlug()->getValue() );
result.extendBy( childBound );
}
}
return result;
return unioner.result();
}