Пример #1
0
void 
HdRenderPass::SetRprimCollection(HdRprimCollection const& col)
{
    if (col == _collection){
        return;
    }
         
    _collection = col; 
    // Force any cached data based on collection to be refreshed.
    _collectionChanged = true;
    // reset the cached collection version
    _collectionVersion = 0;

    // update dirty list subscription for the new collection.
    // holding shared_ptr for the lifetime of the dirty list.
    bool isMinorChange = true;
    if (!_dirtyList || !_dirtyList->ApplyEdit(col)) {
        _dirtyList.reset(new HdDirtyList(_collection, *_renderIndex));
        isMinorChange = false;
    }

    if (TfDebug::IsEnabled(HD_DIRTY_LIST)) {
        std::stringstream s;
        s << "  Include: \n";
        for (auto i : col.GetRootPaths()) {
            s << "    - " << i << "\n";
        }
        s << "  Exclude: \n";
        for (auto i : col.GetExcludePaths()) {
            s << "    - " << i << "\n";
        }
        s << "  Repr: " << col.GetReprName() << "\n";
        s << "  Render Tags: \n";
        for (auto i : col.GetRenderTags()) {
            s << "    - " << i << "\n";
        }

        TF_DEBUG(HD_DIRTY_LIST).Msg("RenderPass(%p)::SetRprimCollection (%s) - "
            "constructing new DirtyList(%p) minorChange(%d) \n%s\n",
            (void*)this,
            col.GetName().GetText(),
            (void*)&*_dirtyList,
            isMinorChange,
            s.str().c_str());
    }
}
Пример #2
0
bool
HdDirtyList::ApplyEdit(HdRprimCollection const& col)
{
    HD_TRACE_FUNCTION();

    // Don't attempt to transition dirty lists where the collection
    // fundamentally changed, we can't reused filtered paths in those cases.
    //
    // when repr changes, don't reuse the dirty list, since the required
    // DirtyBits may change.
    if (col.GetName() != _collection.GetName()
        || col.GetReprName() != _collection.GetReprName()
        || col.IsForcedRepr() != _collection.IsForcedRepr()
        || col.GetRenderTags() != _collection.GetRenderTags()) {
        return false;
    }

    // Also don't attempt to fix-up dirty lists when the collection is radically
    // different in terms of root paths; here a heuristic of 100 root paths is
    // used as a threshold for when we will stop attempting to fix the list.
    if (std::abs(int(col.GetRootPaths().size()) -
                 int(_collection.GetRootPaths().size())) > 100) {
        return false;
    }

    // If the either the old or new collection has Exclude paths do
    // the full rebuild.
    if (!col.GetExcludePaths().empty() ||
        !_collection.GetExcludePaths().empty()) {
        return false;
    }

    // If the varying state has changed - Rebuild the base list
    // before adding the new items
    HdChangeTracker &changeTracker = _renderIndex.GetChangeTracker();

    unsigned int currentVaryingStateVersion =
                                         changeTracker.GetVaryingStateVersion();

    if (_varyingStateVersion != currentVaryingStateVersion) {
           TF_DEBUG(HD_DIRTY_LIST).Msg("DirtyList(%p): varying state changed "
                   "(%s, %d -> %d)\n",
                   (void*)this,
                   _collection.GetName().GetText(),
                   _varyingStateVersion,
                   currentVaryingStateVersion);

           // populate only varying prims in the collection
           _UpdateIDs(&_dirtyIds, HdChangeTracker::Varying);
           _varyingStateVersion = currentVaryingStateVersion;
    }

    SdfPathVector added, removed;
    typedef SdfPathVector::const_iterator ITR;
    ITR newI = col.GetRootPaths().cbegin();
    ITR newEnd = col.GetRootPaths().cend();
    ITR oldI = _collection.GetRootPaths().cbegin();
    ITR oldEnd = _collection.GetRootPaths().cend();
    HdRenderIndex& index = _renderIndex;
    TfToken const & repr = col.GetReprName();

    TF_DEBUG(HD_DIRTY_LIST).Msg("DirtyList(%p): ApplyEdit\n", (void*)this);

    if (TfDebug::IsEnabled(HD_DIRTY_LIST)) {
        std::cout << "  Old Collection: " << std::endl;
        for (auto const& i : _collection.GetRootPaths()) {
            std::cout << "    " << i << std::endl;
        }
        std::cout << "  Old _dirtyIds: " << std::endl;
        for (auto const& i : _dirtyIds) {
            std::cout << "    " << i << std::endl;
        }
    }

    const SdfPathVector &paths = _renderIndex.GetRprimIds();

    while (newI != newEnd || oldI != oldEnd) {
        if (newI != newEnd && oldI != oldEnd && *newI == *oldI) {
            ++newI;
            ++oldI;
            continue;
        }
        // If any paths in the two sets are prefixed by one another, the logic
        // below doesn't work, since the subtree has to be fixed up (it's not
        // just a simple prefix scan). In these cases, we'll just rebuild the
        // entire list.
        if (newI != newEnd && oldI != oldEnd && newI->HasPrefix(*oldI)) {
            return false;          
        }
        if (newI != newEnd && oldI != oldEnd && oldI->HasPrefix(*newI)) {
            return false;          
        }
        if (newI != newEnd && (oldI == oldEnd || *newI < *oldI)) {
            HdPrimGather gather;

            SdfPathVector newPaths;
            gather.Subtree(paths, *newI, &newPaths);

            size_t numNewPaths = newPaths.size();
            for (size_t newPathNum = 0;
                        newPathNum < numNewPaths;
                      ++newPathNum) {
                const SdfPath &newPath = newPaths[newPathNum];

                if (col.HasRenderTag(index.GetRenderTag(newPath, repr))) {
                    _dirtyIds.push_back(newPath);
                    changeTracker.MarkRprimDirty(newPath,
                                                 HdChangeTracker::InitRepr);
                }
            }
            ++newI;
        } else if (oldI != oldEnd) { 
            // oldI < newI: Item removed in new list
            SdfPath const& oldPath = *oldI;
            _dirtyIds.erase(std::remove_if(_dirtyIds.begin(), _dirtyIds.end(), 
                  [&oldPath](SdfPath const& p){return p.HasPrefix(oldPath);}),
                  _dirtyIds.end());
            ++oldI;
        }
    }

    _collection = col;
    _collectionVersion
                    = changeTracker.GetCollectionVersion(_collection.GetName());


    // make sure the next GetDirtyRprims() picks up the updated list.
    _isEmpty = false;

    if (TfDebug::IsEnabled(HD_DIRTY_LIST)) {
        std::cout << "  New Collection: " << std::endl;
        for (auto const& i : _collection.GetRootPaths()) {
            std::cout << "    " << i << std::endl;
        }
        std::cout << "  New _dirtyIds: " << std::endl;
        for (auto const& i : _dirtyIds) {
            std::cout << "    " << i << std::endl;
        }
    }

    return true;
}