Beispiel #1
0
void VectorWarp::hashEngine( const Imath::V2i &tileOrigin, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	Warp::hashEngine( tileOrigin, context, h );

	h.append( tileOrigin );

	ConstStringVectorDataPtr channelNames;

	{
		ImagePlug::GlobalScope c( context );
		channelNames = vectorPlug()->channelNamesPlug()->getValue();
		vectorPlug()->dataWindowPlug()->hash( h );
		inPlug()->formatPlug()->hash( h );
	}


	ImagePlug::ChannelDataScope channelDataScope( context );

	if( ImageAlgo::channelExists( channelNames->readable(), "R" ) )
	{
		channelDataScope.setChannelName( "R" );
		vectorPlug()->channelDataPlug()->hash( h );
	}

	if( ImageAlgo::channelExists( channelNames->readable(), "G" ) )
	{
		channelDataScope.setChannelName( "G" );
		vectorPlug()->channelDataPlug()->hash( h );
	}

	if( ImageAlgo::channelExists( channelNames->readable(), "A" ) )
	{
		channelDataScope.setChannelName( "A" );
		vectorPlug()->channelDataPlug()->hash( h );
	}

	vectorModePlug()->hash( h );
	vectorUnitsPlug()->hash( h );
}
Beispiel #2
0
void CopyChannels::hashChannelData( const GafferImage::ImagePlug *parent, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	ConstCompoundObjectPtr mapping;
	{
		ImagePlug::GlobalScope c( context );
		mapping = mappingPlug()->getValue();
	}
	if( const IntData *i = mapping->member<const IntData>( context->get<string>( ImagePlug::channelNameContextName ) ) )
	{
		const ImagePlug *inputImage = inPlugs()->getChild<ImagePlug>( i->readable() );
		const V2i tileOrigin = context->get<V2i>( ImagePlug::tileOriginContextName );
		const Box2i tileBound( tileOrigin, tileOrigin + V2i( ImagePlug::tileSize() ) );

		Box2i inputDataWindow;
		{
			ImagePlug::GlobalScope c( context );
			inputDataWindow = inputImage->dataWindowPlug()->getValue();
		}

		const Box2i validBound = BufferAlgo::intersection( tileBound, inputDataWindow );
		if( validBound == tileBound )
		{
			h = inputImage->channelDataPlug()->hash();
		}
		else
		{
			ImageProcessor::hashChannelData( parent, context, h );
			if( !BufferAlgo::empty( validBound ) )
			{
				inputImage->channelDataPlug()->hash( h );
				h.append( BufferAlgo::intersection( inputDataWindow, tileBound ) );
			}
		}
	}
	else
	{
		h = ImagePlug::blackTile()->Object::hash();
	}
}
Beispiel #3
0
IECore::MurmurHash StringPlug::hash() const
{
	bool performSubstitution = direction()==Plug::In && !getInput<ValuePlug>() && Plug::getFlags( Plug::PerformsSubstitutions );
	if( performSubstitution )
	{
		IECore::ConstObjectPtr o = getObjectValue();
		const IECore::StringData *s = IECore::runTimeCast<const IECore::StringData>( o.get() );
		if( !s )
		{
			throw IECore::Exception( "StringPlug::getObjectValue() didn't return StringData - is the hash being computed correctly?" );
		}
		
		if( Context::hasSubstitutions( s->readable() ) )
		{
			IECore::MurmurHash result;
			result.append( Context::current()->substitute( s->readable() ) );
			return result;
		}
	}

	// no substitutions
	return ValuePlug::hash();
}
AtNode *InstancingConverter::convert( const IECore::Primitive *primitive, const IECore::MurmurHash &additionalHash )
{
	IECore::MurmurHash h = primitive->::IECore::Object::hash();
	h.append( additionalHash );

	MemberData::Cache::accessor a;
	if( m_data->cache.insert( a, h ) )
	{
		a->second = NodeAlgo::convert( primitive );
		return a->second;
	}
	else
	{
		if( a->second )
		{
			AtNode *instance = AiNode( "ginstance" );
			AiNodeSetPtr( instance, "node", a->second );
			return instance;
		}
	}

	return NULL;
}
Beispiel #5
0
void ImageStats::hash( const ValuePlug *output, const Context *context, IECore::MurmurHash &h ) const
{
	ComputeNode::hash( output, context, h);

	const int colorIndex = ::colorIndex( output );
	if( colorIndex == -1 )
	{
		// Not a plug we know about
		return;
	}

	const std::string channelName = this->channelName( colorIndex );
	const Imath::Box2i area = areaPlug()->getValue();

	if( channelName.empty() || BufferAlgo::empty( area ) )
	{
		h.append( static_cast<const FloatPlug *>( output )->defaultValue() );
		return;
	}

	Sampler s( inPlug(), channelName, area );
	s.hash( h );
}
Beispiel #6
0
void Grid::hashAttributes( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	Source::hashAttributes( path, context, parent, h );
	if( path.size() == 1 )
	{
		h.append( 1 );
	}
	else if( path.size() == 2 )
	{
		if( path.back() == g_gridLinesName )
		{
			gridPixelWidthPlug()->hash( h );
		}
		else if( path.back() == g_centerLinesName )
		{
			centerPixelWidthPlug()->hash( h );
		}
		else if( path.back() == g_borderLinesName )
		{
			borderPixelWidthPlug()->hash( h );
		}
	}
}
Beispiel #7
0
		IECore::MurmurHash contextHash( const Context *context, bool ignoreFrame = false ) const
		{
			IECore::MurmurHash result;
			std::vector<IECore::InternedString> names;
			context->names( names );
			for( std::vector<IECore::InternedString>::const_iterator it = names.begin(); it != names.end(); ++it )
			{
				// Ignore the UI values since they should be irrelevant
				// to execution.
				if( boost::starts_with( it->string(), "ui:" ) )
				{
					continue;
				}
				if( ignoreFrame && *it == g_frame )
				{
					continue;
				}

				result.append( *it );
				context->get<const IECore::Data>( *it )->hash( result );
			}
			return result;
		}
Beispiel #8
0
void ColorProcessor::hashChannelData( const GafferImage::ImagePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	const std::string &channels = channelsPlug()->getValue();
	const std::string &channel = context->get<std::string>( ImagePlug::channelNameContextName );
	const std::string &baseName = ImageAlgo::baseName( channel );

	if(
		( baseName != "R" && baseName != "G" && baseName != "B" ) ||
		!StringAlgo::matchMultiple( channel, channels )
	)
	{
		// Auxiliary channel, or not in channel mask. Pass through.
		h = inPlug()->channelDataPlug()->hash();
		return;
	}

	ImageProcessor::hashChannelData( output, context, h );
	h.append( baseName );
	{
		Context::EditableScope layerScope( context );
		layerScope.set( g_layerNameKey, ImageAlgo::layerName( channel ) );
		colorDataPlug()->hash( h );
	}
}
Beispiel #9
0
void Constant::hashDataWindow( const GafferImage::ImagePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	ImageNode::hashDataWindow( output, context, h );
	h.append( formatPlug()->hash() );
}
Beispiel #10
0
void Duplicate::hashBranchSet( const ScenePath &parentPath, const IECore::InternedString &setName, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	h.append( inPlug()->setHash( setName ) );
	targetPlug()->hash( h );
	childNamesPlug()->hash( h );
}
Beispiel #11
0
void AlembicSource::hashObject( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent, IECore::MurmurHash &h ) const
{
	FileSource::hashObject( path, context, parent, h );
	h.append( context->getFrame() );
}
Beispiel #12
0
void ValuePlug::hash( IECore::MurmurHash &h ) const
{
	h.append( hash() );
}
Beispiel #13
0
void ColorProcessor::hashChannelData( const GafferImage::ImagePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	ImageProcessor::hashChannelData( output, context, h );
	h.append( context->get<std::string>( ImagePlug::channelNameContextName ) );
	colorDataPlug()->hash( h );
}
Beispiel #14
0
void Mix::hashChannelData( const GafferImage::ImagePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	const float mix = mixPlug()->getValue();

	if( mix == 0.0f )
	{
		h = inPlugs()->getChild< ImagePlug >( 0 )->channelDataPlug()->hash();
		return;
	}
	else if( mix == 1.0f && !maskPlug()->getInput<ValuePlug>() )
	{
		h = inPlugs()->getChild< ImagePlug >( 1 )->channelDataPlug()->hash();
		return;
	}

	ImageProcessor::hashChannelData( output, context, h );
	h.append( mix );

	const std::string channelName = context->get<std::string>( ImagePlug::channelNameContextName );
	const V2i tileOrigin = context->get<V2i>( ImagePlug::tileOriginContextName );
	const Box2i tileBound( tileOrigin, tileOrigin + V2i( ImagePlug::tileSize() ) );


	for( ImagePlugIterator it( inPlugs() ); !it.done(); ++it )
	{
		if( !(*it)->getInput<ValuePlug>() )
		{
			continue;
		}

		IECore::ConstStringVectorDataPtr channelNamesData;
		Box2i dataWindow;
		{
			ImagePlug::GlobalScope c( Context::current() );
			channelNamesData = (*it)->channelNamesPlug()->getValue();
			dataWindow = (*it)->dataWindowPlug()->getValue();
		}

		const std::vector<std::string> &channelNames = channelNamesData->readable();

		if( ImageAlgo::channelExists( channelNames, channelName ) )
		{
			(*it)->channelDataPlug()->hash( h );
		}


		// The hash of the channel data we include above represents just the data in
		// the tile itself, and takes no account of the possibility that parts of the
		// tile may be outside of the data window. This simplifies the implementation of
		// nodes like Constant (where all tiles are identical, even the edge tiles) and
		// Crop (which does no processing of tiles at all). For most nodes this doesn't
		// matter, because they don't change the data window, or they use a Sampler to
		// deal with invalid pixels. But because our data window is the union of all
		// input data windows, we may be using/revealing the invalid parts of a tile. We
		// deal with this in computeChannelData() by treating the invalid parts as black,
		// and must therefore hash in the valid bound here to take that into account.
		const Box2i validBound = boxIntersection( tileBound, dataWindow );
		h.append( validBound );
	}

	IECore::ConstStringVectorDataPtr maskChannelNamesData;
	Box2i maskDataWindow;
	{
		ImagePlug::GlobalScope c( Context::current() );
		maskChannelNamesData = maskPlug()->channelNamesPlug()->getValue();
		maskDataWindow = maskPlug()->dataWindowPlug()->getValue();
	}


	const std::string &maskChannel = maskChannelPlug()->getValue();
	if( maskPlug()->getInput<ValuePlug>() && ImageAlgo::channelExists( maskChannelNamesData->readable(), maskChannel ) )
	{
		h.append( maskPlug()->channelDataHash( maskChannel, tileOrigin ) );
	}

	const Box2i maskValidBound = boxIntersection( tileBound, maskDataWindow );
	h.append( maskValidBound );
}
void IECoreArnold::RendererImplementation::addPrimitive( const IECore::Primitive *primitive, const std::string &attributePrefix )
{
	if( !m_motionTimes.empty() )
	{
		// We're in a motion block. Just store samples
		// until we have all of them.
		m_motionPrimitives.push_back( primitive );
		if( m_motionPrimitives.size() != m_motionTimes.size() )
		{
			return;
		}
	}

	const CompoundDataMap &attributes = m_attributeStack.top().attributes->readable();

	AtNode *shape = NULL;
	if( automaticInstancing() )
	{
		IECore::MurmurHash hash;
		for( CompoundDataMap::const_iterator it = attributes.begin(), eIt = attributes.end(); it != eIt; it++ )
		{
			if(
				boost::starts_with( it->first.value(), attributePrefix ) ||
				boost::starts_with( it->first.c_str(), "ai:shape:" )
			)
			{
				hash.append( it->first.value() );
				it->second->hash( hash );
			}
		}
		if( !m_motionTimes.empty() )
		{
			vector<const Primitive *> prims;
			for( vector<ConstPrimitivePtr>::const_iterator it = m_motionPrimitives.begin(), eIt = m_motionPrimitives.end(); it != eIt; ++it )
			{
				prims.push_back( it->get() );
			}
			shape = m_instancingConverter->convert( prims, m_motionTimes, hash );
		}
		else
		{
			shape = m_instancingConverter->convert( primitive, hash );
		}
	}
	else
	{
		if( !m_motionTimes.empty() )
		{
			vector<const Object *> prims;
			for( vector<ConstPrimitivePtr>::const_iterator it = m_motionPrimitives.begin(), eIt = m_motionPrimitives.end(); it != eIt; ++it )
			{
				prims.push_back( it->get() );
			}
			shape = NodeAlgo::convert( prims, m_motionTimes );
		}
		else
		{
			shape = NodeAlgo::convert( primitive );
		}
	}

	if( strcmp( AiNodeEntryGetName( AiNodeGetNodeEntry( shape ) ), "ginstance" ) )
	{
		// it's not an instance, copy over attributes destined for this object type.
		const CompoundDataMap &attributes = m_attributeStack.top().attributes->readable();
		for( CompoundDataMap::const_iterator it = attributes.begin(), eIt = attributes.end(); it != eIt; it++ )
		{
			if( boost::starts_with( it->first.value(), attributePrefix ) )
			{
				ParameterAlgo::setParameter( shape, it->first.value().c_str() + attributePrefix.size(), it->second.get() );
			}
			else if( boost::starts_with( it->first.c_str(), "ai:shape:" ) )
			{
				ParameterAlgo::setParameter( shape, it->first.value().c_str() + 9, it->second.get() );
			}
		}
	}
	else
	{
		// it's an instance - make sure we don't get double transformations.
		AiNodeSetBool( shape, "inherit_xform", false );
	}

	addShape( shape );
}
void CompoundObjectSource::hashSet( const IECore::InternedString &setName, const Gaffer::Context *context, const GafferScene::ScenePlug *parent, IECore::MurmurHash &h ) const
{
	SceneNode::hashSet( setName, context, parent, h );
	inPlug()->hash( h );
	h.append( setName );
}
Beispiel #17
0
void SceneNode::hash( const ValuePlug *output, const Context *context, IECore::MurmurHash &h ) const
{
	const ScenePlug *scenePlug = output->parent<ScenePlug>();
	if( scenePlug && enabledPlug()->getValue() )
	{
		// We don't call ComputeNode::hash() immediately here, because for subclasses which
		// want to pass through a specific hash in the hash*() methods it's a waste of time (the
		// hash will get overwritten anyway). Instead we call ComputeNode::hash() in our
		// hash*() implementations, and allow subclass implementations to not call the base class
		// if they intend to overwrite the hash.
		if( output == scenePlug->boundPlug() )
		{
			const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
			hashBound( scenePath, context, scenePlug, h );
		}
		else if( output == scenePlug->transformPlug() )
		{
			const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
			if( scenePath.empty() )
			{
				// the result of compute() will actually be different if we're at the root, so
				// we hash an identity M44fData:
				h.append( IECore::M44fData::staticTypeId() );
				h.append( Imath::M44f() );
			}
			else
			{
				hashTransform( scenePath, context, scenePlug, h );
			}
		}
		else if( output == scenePlug->attributesPlug() )
		{
			const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
			if( scenePath.empty() )
			{
				// the result of compute() will actually be different if we're at the root, so
				// we just hash the default value:
				scenePlug->attributesPlug()->defaultValue()->hash( h );
			}
			else
			{
				hashAttributes( scenePath, context, scenePlug, h );
			}
		}
		else if( output == scenePlug->objectPlug() )
		{
			const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
			if( scenePath.empty() )
			{
				// the result of compute() will actually be different if we're at the root, so
				// we just hash the default value:
				scenePlug->objectPlug()->defaultValue()->hash( h );
			}
			else
			{
				hashObject( scenePath, context, scenePlug, h );
			}
		}
		else if( output == scenePlug->childNamesPlug() )
		{
			const ScenePath &scenePath = context->get<ScenePath>( ScenePlug::scenePathContextName );
			hashChildNames( scenePath, context, scenePlug, h );
		}
		else if( output == scenePlug->globalsPlug() )
		{
			hashGlobals( context, scenePlug, h );
		}
		else if( output == scenePlug->setNamesPlug() )
		{
			hashSetNames( context, scenePlug, h );
		}
		else if( output == scenePlug->setPlug() )
		{
			const IECore::InternedString &setName = context->get<IECore::InternedString>( ScenePlug::setNameContextName );
			hashSet( setName, context, scenePlug, h );
		}
	}
	else
	{
		ComputeNode::hash( output, context, h );
	}
}
Beispiel #18
0
void CompoundDataPlug::hash( IECore::MurmurHash &h ) const
{
	h.append( hash() );
}
Beispiel #19
0
void Shader::stateHash( IECore::MurmurHash &h ) const
{
	h.append( stateHash() );
}
Beispiel #20
0
void ImageStats::hash( const ValuePlug *output, const Context *context, IECore::MurmurHash &h ) const
{
	ComputeNode::hash( output, context, h);

	bool earlyOut = true;
	for( int i = 0; i < 4; ++i )
	{
		if (
				output == minPlug()->getChild(i) ||
				output == maxPlug()->getChild(i) ||
				output == averagePlug()->getChild(i)
		   )
		{
			earlyOut = false;
			break;
		}
	}
	if( earlyOut )
	{
		return;
	}

	const Imath::Box2i regionOfInterest( regionOfInterestPlug()->getValue() );
	regionOfInterestPlug()->hash( h );
	inPlug()->channelNamesPlug()->hash( h );
	inPlug()->dataWindowPlug()->hash( h );

	IECore::ConstStringVectorDataPtr channelNamesData = inPlug()->channelNamesPlug()->getValue();
	std::vector<std::string> maskChannels = channelNamesData->readable();
	channelsPlug()->maskChannels( maskChannels );
	const int nChannels( maskChannels.size() );

	if ( nChannels > 0 )
	{
		std::vector<std::string> uniqueChannels = maskChannels;
		GafferImage::ChannelMaskPlug::removeDuplicateIndices( uniqueChannels );
		std::string channel;
		channelNameFromOutput( output, channel );

		if ( !channel.empty() )
		{
			h.append( channel );
			Sampler s( inPlug(), channel, regionOfInterest );
			s.hash( h );
			return;
		}
	}

	// If our node is not enabled then we just append the default value that we will give the plug.
	if(
			output == maxPlug()->getChild(3) ||
			output == minPlug()->getChild(3) ||
			output == averagePlug()->getChild(3)
	  )
	{
		h.append( 0 );
	}
	else
	{
		h.append( 1 );
	}
}
Beispiel #21
0
void OSLLight::hashAttributes( const SceneNode::ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent, IECore::MurmurHash &h ) const
{
	ObjectSource::hashAttributes( path, context, parent, h );
	h.append( shaderInPlug()->attributesHash() );
	attributesPlug()->hash( h );
}
void CompoundObjectSource::hashTransform( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent, IECore::MurmurHash &h ) const
{
	SceneNode::hashTransform( path, context, parent, h );
	h.append( &path.front(), path.size() );
	inPlug()->hash( h );
}
Beispiel #23
0
IECore::MurmurHash ImageWriter::executionHash( const Context *context ) const
{
	IECore::MurmurHash h = fileNamePlug()->hash();
	h.append( inPlug()->imageHash() );
	return h;
}
Beispiel #24
0
		static IECore::MurmurHash hash( const ValuePlug *plug )
		{
			const ValuePlug *p = sourcePlug( plug );

			if( const ValuePlug *input = p->getInput<ValuePlug>() )
			{
				// We know that the input is of a different type to the plug,
				// because that is guaranteed by sourcePlug(). Get the hash from
				// the input and add a little extra something to represent the
				// conversion that m_resultPlug->setFrom( input ) will perform,
				// to break apart the cache entries.
				IECore::MurmurHash h = input->hash();
				h.append( input->typeId() );
				h.append( plug->typeId() );
				return h;
			}
			else if( p->direction() == In || !p->ancestor<ComputeNode>() )
			{
				// No input connection, and no means of computing
				// a value. There can only ever be a single value,
				// which is stored directly on the plug - so we return
				// the hash of that.
				return p->m_staticValue->hash();
			}

			// A plug with an input connection or an output plug on a ComputeNode. There can be many values -
			// one per context, computed by ComputeNode::hash(). First we see if we can retrieve the hash
			// from our cache, and if we can't we'll compute it using a HashProcess instance.

			ThreadData &threadData = g_threadData.local();
			if( !Process::current() )
			{
				// Starting a new root computation.
				if( ++(threadData.cacheClearCount) == 3200 )
				{
					// Prevent unbounded growth in the hash cache
					// if many computations are being performed
					// without any plugs being dirtied in between,
					// by clearing it after every Nth computation.
					// N == 3200 was observed to be 6x faster than
					// N == 100 for a procedural instancing scene at
					// a memory cost of about 100 mb.
					threadData.clearCache = 1;
				}
			}

			if( threadData.clearCache )
			{
				threadData.cache.clear();
				threadData.cacheClearCount = 0;
				threadData.clearCache = 0;
			}

			const CacheKey key( p, Context::current()->hash() );
			Cache::iterator it = threadData.cache.find( key );
			if( it != threadData.cache.end() )
			{
				return it->second;
			}

			HashProcess process( p, plug );
			threadData.cache[key] = process.m_result;
			return process.m_result;
		}
Beispiel #25
0
IECore::MurmurHash TaskNode::hash( const Context *context ) const
{
	IECore::MurmurHash h;
	h.append( typeId() );
	return h;
}
Beispiel #26
0
void Seeds::hashBranchBound( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	BranchCreator::hashBranchBound( parentPath, branchPath, context, h );
	h.append( inPlug()->boundHash( parentPath ) );
}
Beispiel #27
0
/// \todo this hash needs to be smarter - it should detect if the scene cache is animated or not
void SceneReader::hash( const Gaffer::ValuePlug *output, const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
	FileSource::hash( output, context, h );
	h.append( context->getFrame() / g_frameRate );
}