-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure light collections are dirtied on creation #1653
Changes from 2 commits
73d78c8
37b4920
94e4ec5
98f3884
6d64dee
36c306e
4ff47b7
c653c37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,10 +38,29 @@ _IsQueryTrivial(UsdCollectionAPI::MembershipQuery const& query) | |
ruleMap.begin()->second == UsdTokens->expandPrims; | ||
} | ||
|
||
void | ||
UsdImaging_CollectionCache::_MarkCollectionContentDirty(UsdStageWeakPtr const& stage, | ||
UsdCollectionAPI::MembershipQuery const& query) | ||
{ | ||
if(query.HasExcludes()) | ||
{ | ||
// If there are any exlusion we have to consider all previously excluded paths dirty | ||
// As there is no API to query excluded paths we mark all prims in the Stage dirty | ||
_allPathsDirty = true; | ||
} | ||
else | ||
{ | ||
SdfPathSet linkedPaths = UsdComputeIncludedPathsFromCollection(query, stage); | ||
std::merge(_dirtyPaths.begin(), _dirtyPaths.end(), linkedPaths.begin(), linkedPaths.end(), | ||
std::inserter(_dirtyPaths, _dirtyPaths.begin())); | ||
} | ||
} | ||
|
||
TfToken | ||
UsdImaging_CollectionCache::UpdateCollection(UsdCollectionAPI const& c) | ||
{ | ||
RemoveCollection(c); | ||
const UsdStageWeakPtr& stage = c.GetPrim().GetStage(); | ||
RemoveCollection(stage, c.GetCollectionPath()); | ||
|
||
std::lock_guard<std::mutex> lock(_mutex); | ||
|
||
|
@@ -78,15 +97,16 @@ UsdImaging_CollectionCache::UpdateCollection(UsdCollectionAPI const& c) | |
_pathsForQuery[query].insert(path); | ||
_idForPath[path] = id; | ||
|
||
_MarkCollectionContentDirty(stage, query); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like there's some missing bits here... If _queryForId[id] before you update it != query, also _MarkContentDirty(stage, _queryForId[id])? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
return id; | ||
} | ||
|
||
void | ||
UsdImaging_CollectionCache::RemoveCollection(UsdCollectionAPI const& c) | ||
UsdImaging_CollectionCache::RemoveCollection(UsdStageWeakPtr const& stage, SdfPath const& path) | ||
{ | ||
std::lock_guard<std::mutex> lock(_mutex); | ||
|
||
SdfPath path = c.GetCollectionPath(); | ||
auto const& pathEntry = _idForPath.find(path); | ||
if (pathEntry == _idForPath.end()) { | ||
// No pathEntry -- bail. This can happen if the collection was | ||
|
@@ -102,6 +122,9 @@ UsdImaging_CollectionCache::RemoveCollection(UsdCollectionAPI const& c) | |
return; | ||
} | ||
UsdCollectionAPI::MembershipQuery const& queryRef = queryEntry->second; | ||
_idForQuery.erase(queryRef); | ||
|
||
_MarkCollectionContentDirty(stage, queryRef); | ||
|
||
auto const& pathsForQueryEntry = _pathsForQuery.find(queryRef); | ||
pathsForQueryEntry->second.erase(path); | ||
|
@@ -113,13 +136,31 @@ UsdImaging_CollectionCache::RemoveCollection(UsdCollectionAPI const& c) | |
// This also reaps the associated identifier. | ||
if (pathsForQueryEntry->second.empty()) { | ||
_pathsForQuery.erase(pathsForQueryEntry); | ||
_idForQuery.erase(queryRef); | ||
_queryForId.erase(queryEntry); | ||
TF_DEBUG(USDIMAGING_COLLECTIONS) | ||
.Msg("UsdImaging_CollectionCache: Dropped id '%s'", id.GetText()); | ||
} | ||
}; | ||
|
||
SdfPathSet const& | ||
UsdImaging_CollectionCache::GetDirtyPaths() const | ||
{ | ||
return _dirtyPaths; | ||
} | ||
|
||
bool | ||
UsdImaging_CollectionCache::AreAllPathsDirty() const | ||
{ | ||
return _allPathsDirty; | ||
} | ||
|
||
void | ||
UsdImaging_CollectionCache::ClearDirtyPaths() | ||
{ | ||
_dirtyPaths.clear(); | ||
_allPathsDirty = false; | ||
} | ||
|
||
TfToken | ||
UsdImaging_CollectionCache::GetIdForCollection(UsdCollectionAPI const& c) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -80,6 +80,42 @@ UsdImagingLightAdapter::_RemovePrim(SdfPath const& cachePath, | |
UsdImagingIndexProxy* index) | ||
{ | ||
index->RemoveSprim(HdPrimTypeTokens->light, cachePath); | ||
UsdImaging_CollectionCache &collectionCache = _GetCollectionCache(); | ||
SdfPath lightLinkPath = cachePath.AppendProperty(UsdImagingTokens->collectionLightLink); | ||
collectionCache.RemoveCollection(GetDelegate()->GetStage(), lightLinkPath); | ||
SdfPath shadowLinkPath = cachePath.AppendProperty(UsdImagingTokens->collectionShadowLink); | ||
collectionCache.RemoveCollection(GetDelegate()->GetStage(), shadowLinkPath); | ||
aloysbaillet marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
bool | ||
UsdImagingLightAdapter::_UpdateCollectionsChanged(UsdPrim const& prim, SdfPath const& cachePath) const | ||
{ | ||
UsdImaging_CollectionCache &collectionCache = _GetCollectionCache(); | ||
auto getCollectionHash = [&collectionCache] (const UsdCollectionAPI& api) -> size_t { | ||
const TfToken id = collectionCache.UpdateCollection(api); | ||
const UsdImaging_CollectionCache::Query* query = nullptr; | ||
collectionCache.GetMembershipQuery(id, &query); | ||
return query != nullptr ? query->GetHash() : 0; | ||
}; | ||
UsdLuxLight light(prim); | ||
const size_t newLightCollectionHash = getCollectionHash(light.GetLightLinkCollectionAPI()); | ||
const size_t newShadowCollectionHash = getCollectionHash(light.GetShadowLinkCollectionAPI()); | ||
aloysbaillet marked this conversation as resolved.
Show resolved
Hide resolved
|
||
auto hashesIt = _collectionHashes.find(cachePath); | ||
if(hashesIt == _collectionHashes.end()){ | ||
hashesIt = _collectionHashes.insert({cachePath, {0, 0}}).first; | ||
} | ||
HashPair& hashes = hashesIt->second; | ||
if (newLightCollectionHash != hashes.lightCollectionHash || newShadowCollectionHash != hashes.shadowCollectionHash) | ||
{ | ||
|
||
hashes.lightCollectionHash = newLightCollectionHash; | ||
hashes.shadowCollectionHash = newShadowCollectionHash; | ||
return true; | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
|
||
void | ||
|
@@ -127,11 +163,14 @@ UsdImagingLightAdapter::TrackVariability(UsdPrim const& prim, | |
|
||
UsdLuxLightAPI light(prim); | ||
if (TF_VERIFY(light)) { | ||
UsdImaging_CollectionCache &collectionCache = _GetCollectionCache(); | ||
collectionCache.UpdateCollection(light.GetLightLinkCollectionAPI()); | ||
collectionCache.UpdateCollection(light.GetShadowLinkCollectionAPI()); | ||
// TODO: When collections change we need to invalidate affected | ||
// prims with the DirtyCollections flag. | ||
if (_UpdateCollectionsChanged(prim, cachePath)) | ||
{ | ||
*timeVaryingBits |= HdLight::DirtyBits::DirtyCollection; | ||
} | ||
else | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can skip the else here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, can just call _UpdateCollectionsChanged. I don't think collections are allowed to be time-varying? And if you did want to check that, instead of seeing if the collection has new contents, you'd want to ask whether the attributes are time varying. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I removed the call altogether as the attributes cannot be animated... I'm guessing that if timesamples are added on the includeRoot bool that could cause some issues though? |
||
{ | ||
*timeVaryingBits &= ~HdLight::DirtyBits::DirtyCollection; | ||
} | ||
} | ||
|
||
// XXX Cache primvars for lights. | ||
|
@@ -177,6 +216,9 @@ UsdImagingLightAdapter::ProcessPropertyChange(UsdPrim const& prim, | |
if (UsdGeomXformable::IsTransformationAffectedByAttrNamed(propertyName)) { | ||
return HdLight::DirtyBits::DirtyTransform; | ||
} | ||
|
||
_UpdateCollectionsChanged(prim, cachePath); | ||
aloysbaillet marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// "DirtyParam" is the catch-all bit for light params. | ||
return HdLight::DirtyBits::DirtyParams; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the query has exclude paths, I'd still expect UsdComputeIncludedPathsFromCollection to come up with the right list. That should return the set of paths that pass both the include & exclude rules, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, but prims that were previously excluded from the collection would not be returned in the include set, and these also need to be marked dirty...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually as the RemoveCollection call will catch all paths from the outgoing collection, the UpdateCollection should be able to safely ignore the excluded paths... Will test that further!