Skip to content

Commit

Permalink
Adding GetScenePrimPaths method to HdSceneDelegate which allows a single
Browse files Browse the repository at this point in the history
method call to fetch prim paths for a large number of instances in a single
method call. Especially useful for native instances which use an O(n)
algorithm to discover the path of a single instance.
  • Loading branch information
marktucker committed Jan 9, 2022
1 parent 928c584 commit a3ed33f
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 2 deletions.
8 changes: 8 additions & 0 deletions pxr/imaging/hd/sceneDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,14 @@ HdSceneDelegate::GetScenePrimPath(SdfPath const& rprimId,
return rprimId.ReplacePrefix(_delegateID, SdfPath::AbsoluteRootPath());
}

/*virtual*/
SdfPathVector
HdSceneDelegate::GetScenePrimPaths(SdfPath const& rprimId,
std::vector<int> instanceIndices,
std::vector<HdInstancerContext> *instancerContexts)
{
return SdfPathVector(instanceIndices.size());
}

/*virtual*/
SdfPath
Expand Down
10 changes: 10 additions & 0 deletions pxr/imaging/hd/sceneDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,16 @@ class HdSceneDelegate {
int instanceIndex,
HdInstancerContext *instancerContext = nullptr);

/// A vectorized version of GetScenePrimPath that allows the prim adapter
/// to amortize expensive calculations across a number of path evaluations
/// in a single call. Note that only a single rprimId is supported. This
/// allows this call to be forwarded directly to a single prim adapter
/// rather than requiring a lot of data shuffling.
HD_API
virtual SdfPathVector GetScenePrimPaths(SdfPath const& rprimId,
std::vector<int> instanceIndices,
std::vector<HdInstancerContext> *instancerContexts = nullptr);

/// Returns an identifier that can be used to share data between HdPrims
/// during a Sync operation. Any number of HdPrims of the same type may
/// return the same identifier. In this situation, the render delegate
Expand Down
17 changes: 17 additions & 0 deletions pxr/usdImaging/usdImaging/delegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2263,6 +2263,23 @@ UsdImagingDelegate::GetScenePrimPath(SdfPath const& rprimId,
return protoPath;
}

SdfPathVector
UsdImagingDelegate::GetScenePrimPaths(SdfPath const& rprimId,
std::vector<int> instanceIndices,
std::vector<HdInstancerContext> *instancerContexts)
{
SdfPath cachePath = ConvertIndexPathToCachePath(rprimId);
_HdPrimInfo *primInfo = _GetHdPrimInfo(cachePath);
if (!primInfo || !primInfo->adapter) {
TF_WARN("GetScenePrimPaths: Couldn't find rprim <%s>",
rprimId.GetText());
return SdfPathVector(instanceIndices.size(), cachePath);
}

return primInfo->adapter->GetScenePrimPaths(
cachePath, instanceIndices, instancerContexts);
}

SdfPath
UsdImagingDelegate::GetDataSharingId(SdfPath const& primId)
{
Expand Down
6 changes: 6 additions & 0 deletions pxr/usdImaging/usdImaging/delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,12 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase {
int instanceIndex,
HdInstancerContext *instancerContext = nullptr) override;

USDIMAGING_API
virtual SdfPathVector
GetScenePrimPaths(SdfPath const& rprimId,
std::vector<int> instanceIndices,
std::vector<HdInstancerContext> *instancerContexts = nullptr) override;

USDIMAGING_API
virtual SdfPath GetDataSharingId(SdfPath const& primId) override;

Expand Down
137 changes: 137 additions & 0 deletions pxr/usdImaging/usdImaging/instanceAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2511,6 +2511,143 @@ UsdImagingInstanceAdapter::GetScenePrimPath(
return SdfPath();
}

struct UsdImagingInstanceAdapter::_GetScenePrimPathsFn
{
_GetScenePrimPathsFn(
const UsdImagingInstanceAdapter* adapter_,
const std::vector<int> &instanceIndices_,
const SdfPath &protoPath_)
: adapter(adapter_)
, protoPath(protoPath_)
{
instanceIndices.insert(
instanceIndices_.begin(), instanceIndices_.end());
}

void Initialize(size_t numInstances)
{
}

bool operator()(
const std::vector<UsdPrim>& instanceContext, size_t instanceIdx)
{
// If this iteration is the right instance index, compose all the USD
// prototype paths together to get the instance proxy path. Include the
// proto path (of the child prim), if one was provided.
if (instanceIndices.find(instanceIdx) != instanceIndices.end()) {
SdfPathVector instanceChain;
// To get the correct prim-in-prototype, we need to add the
// prototype path to the instance chain. However, there's a case in
// _Populate where we populate prims that are just a USD prototype
// (used by e.g. cards). In this case, the hydra proto path is
// overridden to be the path of the USD instance, and we don't want
// to add it to the instance chain since instanceContext.front
// would duplicate it.
UsdPrim p = adapter->_GetPrim(protoPath);
if (p && !p.IsInstance()) {
instanceChain.push_back(protoPath);
}
for (UsdPrim const& prim : instanceContext) {
instanceChain.push_back(prim.GetPath());
}
primPaths.emplace(instanceIdx,
adapter->_GetPrimPathFromInstancerChain(instanceChain));
// We can stop iterating when we've found a prim path for each
// instance index.
return primPaths.size() != instanceIndices.size();
}
return true;
}

const UsdImagingInstanceAdapter* adapter;
const SdfPath& protoPath;
std::set<int> instanceIndices;
std::map<int, SdfPath> primPaths;
};

/* virtual */
SdfPathVector
UsdImagingInstanceAdapter::GetScenePrimPaths(
SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const
{
HD_TRACE_FUNCTION();

// For child prims (hydra prototypes) and USD instances, the process is
// the same: find the associated hydra instancer, and use the instance
// index to look up the composed instance path. They differ based on
// whether you append a hydra proto path, and how you find the
// hydra instancer.
UsdPrim usdPrim = _GetPrim(cachePath.GetAbsoluteRootOrPrimPath());
if (_IsChildPrim(usdPrim, cachePath)) {

TF_DEBUG(USDIMAGING_SELECTION).Msg(
"GetScenePrimPaths: instance proto = %s\n", cachePath.GetText());

UsdImagingInstancerContext instancerContext;
_ProtoPrim const& proto = _GetProtoPrim(
cachePath.GetAbsoluteRootOrPrimPath(),
cachePath, &instancerContext);

if (!proto.adapter) {
return SdfPathVector(instanceIndices.size(), cachePath);
}

_InstancerData const* instrData =
TfMapLookupPtr(_instancerData, instancerContext.instancerCachePath);
if (!instrData) {
return SdfPathVector(instanceIndices.size(), cachePath);
}

UsdPrim instancerPrim = _GetPrim(instancerContext.instancerCachePath);

// Translate from hydra instance index to USD (since hydra filters out
// invisible instances).
VtIntArray indices = _ComputeInstanceMap(instancerPrim, *instrData,
_GetTimeWithOffset(0.0));
std::vector<int> remappedIndices;

remappedIndices.reserve(instanceIndices.size());
for (size_t i = 0; i < instanceIndices.size(); i++)
remappedIndices.push_back(indices[instanceIndices[i]]);

SdfPathVector result;
result.reserve(instanceIndices.size());
_GetScenePrimPathsFn primPathsFn(this, remappedIndices, proto.path);
_RunForAllInstancesToDraw(instancerPrim, &primPathsFn);
for (size_t i = 0; i < remappedIndices.size(); i++)
result.push_back(primPathsFn.primPaths[remappedIndices[i]]);
return result;
} else {

TF_DEBUG(USDIMAGING_SELECTION).Msg(
"GetScenePrimPaths: instance = %s\n", cachePath.GetText());

SdfPath const* instancerPath =
TfMapLookupPtr(_instanceToInstancerMap, cachePath);
if (instancerPath == nullptr) {
return SdfPathVector(instanceIndices.size(), cachePath);
}
_InstancerData const* instrData =
TfMapLookupPtr(_instancerData, *instancerPath);
if (instrData == nullptr) {
return SdfPathVector(instanceIndices.size(), cachePath);
}

SdfPathVector result;
result.reserve(instanceIndices.size());
_GetScenePrimPathsFn primPathsFn(this, instanceIndices,
SdfPath::EmptyPath());
_RunForAllInstancesToDraw(_GetPrim(*instancerPath), &primPathsFn);
for (size_t i = 0; i < instanceIndices.size(); i++)
result.push_back(primPathsFn.primPaths[instanceIndices[i]]);
return result;
}

return SdfPathVector(instanceIndices.size(), cachePath);
}

/* virtual */
SdfPath
UsdImagingInstanceAdapter::GetDataSharingId(SdfPath const& cachePath) const
Expand Down
6 changes: 6 additions & 0 deletions pxr/usdImaging/usdImaging/instanceAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter
int instanceIndex,
HdInstancerContext *instancerContext) const override;

virtual SdfPathVector GetScenePrimPaths(
SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const override;

virtual SdfPath GetDataSharingId(
SdfPath const& cachePath) const override;

Expand Down Expand Up @@ -458,6 +463,7 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter

struct _PopulateInstanceSelectionFn;
struct _GetScenePrimPathFn;
struct _GetScenePrimPathsFn;

// Helper functions for dealing with "actual" instances to be drawn.
//
Expand Down
23 changes: 23 additions & 0 deletions pxr/usdImaging/usdImaging/pointInstancerAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,29 @@ UsdImagingPointInstancerAdapter::GetScenePrimPath(
return _GetPrimPathFromInstancerChain(paths);
}

/* virtual */
SdfPathVector
UsdImagingPointInstancerAdapter::GetScenePrimPaths(
SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const
{
SdfPathVector result;
HdInstancerContext instanceCtx;

result.reserve(instanceIndices.size());
if (instancerCtxs)
instancerCtxs->reserve(instanceIndices.size());
for (size_t i = 0; i < instanceIndices.size(); i++) {
result.push_back(
GetScenePrimPath(cachePath, instanceIndices[i], &instanceCtx));
if (instancerCtxs)
instancerCtxs->push_back(std::move(instanceCtx));
}

return result;
}

/* virtual */
SdfPath
UsdImagingPointInstancerAdapter::GetDataSharingId(
Expand Down
5 changes: 5 additions & 0 deletions pxr/usdImaging/usdImaging/pointInstancerAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ class UsdImagingPointInstancerAdapter : public UsdImagingPrimAdapter
int instanceIndex,
HdInstancerContext *instancerContext) const override;

virtual SdfPathVector GetScenePrimPaths(
SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const override;

virtual SdfPath GetDataSharingId(
SdfPath const& cachePath) const override;

Expand Down
11 changes: 11 additions & 0 deletions pxr/usdImaging/usdImaging/primAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,17 @@ UsdImagingPrimAdapter::GetScenePrimPath(
return cachePath;
}

/*virtual*/
SdfPathVector
UsdImagingPrimAdapter::GetScenePrimPaths(SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const
{
// Note: if we end up here, we're not instanced, since primInfo
// holds the instance adapter for instanced gprims.
return SdfPathVector(instanceIndices.size(), cachePath);
}

/*virtual*/
SdfPath
UsdImagingPrimAdapter::GetDataSharingId(SdfPath const& cachePath) const
Expand Down
9 changes: 7 additions & 2 deletions pxr/usdImaging/usdImaging/primAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,13 @@ class UsdImagingPrimAdapter

USDIMAGING_API
virtual SdfPath GetScenePrimPath(SdfPath const& cachePath,
int instanceIndex,
HdInstancerContext *instancerCtx) const;
int instanceIndex,
HdInstancerContext *instancerCtx) const;

USDIMAGING_API
virtual SdfPathVector GetScenePrimPaths(SdfPath const& cachePath,
std::vector<int> const& instanceIndices,
std::vector<HdInstancerContext> *instancerCtxs) const;

USDIMAGING_API
virtual SdfPath GetDataSharingId(SdfPath const& cachePath) const;
Expand Down

0 comments on commit a3ed33f

Please sign in to comment.