void Hd_PrimTypeIndex<PrimType>::GetPrimSubtree(const TfToken &typeId, const SdfPath &rootPath, SdfPathVector *outPaths) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); typename _TypeIndex::const_iterator typeIt = _index.find(typeId); if (typeIt ==_index.end()) { TF_CODING_ERROR("Unsupported prim type: %s", typeId.GetText()); return; } _PrimTypeEntry &typeEntry = _entries[typeIt->second]; HdPrimGather gather; gather.Subtree(typeEntry.primIds.GetIds(), rootPath, outPaths); }
void HdDirtyList::_UpdateIDs(SdfPathVector* ids, HdDirtyBits mask) { HD_TRACE_FUNCTION(); HD_PERF_COUNTER_INCR(HdPerfTokens->dirtyListsRebuilt); const SdfPathVector &paths = _renderIndex.GetRprimIds(); const SdfPathVector &includePaths = _collection.GetRootPaths(); const SdfPathVector &excludePaths = _collection.GetExcludePaths(); _FilterParam filterParam = {_collection, _renderIndex, mask}; HdPrimGather gather; gather.PredicatedFilter(paths, includePaths, excludePaths, _DirtyListFilterPredicate, &filterParam, ids); }
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; }
void Hd_PrimTypeIndex<PrimType>::RemoveSubtree(const SdfPath &root, HdSceneDelegate* sceneDelegate, HdChangeTracker &tracker, HdRenderDelegate *renderDelegate) { HD_TRACE_FUNCTION(); HF_MALLOC_TAG_FUNCTION(); struct _Range { size_t _start; size_t _end; _Range() = default; _Range(size_t start, size_t end) : _start(start) , _end(end) { } }; size_t numTypes = _entries.size(); for (size_t typeIdx = 0; typeIdx < numTypes; ++typeIdx) { _PrimTypeEntry &typeEntry = _entries[typeIdx]; HdPrimGather gather; _Range totalRange; std::vector<_Range> rangesToRemove; const SdfPathVector &ids = typeEntry.primIds.GetIds(); if (gather.SubtreeAsRange(ids, root, &totalRange._start, &totalRange._end)) { // end is inclusive! size_t currentRangeStart = totalRange._start; for (size_t primIdIdx = totalRange._start; primIdIdx <= totalRange._end; ++primIdIdx) { const SdfPath &primId = ids[primIdIdx]; typename _PrimMap::iterator primIt = typeEntry.primMap.find(primId); if (primIt == typeEntry.primMap.end()) { TF_CODING_ERROR("Prim in id list not in info map: %s", primId.GetText()); } else { _PrimInfo &primInfo = primIt->second; if (primInfo.sceneDelegate == sceneDelegate) { _TrackerRemovePrim(tracker, primId); _RenderDelegateDestroyPrim(renderDelegate, primInfo.prim); primInfo.prim = nullptr; typeEntry.primMap.erase(primIt); } else { if (currentRangeStart < primIdIdx) { rangesToRemove.emplace_back(currentRangeStart, primIdIdx - 1); } currentRangeStart = primIdIdx + 1; } } } // Remove final range if (currentRangeStart <= totalRange._end) { rangesToRemove.emplace_back(currentRangeStart, totalRange._end); } // Remove ranges from id's in back to front order to not invalidate indices while (!rangesToRemove.empty()) { _Range &range = rangesToRemove.back(); typeEntry.primIds.RemoveRange(range._start, range._end); rangesToRemove.pop_back(); } } } }