Ejemplo n.º 1
0
bool
GusdUSD_StageProxy::MultiAccessor::Bind(
    const UT_Array<GusdUSD_StageProxyHandle>& proxies,
    const UT_Array<SdfPath>& paths,
    UT_Array<UsdPrim>& prims,
    UsdStage::InitialLoadSet loadSet,
    GusdUT_ErrorContext* err)
{
    Release();

    UT_ASSERT(paths.isEmpty() || paths.size() == proxies.size());

    if(proxies.size() == 0)
        return true;

    /* We have an input arrays of proxies and paths.
       Many of the paths will be associated with the same proxy,
       but they may also point at different proxies.
       
       To avoid having to lock every individual prim, we want to compute
       a mapping of indices from those input arrays into indices in
       an array containing just the unique set of proxies.*/

    UT_Array<GusdUSD_StageProxyHandle> uniqueProxies;
    if(!_ComputeUniqueProxies(uniqueProxies, _indexMap, proxies))
        return false;

    _numAccessors = uniqueProxies.size();
    _accessors = new Accessor[_numAccessors];
    _size = proxies.size();

    /* Now the unique set of proxies is known, so acquire accessors
       (I.e., lock and load stages) */
    std::atomic_bool workerInterrupt(false);
    UTparallelForHeavyItems(UT_BlockedRange<size_t>(0, _numAccessors),
                            _BindAccessorsFn(_accessors, uniqueProxies,
                                             loadSet, err, workerInterrupt));
    if(UTgetInterrupt()->opInterrupt() || workerInterrupt)
        return false;

    /* Any entries referencing proxies that couldn't be bound 
       should have an invalid index; no point in accessing invalid accessors.*/
    for(exint i = 0; i < _indexMap.size(); ++i) {
        int idx = _indexMap(i);
        if(idx >= 0) {
            if(!_accessors[idx])
                _indexMap(i) = -1;
        }
    }

    return _GetPrims(paths, prims, err);
}
Ejemplo n.º 2
0
bool
GusdUSD_StageProxy::MultiAccessor::_Load(const UT_Array<SdfPath>& paths)
{
    if(paths.isEmpty())
        return true;

    UT_ASSERT_P(paths.size() == _size);

    typedef tbb::concurrent_unordered_set<
        SdfPath,SdfPath::Hash> ConcurrentPathSet;

    struct _ComputeUnloadedPrimsFn
    {
        _ComputeUnloadedPrimsFn(const UT_Array<SdfPath>& paths,
                                const UT_Array<exint>& indexMap,
                                const UT_Array<_PrimLoader*>& loaders,
                                UT_Array<ConcurrentPathSet*>& pathSets)
            : _paths(paths), _indexMap(indexMap),
              _loaders(loaders), _pathSets(pathSets) {}

        void    operator()(const UT_BlockedRange<size_t>& r) const
                {
                    auto* boss = UTgetInterrupt();
                    char bcnt = 0;

                    for(size_t i = r.begin(); i < r.end(); ++i) {
                        if(BOOST_UNLIKELY(!++bcnt && boss->opInterrupt()))
                            return;
                        
                        exint idx = _indexMap(i);
                        if(idx >= 0) {
                            if(auto* loader = _loaders(idx)) {
                                const SdfPath& path = _paths(i);
                                if(!path.IsEmpty() && !loader->IsLoaded(path))
                                    _pathSets(idx)->insert(path);
                            }
                        }
                    }
                }

    private:
        const UT_Array<SdfPath>&        _paths;
        const UT_Array<exint>&          _indexMap;
        const UT_Array<_PrimLoader*>&   _loaders;
        UT_Array<ConcurrentPathSet*>    _pathSets;
    };

    /* Compute sets of unloaded prims.
       This constitutes the bulk of binding time, so do this parallel.*/
    UT_Array<_PrimLoader*> loaders(_numAccessors, _numAccessors);
    UT_Array<ConcurrentPathSet*> pathSets(_numAccessors, _numAccessors);
    for(exint i = 0; i < _numAccessors; ++i) {
        if ( _accessors[i] ) {
            auto* loader = _accessors[i].GetProxy()->_primLoader;
            if(loader) {
                loaders(i) = loader;
                pathSets(i) = new ConcurrentPathSet;
            }
        }
    }

    UTparallelFor(UT_BlockedRange<size_t>(0, _size),
                  _ComputeUnloadedPrimsFn(paths, _indexMap, loaders, pathSets));

    if(UTgetInterrupt()->opInterrupt())
        return false;

    /* Load the actual prims.
       This could be done in parallel, but is probably not worth it since
       there's only work to perform the first time a prim load is requested.*/
    for(exint i = 0; i < _numAccessors; ++i) {
        if(auto* pathSet = pathSets(i)) {
            SdfPathSet pathsToLoad(pathSet->begin(), pathSet->end());
            _accessors[i]._Load(pathsToLoad);
            
            delete pathSet;
        }
    }

    return true;
}