static MurmurHash hashFn( const ComputeParameters ¶ms ) { const std::string &filePath = params.first; MurmurHash h; h.append( filePath ); return h; }
OP_ERROR SOP_SceneCacheSource::cookMySop( OP_Context &context ) { flags().setTimeDep( true ); std::string file; if ( !ensureFile( file ) ) { addError( SOP_ATTRIBUTE_INVALID, ( file + " is not a valid .scc" ).c_str() ); gdp->clearAndDestroy(); return error(); } std::string path = getPath(); Space space = getSpace(); UT_String shapeFilterStr; evalString( shapeFilterStr, pShapeFilter.getToken(), 0, 0 ); UT_StringMMPattern shapeFilter; shapeFilter.compile( shapeFilterStr ); UT_String p( "P" ); UT_String attributeFilter; evalString( attributeFilter, pAttributeFilter.getToken(), 0, 0 ); if ( !p.match( attributeFilter ) ) { attributeFilter += " P"; } ConstSceneInterfacePtr scene = this->scene( file, path ); if ( !scene ) { addError( SOP_ATTRIBUTE_INVALID, ( path + " is not a valid location in " + file ).c_str() ); gdp->clearAndDestroy(); return error(); } MurmurHash hash; hash.append( file ); hash.append( path ); hash.append( space ); hash.append( shapeFilterStr ); hash.append( attributeFilter ); if ( !m_loaded || m_hash != hash ) { gdp->clearAndDestroy(); } Imath::M44d transform = ( space == World ) ? worldTransform( file, path, context.getTime() ) : Imath::M44d(); SceneInterface::Path rootPath; scene->path( rootPath ); loadObjects( scene, transform, context.getTime(), space, shapeFilter, attributeFilter.toStdString(), rootPath.size() ); m_loaded = true; m_hash = hash; return error(); }
static MurmurHash hash( const ComputationParams ¶ms ) { int id = params; MurmurHash h; h.append(id); return h; }
IECore::MurmurHash Dispatcher::batchHash( const ExecutableNode::Task &task ) { MurmurHash result; result.append( (uint64_t)task.node() ); if ( task.hash() == MurmurHash() ) { return result; } const Context *context = task.context(); std::vector<IECore::InternedString> names; context->names( names ); for ( std::vector<IECore::InternedString>::const_iterator it = names.begin(); it != names.end(); ++it ) { // ignore the frame and the ui values if ( ( *it != g_frame ) && it->string().compare( 0, 3, "ui:" ) ) { result.append( *it ); if ( const IECore::Data *data = context->get<const IECore::Data>( *it ) ) { data->hash( result ); } } } return result; }
IECore::MurmurHash ImagePlug::imageHash() const { const Box2i dataWindow = dataWindowPlug()->getValue(); ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue(); const vector<string> &channelNames = channelNamesData->readable(); MurmurHash result = formatPlug()->hash(); result.append( dataWindowPlug()->hash() ); result.append( metadataPlug()->hash() ); result.append( channelNamesPlug()->hash() ); V2i minTileOrigin = tileOrigin( dataWindow.min ); V2i maxTileOrigin = tileOrigin( dataWindow.max ); ContextPtr context = new Context( *Context::current(), Context::Borrowed ); Context::Scope scope( context.get() ); for( vector<string>::const_iterator it = channelNames.begin(), eIt = channelNames.end(); it!=eIt; it++ ) { context->set( ImagePlug::channelNameContextName, *it ); for( int tileOriginY = minTileOrigin.y; tileOriginY<=maxTileOrigin.y; tileOriginY += tileSize() ) { for( int tileOriginX = minTileOrigin.x; tileOriginX<=maxTileOrigin.x; tileOriginX += tileSize() ) { context->set( ImagePlug::tileOriginContextName, V2i( tileOriginX, tileOriginY ) ); channelDataPlug()->hash( result ); } } } return result; }
IECore::MurmurHash ImagePlug::imageHash() const { const Box2i dataWindow = dataWindowPlug()->getValue(); ConstStringVectorDataPtr channelNamesData = channelNamesPlug()->getValue(); const vector<string> &channelNames = channelNamesData->readable(); MurmurHash result = formatPlug()->hash(); result.append( dataWindowPlug()->hash() ); result.append( metadataPlug()->hash() ); result.append( channelNamesPlug()->hash() ); ImageAlgo::parallelGatherTiles( this, channelNames, // Tile [] ( const ImagePlug *imagePlug, const string &channelName, const V2i &tileOrigin ) { return imagePlug->channelDataPlug()->hash(); }, // Gather [ &result ] ( const ImagePlug *imagePlug, const string &channelName, const V2i &tileOrigin, const IECore::MurmurHash &tileHash ) { result.append( tileHash ); }, dataWindow, ImageAlgo::BottomToTop ); return result; }
void SimpleDataHolder<Format>::hash( MurmurHash &h ) const { Format f = readable(); h.append( f.getDisplayWindow().min ); h.append( f.getDisplayWindow().max ); h.append( f.getPixelAspect() ); }
MurmurHash ExecutableNode::Task::hash() const { MurmurHash h; const Node *nodePtr = node.get(); h.append( (const char *)nodePtr, sizeof(Node*) ); h.append( context->hash() ); return h; }
void Display::hash( MurmurHash &h ) const { PreWorldRenderable::hash( h ); h.append( m_name ); h.append( m_type ); h.append( m_data ); m_parameters->hash( h ); }
void CurvesPrimitive::topologyHash( MurmurHash &h ) const { h.append( m_basis.matrix ); h.append( m_basis.step ); h.append( m_linear ); h.append( m_periodic ); m_vertsPerCurve->hash( h ); }
void MatrixMotionTransform::hash( MurmurHash &h ) const { Transform::hash( h ); for( SnapshotMap::const_iterator it=m_snapshots.begin(); it!=m_snapshots.end(); it++ ) { h.append( it->first ); h.append( it->second ); } }
// Hash used to determine how to coalesce tasks into batches. // If `batchHash( task1 ) == batchHash( task2 )` then the two // tasks can be placed in the same batch. IECore::MurmurHash batchHash( const TaskNode::Task &task ) { MurmurHash result; result.append( (uint64_t)task.node() ); // We ignore the frame because the whole point of batching // is to allow multiple frames to be placed in the same // batch if the context is otherwise identical. result.append( contextHash( task.context(), /* ignoreFrame = */ true ) ); return result; }
MurmurHash Renderer::ExternalProcedural::hash() const { MurmurHash h; h.append( m_fileName ); for( CompoundDataMap::const_iterator it = m_parameters.begin(), eIt = m_parameters.end(); it != eIt; ++it ) { h.append( it->first ); it->second->hash( h ); } return h; }
void NURBSPrimitive::topologyHash( MurmurHash &h ) const { h.append( m_uOrder ); m_uKnot->hash( h ); h.append( m_uMin ); h.append( m_uMax ); h.append( m_vOrder ); m_vKnot->hash( h ); h.append( m_vMin ); h.append( m_vMax ); }
void Primitive::hash( MurmurHash &h ) const { VisibleRenderable::hash( h ); for( PrimitiveVariableMap::const_iterator it=variables.begin(); it!=variables.end(); it++ ) { h.append( it->first ); h.append( it->second.interpolation ); it->second.data->hash( h ); } topologyHash( h ); }
Dispatcher::TaskBatchPtr Dispatcher::acquireBatch( const ExecutableNode::Task &task, BatchMap ¤tBatches, TaskToBatchMap &tasksToBatches ) { MurmurHash taskToBatchMapHash = task.hash(); taskToBatchMapHash.append( (uint64_t)task.node() ); TaskToBatchMap::iterator it = tasksToBatches.find( taskToBatchMapHash ); if ( it != tasksToBatches.end() ) { return it->second; } MurmurHash batchMapHash = batchHash( task ); BatchMap::iterator bIt = currentBatches.find( batchMapHash ); if ( bIt != currentBatches.end() ) { TaskBatchPtr batch = bIt->second; std::vector<float> &frames = batch->frames(); const Plug *dispatcherPlug = task.node()->dispatcherPlug(); const IntPlug *batchSizePlug = dispatcherPlug->getChild<const IntPlug>( g_batchSize ); size_t batchSize = ( batchSizePlug ) ? batchSizePlug->getValue() : 1; if ( task.node()->requiresSequenceExecution() || ( frames.size() < batchSize ) ) { if ( task.hash() != MurmurHash() ) { float frame = task.context()->getFrame(); if ( std::find( frames.begin(), frames.end(), frame ) == frames.end() ) { if ( task.node()->requiresSequenceExecution() ) { frames.insert( std::lower_bound( frames.begin(), frames.end(), frame ), frame ); } else { frames.push_back( frame ); } } } tasksToBatches[taskToBatchMapHash] = batch; return batch; } } TaskBatchPtr batch = new TaskBatch( task ); currentBatches[batchMapHash] = batch; tasksToBatches[taskToBatchMapHash] = batch; return batch; }
void SimpleDataHolder<CompoundDataMap>::hash( MurmurHash &h ) const { // the CompoundDataMap is sorted by InternedString::operator <, // which just compares addresses of the underlying interned object. // this isn't stable between multiple processes. const CompoundDataMap &m = readable(); std::vector<CompoundDataMap::const_iterator> iterators; iterators.reserve( m.size() ); for( CompoundDataMap::const_iterator it=m.begin(); it!=m.end(); it++ ) { iterators.push_back( it ); } // so we have to sort again based on the string values // themselves. sort( iterators.begin(), iterators.end(), comp ); // and then hash everything in the stable order. std::vector<CompoundDataMap::const_iterator>::const_iterator it; for( it=iterators.begin(); it!=iterators.end(); it++ ) { if ( !((*it)->second) ) { throw Exception( "Cannot compute hash from a CompoundData will NULL data pointers!" ); } h.append( (*it)->first.value() ); (*it)->second->hash( h ); } }
void Shader::hash( MurmurHash &h ) const { StateRenderable::hash( h ); h.append( m_name ); h.append( m_type ); m_parameters->hash( h ); }
asf::auto_release_ptr<asr::Object> IECoreAppleseed::BatchPrimitiveConverter::doConvertPrimitive( PrimitivePtr primitive, const string &name ) { MurmurHash primitiveHash; primitiveHash.append( name ); primitive->hash( primitiveHash ); if( primitive->typeId() == MeshPrimitiveTypeId ) { // Check if we already have a mesh saved for this object. string fileName = string( "_geometry/" ) + primitiveHash.toString() + m_meshGeomExtension; filesystem::path p = m_projectPath / fileName; if( !filesystem::exists( p ) ) { ToAppleseedConverterPtr converter = ToAppleseedConverter::create( primitive.get() ); if( !converter ) { msg( Msg::Warning, "IECoreAppleseed::BatchPrimitiveConverter", "Couldn't convert primitive." ); return asf::auto_release_ptr<asr::Object>(); } asf::auto_release_ptr<asr::Object> entity; entity.reset( static_cast<asr::Object*>( converter->convert() ) ); if( entity.get() == 0 ) { msg( Msg::Warning, "IECoreAppleseed::BatchPrimitiveConverter", "Couldn't convert primitive." ); return asf::auto_release_ptr<asr::Object>(); } // Write the mesh to a file. p = m_projectPath / fileName; if( !asr::MeshObjectWriter::write( static_cast<const asr::MeshObject&>( *entity ), name.c_str(), p.string().c_str() ) ) { msg( Msg::Warning, "IECoreAppleseed::BatchPrimitiveConverter", "Couldn't save mesh primitive." ); return asf::auto_release_ptr<asr::Object>(); } } asf::auto_release_ptr<asr::MeshObject> meshObj( asr::MeshObjectFactory().create( name.c_str(), asr::ParamArray().insert( "filename", fileName.c_str() ) ) ); return asf::auto_release_ptr<asr::Object>( meshObj.release() ); } return asf::auto_release_ptr<asr::Object>(); }
void MotionPrimitive::hash( MurmurHash &h ) const { VisibleRenderable::hash( h ); for( SnapshotMap::const_iterator it=m_snapshots.begin(); it!=m_snapshots.end(); it++ ) { h.append( it->first ); it->second->hash( h ); } }
void SetVisualiser::hashProcessedAttributes( const ScenePath &path, const Gaffer::Context *context, MurmurHash &h ) const { ConstCompoundDataPtr outSetsData = outSetsPlug()->getValue(); outSetsData->hash( h ); includeInheritedPlug()->hash( h ); // We also need to consider each of our candidate sets membership // definition (which we didn't need to when computing outSets). // outSetsData is map of names -> colors. ConstInternedStringVectorDataPtr setNames = outSetsData->member<InternedStringVectorData>( "names" ); for( auto &setName : setNames->readable() ) { h.append( inPlug()->setHash( setName ) ); } h.append( path.data(), path.size() ); stripeWidthPlug()->hash( h ); }
void SetVisualiser::hash( const ValuePlug *output, const Context *context, MurmurHash &h ) const { SceneElementProcessor::hash( output, context, h ); if( output == outSetsPlug() ) { setsPlug()->hash( h ); colorOverridesPlug()->hash( h ); // We don't care about a set's hash here as we're only computing which // sets we will consider and their corresponding colors - which depends // solely on their names. h.append( inPlug()->setNamesHash() ); } }
void ObjectVector::hash( MurmurHash &h ) const { Object::hash( h ); for( MemberContainer::const_iterator it=m_members.begin(); it!=m_members.end(); it++ ) { if( *it ) { (*it)->hash( h ); } else { h.append( 0 ); } } }
// Hash used to determine how to coalesce tasks into batches. // If `batchHash( task1 ) == batchHash( task2 )` then the two // tasks can be placed in the same batch. IECore::MurmurHash batchHash( const TaskNode::Task &task ) { MurmurHash result; result.append( (uint64_t)task.node() ); const Context *context = task.context(); 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( it->string().compare( 0, 3, "ui:" ) == 0 ) { continue; } // Ignore the frame, since the whole point of batching // is to allow multiple frames to be placed in the same // batch if the context is otherwise identical. /// // There is one exception to this though - if the task is // a no-op, then we don't want to coalesce, because then // every single frame of the no-op would be placed in the // same batch, and all downstream frames would then be forced // to depend unnecessarily on all upstream frames. if( *it == g_frame && task.hash() != MurmurHash() ) { continue; } result.append( *it ); context->get<const IECore::Data>( *it )->hash( result ); } return result; }
OP_ERROR SOP_SceneCacheSource::cookMySop( OP_Context &context ) { // make sure the state is valid if ( boost::indeterminate( m_static ) ) { sceneChanged(); } flags().setTimeDep( bool( !m_static ) ); std::string file; if ( !ensureFile( file ) ) { addError( SOP_ATTRIBUTE_INVALID, ( file + " is not a valid .scc" ).c_str() ); gdp->clearAndDestroy(); return error(); } std::string path = getPath(); Space space = getSpace(); GeometryType geometryType = (GeometryType)this->evalInt( pGeometryType.getToken(), 0, 0 ); UT_String tagFilterStr; getTagFilter( tagFilterStr ); UT_StringMMPattern tagFilter; tagFilter.compile( tagFilterStr ); UT_String shapeFilterStr; getShapeFilter( shapeFilterStr ); UT_StringMMPattern shapeFilter; shapeFilter.compile( shapeFilterStr ); UT_String p( "P" ); UT_String attributeFilter; getAttributeFilter( attributeFilter ); if ( !p.match( attributeFilter ) ) { attributeFilter += " P"; } UT_String attributeCopy; getAttributeCopy( attributeCopy ); UT_String fullPathName; getFullPathName( fullPathName ); ConstSceneInterfacePtr scene = this->scene( file, path ); if ( !scene ) { addError( SOP_ATTRIBUTE_INVALID, ( path + " is not a valid location in " + file ).c_str() ); gdp->clearAndDestroy(); return error(); } MurmurHash hash; hash.append( file ); hash.append( path ); hash.append( space ); hash.append( tagFilterStr ); hash.append( shapeFilterStr ); hash.append( attributeFilter ); hash.append( attributeCopy ); hash.append( fullPathName ); hash.append( geometryType ); hash.append( getObjectOnly() ); if ( !m_loaded || m_hash != hash ) { gdp->clearAndDestroy(); } double readTime = time( context ); Imath::M44d transform = ( space == World ) ? worldTransform( file, path, readTime ) : Imath::M44d(); SceneInterface::Path rootPath; scene->path( rootPath ); UT_Interrupt *progress = UTgetInterrupt(); if ( !progress->opStart( ( "Cooking objects for " + getPath() ).c_str() ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted before it started" ); gdp->clearAndDestroy(); return error(); } Parameters params; UT_String attribFilter; getAttributeFilter( attribFilter ); params.attributeFilter = attribFilter.toStdString(); params.attributeCopy = attributeCopy.toStdString(); params.fullPathName = fullPathName.toStdString(); params.geometryType = getGeometryType(); getShapeFilter( params.shapeFilter ); getTagFilter( params.tagFilter ); // Building a map from shape name to primitive range, which will be used during // convertObject() to do a lazy update of animated primvars where possible, and // to destroy changing topology shapes when necessary. GA_ROAttributeRef nameAttrRef = gdp->findStringTuple( GA_ATTRIB_PRIMITIVE, "name" ); if ( nameAttrRef.isValid() ) { const GA_Attribute *attr = nameAttrRef.getAttribute(); const GA_AIFSharedStringTuple *tuple = attr->getAIFSharedStringTuple(); std::map<std::string, GA_OffsetList> offsets; GA_Range primRange = gdp->getPrimitiveRange(); for ( GA_Iterator it = primRange.begin(); !it.atEnd(); ++it ) { std::string current = ""; if ( const char *value = tuple->getString( attr, it.getOffset() ) ) { current = value; } std::map<std::string, GA_OffsetList>::iterator oIt = offsets.find( current ); if ( oIt == offsets.end() ) { oIt = offsets.insert( std::pair<std::string, GA_OffsetList>( current, GA_OffsetList() ) ).first; } oIt->second.append( it.getOffset() ); } for ( std::map<std::string, GA_OffsetList>::iterator oIt = offsets.begin(); oIt != offsets.end(); ++oIt ) { params.namedRanges[oIt->first] = GA_Range( gdp->getPrimitiveMap(), oIt->second ); } } loadObjects( scene.get(), transform, readTime, space, params, rootPath.size() ); if ( progress->opInterrupt( 100 ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted" ); gdp->clearAndDestroy(); m_loaded = false; m_hash = MurmurHash(); } else { m_loaded = true; m_hash = hash; } progress->opEnd(); return error(); }
void SimpleDataHolder<TimePeriod>::hash( MurmurHash &h ) const { h.append( boost::posix_time::to_iso_string( readable().begin() ) ); h.append( boost::posix_time::to_iso_string( readable().end() ) ); }
void IECoreAppleseed::ShadingState::materialHash( MurmurHash &hash ) const { shaderGroupHash( hash ); hash.append( m_shadingSamples ); }
OP_ERROR SOP_SceneCacheSource::cookMySop( OP_Context &context ) { // make sure the state is valid if ( boost::indeterminate( m_static ) ) { sceneChanged(); } flags().setTimeDep( bool( !m_static ) ); std::string file; if ( !ensureFile( file ) ) { addError( SOP_ATTRIBUTE_INVALID, ( file + " is not a valid .scc" ).c_str() ); gdp->clearAndDestroy(); return error(); } std::string path = getPath(); Space space = getSpace(); GeometryType geometryType = (GeometryType)this->evalInt( pGeometryType.getToken(), 0, 0 ); UT_String shapeFilterStr; evalString( shapeFilterStr, pShapeFilter.getToken(), 0, 0 ); UT_StringMMPattern shapeFilter; shapeFilter.compile( shapeFilterStr ); UT_String p( "P" ); UT_String attributeFilter; evalString( attributeFilter, pAttributeFilter.getToken(), 0, 0 ); if ( !p.match( attributeFilter ) ) { attributeFilter += " P"; } ConstSceneInterfacePtr scene = this->scene( file, path ); if ( !scene ) { addError( SOP_ATTRIBUTE_INVALID, ( path + " is not a valid location in " + file ).c_str() ); gdp->clearAndDestroy(); return error(); } MurmurHash hash; hash.append( file ); hash.append( path ); hash.append( space ); hash.append( shapeFilterStr ); hash.append( attributeFilter ); hash.append( geometryType ); hash.append( getObjectOnly() ); if ( !m_loaded || m_hash != hash ) { gdp->clearAndDestroy(); } Imath::M44d transform = ( space == World ) ? worldTransform( file, path, context.getTime() ) : Imath::M44d(); SceneInterface::Path rootPath; scene->path( rootPath ); UT_Interrupt *progress = UTgetInterrupt(); if ( !progress->opStart( ( "Cooking objects for " + getPath() ).c_str() ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted before it started" ); gdp->clearAndDestroy(); return error(); } loadObjects( scene, transform, context.getTime(), space, shapeFilter, attributeFilter.toStdString(), geometryType, rootPath.size() ); if ( progress->opInterrupt( 100 ) ) { addError( SOP_ATTRIBUTE_INVALID, "Cooking interrupted" ); gdp->clearAndDestroy(); m_loaded = false; m_hash = MurmurHash(); } else { m_loaded = true; m_hash = hash; } progress->opEnd(); return error(); }
void ImagePrimitive::topologyHash( MurmurHash &h ) const { h.append( m_dataWindow ); h.append( m_displayWindow ); }
void SimpleDataHolder<Imf::TimeCode>::hash( MurmurHash &h ) const { const Imf::TimeCode &timeCode = readable(); h.append( Imath::V2i( timeCode.timeAndFlags(), timeCode.userData() ) ); }