Clarification on Hd...SentinelTokens->container usage

In reading the header for HdDataSourceLocatorSentinelTokens->container I’m a bit confused about why all nested invalidation is necessary.

/// HdDataSourceLocatorSentinelTokens->container indicates that
/// the container data source needs to be refetched even though none of
/// its contained data sources have changed unless indicated by another
/// data source locator.
///
/// For example, assume that MyFilteringSceneIndex::GetPrim("/MyPrim")
/// previously returned the result from the input scene index but now
/// returns
///     HdContainerDataSourceEditor(_GetInputScene()->GetPrim("/MyPrim"))
///         .Set(HdDataSourceLocator("foo", "bar", "mySource"), mySource)
///         .Finish().
/// Then it needs to send prims dirtied with
///     HdDataSourceLocatorSet{
///         HdDataSourceLocator(
///             HdDataSourceLocatorSentinelTokens->container),
///         HdDataSourceLocator(
///             "foo", HdDataSourceLocatorSentinelTokens->container),
///         HdDataSourceLocator(
///             "foo", "bar", HdDataSourceLocatorSentinelTokens->container),
///         HdDataSourceLocator(
///             "foo", "bar", "mySource")}.

In particular, why is the container dirtying required on /foo and on /foo/bar; why isn’t the container dirtying on / necessarily sufficient?

Scanning containerDataSourceEditor.h I see similar “need to send a dirty notice invalidating the chain of container handles” messaging, but I’m missing the motivation.

PS, forum won’t let me create a topic that has HdDataSourceLocatorSentinelTokens->container in the title … “Title seems unclear, one or more words is very long?” :frowning:

Hi Rob,

Good question! It really has to do with the nature of data source access and what that entails for a scene index wanting to provide caching behaviors.
Accessing a data source at /a/b/c requires querying the prim container, and from it, the data source at a, and so on until c.
A scene index that wants to provide caching behavior for /a/b will have to override the prim container so it can override the data source at /a so that the query for /a/b can lookup an internal cache on the scene index.

So, if we have a scene index that conditionally overrides a prim’s data source, as follows:

HdSceneIndexPrim MySceneIndex::GetPrim(const SdfPath &primPath)
{
    auto prim = _GetInputSceneIndex()->GetPrim();
    if (_someCondition) {
        prim.dataSource =
            HdContainerDataSourceEditor(prim.dataSource)
            .Set(HdDataSourceLocator("foo", "bar", "mySource"), _CompiteMySource(..))
            .Finish();
    }
    return prim;
}

and a caching scene index downstream that caches /foo, then invalidating just /<sentinel> in addition to /foo/bar/mySource when _someCondition changes won’t suffice because the consumer’s query for /foo/bar/mySource will hit the cache for /foo, and thus receive a stale answer.

In the example above, because the editor is used with the prim container data source, the value for /foo/bar/mySource is tied to the prim container.

Your question seems to ask: should the caching scene index drop its cached entries for /foo if it encounters a /<sentinel>?

  1. /<sentinel>does not contain /foo/<sentinel>, so it’d break away from the closed under descendancy nature of HdDataSourceLocatorSet and require special handling w/r/t Intersects.
  2. The interpretation of a data source locator w/r/t invalidation is that the data source addressed by the locator and all nested data sources under it are invalid and need to be re-queried. We didn’t have a way to invalidate a data source handle w/o invalidating nested data sources under it, and that seemed like a limitation.

Let me know if that helps clarify!

Thanks Raja, I’d like to follow up on one point:

The interpretation of a data source locator w/r/t invalidation is that the data source addressed by the locator and all nested data sources under it are invalid and need to be re-queried. We didn’t have a way to invalidate a data source handle w/o invalidating nested data sources under it, and that seemed like a limitation.

Has that shown up in practice (i.e., the need/desire to invalidate a parent datasource without invalidating a child)?