diff --git a/pxr/imaging/hd/sceneDelegate.cpp b/pxr/imaging/hd/sceneDelegate.cpp index 3e2162358f..f64c66e568 100644 --- a/pxr/imaging/hd/sceneDelegate.cpp +++ b/pxr/imaging/hd/sceneDelegate.cpp @@ -304,6 +304,14 @@ HdSceneDelegate::GetScenePrimPath(SdfPath const& rprimId, return rprimId.ReplacePrefix(_delegateID, SdfPath::AbsoluteRootPath()); } +/*virtual*/ +SdfPathVector +HdSceneDelegate::GetScenePrimPaths(SdfPath const& rprimId, + std::vector instanceIndices, + std::vector *instancerContexts) +{ + return SdfPathVector(instanceIndices.size()); +} // -----------------------------------------------------------------------// diff --git a/pxr/imaging/hd/sceneDelegate.h b/pxr/imaging/hd/sceneDelegate.h index b47cbc153f..e3a9be8c2d 100644 --- a/pxr/imaging/hd/sceneDelegate.h +++ b/pxr/imaging/hd/sceneDelegate.h @@ -623,6 +623,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 instanceIndices, + std::vector *instancerContexts = nullptr); + // -----------------------------------------------------------------------// /// \name Material Aspects // -----------------------------------------------------------------------// diff --git a/pxr/usdImaging/usdImaging/delegate.cpp b/pxr/usdImaging/usdImaging/delegate.cpp index bb3da02fa0..51e6ac4c36 100644 --- a/pxr/usdImaging/usdImaging/delegate.cpp +++ b/pxr/usdImaging/usdImaging/delegate.cpp @@ -2254,6 +2254,23 @@ UsdImagingDelegate::GetScenePrimPath(SdfPath const& rprimId, return protoPath; } +SdfPathVector +UsdImagingDelegate::GetScenePrimPaths(SdfPath const& rprimId, + std::vector instanceIndices, + std::vector *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); +} + bool UsdImagingDelegate::PopulateSelection( HdSelection::HighlightMode const& highlightMode, diff --git a/pxr/usdImaging/usdImaging/delegate.h b/pxr/usdImaging/usdImaging/delegate.h index ba1211cddc..6a292da0f4 100644 --- a/pxr/usdImaging/usdImaging/delegate.h +++ b/pxr/usdImaging/usdImaging/delegate.h @@ -411,6 +411,12 @@ class UsdImagingDelegate : public HdSceneDelegate, public TfWeakBase { int instanceIndex, HdInstancerContext *instancerContext = nullptr) override; + USDIMAGING_API + virtual SdfPathVector + GetScenePrimPaths(SdfPath const& rprimId, + std::vector instanceIndices, + std::vector *instancerContexts = nullptr) override; + // ExtComputation support USDIMAGING_API TfTokenVector diff --git a/pxr/usdImaging/usdImaging/instanceAdapter.cpp b/pxr/usdImaging/usdImaging/instanceAdapter.cpp index baac40123c..dea0df0ddb 100644 --- a/pxr/usdImaging/usdImaging/instanceAdapter.cpp +++ b/pxr/usdImaging/usdImaging/instanceAdapter.cpp @@ -2384,16 +2384,34 @@ UsdImagingInstanceAdapter::_ComputeInstanceMap( return indices; } -struct UsdImagingInstanceAdapter::_GetScenePrimPathFn +/* virtual */ +SdfPath +UsdImagingInstanceAdapter::GetScenePrimPath( + SdfPath const& cachePath, + int instanceIndex, + HdInstancerContext *instancerContext) const { - _GetScenePrimPathFn( + HD_TRACE_FUNCTION(); + + // Pass nullptr to instancerCtxs because this value is never used by + // our implementation of this method. + SdfPathVector paths = GetScenePrimPaths( + cachePath, { instanceIndex }, nullptr); + return paths.size() > 0 ? paths[0] : SdfPath(); +} + +struct UsdImagingInstanceAdapter::_GetScenePrimPathsFn +{ + _GetScenePrimPathsFn( const UsdImagingInstanceAdapter* adapter_, - int instanceIndex_, + const std::vector &instanceIndices_, const SdfPath &protoPath_) : adapter(adapter_) - , instanceIndex(instanceIndex_) , protoPath(protoPath_) - { } + { + instanceIndices.insert( + instanceIndices_.begin(), instanceIndices_.end()); + } void Initialize(size_t numInstances) { @@ -2405,7 +2423,7 @@ struct UsdImagingInstanceAdapter::_GetScenePrimPathFn // 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 (instanceIdx == instanceIndex) { + 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 @@ -2421,24 +2439,27 @@ struct UsdImagingInstanceAdapter::_GetScenePrimPathFn for (UsdPrim const& prim : instanceContext) { instanceChain.push_back(prim.GetPath()); } - primPath = adapter->_GetPrimPathFromInstancerChain(instanceChain); - return false; + 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 size_t instanceIndex; const SdfPath& protoPath; - SdfPath primPath; + std::set instanceIndices; + std::map primPaths; }; /* virtual */ -SdfPath -UsdImagingInstanceAdapter::GetScenePrimPath( +SdfPathVector +UsdImagingInstanceAdapter::GetScenePrimPaths( SdfPath const& cachePath, - int instanceIndex, - HdInstancerContext *instancerContext) const + std::vector const& instanceIndices, + std::vector *instancerCtxs) const { HD_TRACE_FUNCTION(); @@ -2451,7 +2472,7 @@ UsdImagingInstanceAdapter::GetScenePrimPath( if (_IsChildPrim(usdPrim, cachePath)) { TF_DEBUG(USDIMAGING_SELECTION).Msg( - "GetScenePrimPath: instance proto = %s\n", cachePath.GetText()); + "GetScenePrimPaths: instance proto = %s\n", cachePath.GetText()); UsdImagingInstancerContext instancerContext; _ProtoPrim const& proto = _GetProtoPrim( @@ -2459,13 +2480,13 @@ UsdImagingInstanceAdapter::GetScenePrimPath( cachePath, &instancerContext); if (!proto.adapter) { - return SdfPath(); + return SdfPathVector(instanceIndices.size(), cachePath); } _InstancerData const* instrData = TfMapLookupPtr(_instancerData, instancerContext.instancerCachePath); if (!instrData) { - return SdfPath(); + return SdfPathVector(instanceIndices.size(), cachePath); } UsdPrim instancerPrim = _GetPrim(instancerContext.instancerCachePath); @@ -2474,34 +2495,46 @@ UsdImagingInstanceAdapter::GetScenePrimPath( // invisible instances). VtIntArray indices = _ComputeInstanceMap(instancerPrim, *instrData, _GetTimeWithOffset(0.0)); - - instanceIndex = indices[instanceIndex]; - - _GetScenePrimPathFn primPathFn(this, instanceIndex, proto.path); - _RunForAllInstancesToDraw(instancerPrim, &primPathFn); - return primPathFn.primPath; + std::vector 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( - "GetScenePrimPath: instance = %s\n", cachePath.GetText()); + "GetScenePrimPaths: instance = %s\n", cachePath.GetText()); SdfPath const* instancerPath = TfMapLookupPtr(_instanceToInstancerMap, cachePath); if (instancerPath == nullptr) { - return SdfPath(); + return SdfPathVector(instanceIndices.size(), cachePath); } _InstancerData const* instrData = TfMapLookupPtr(_instancerData, *instancerPath); if (instrData == nullptr) { - return SdfPath(); + return SdfPathVector(instanceIndices.size(), cachePath); } - _GetScenePrimPathFn primPathFn(this, instanceIndex, + + SdfPathVector result; + result.reserve(instanceIndices.size()); + _GetScenePrimPathsFn primPathsFn(this, instanceIndices, SdfPath::EmptyPath()); - _RunForAllInstancesToDraw(_GetPrim(*instancerPath), &primPathFn); - return primPathFn.primPath; + _RunForAllInstancesToDraw(_GetPrim(*instancerPath), &primPathsFn); + for (size_t i = 0; i < instanceIndices.size(); i++) + result.push_back(primPathsFn.primPaths[instanceIndices[i]]); + return result; } - return SdfPath(); + return SdfPathVector(instanceIndices.size(), cachePath); } struct UsdImagingInstanceAdapter::_PopulateInstanceSelectionFn diff --git a/pxr/usdImaging/usdImaging/instanceAdapter.h b/pxr/usdImaging/usdImaging/instanceAdapter.h index e76775296a..8a154c1d49 100644 --- a/pxr/usdImaging/usdImaging/instanceAdapter.h +++ b/pxr/usdImaging/usdImaging/instanceAdapter.h @@ -314,6 +314,11 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter int instanceIndex, HdInstancerContext *instancerContext) const override; + virtual SdfPathVector GetScenePrimPaths( + SdfPath const& cachePath, + std::vector const& instanceIndices, + std::vector *instancerCtxs) const override; + virtual bool PopulateSelection( HdSelection::HighlightMode const& highlightMode, SdfPath const &cachePath, @@ -455,6 +460,7 @@ class UsdImagingInstanceAdapter : public UsdImagingPrimAdapter struct _PopulateInstanceSelectionFn; struct _GetScenePrimPathFn; + struct _GetScenePrimPathsFn; // Helper functions for dealing with "actual" instances to be drawn. // diff --git a/pxr/usdImaging/usdImaging/pointInstancerAdapter.cpp b/pxr/usdImaging/usdImaging/pointInstancerAdapter.cpp index 49c6e7fbca..13391c58b1 100644 --- a/pxr/usdImaging/usdImaging/pointInstancerAdapter.cpp +++ b/pxr/usdImaging/usdImaging/pointInstancerAdapter.cpp @@ -1359,6 +1359,29 @@ UsdImagingPointInstancerAdapter::GetScenePrimPath( return _GetPrimPathFromInstancerChain(paths); } +/* virtual */ +SdfPathVector +UsdImagingPointInstancerAdapter::GetScenePrimPaths( + SdfPath const& cachePath, + std::vector const& instanceIndices, + std::vector *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; +} + static size_t _GatherAuthoredTransformTimeSamples( diff --git a/pxr/usdImaging/usdImaging/pointInstancerAdapter.h b/pxr/usdImaging/usdImaging/pointInstancerAdapter.h index 573071fea3..f7f254fd35 100644 --- a/pxr/usdImaging/usdImaging/pointInstancerAdapter.h +++ b/pxr/usdImaging/usdImaging/pointInstancerAdapter.h @@ -260,6 +260,11 @@ class UsdImagingPointInstancerAdapter : public UsdImagingPrimAdapter int instanceIndex, HdInstancerContext *instancerContext) const override; + virtual SdfPathVector GetScenePrimPaths( + SdfPath const& cachePath, + std::vector const& instanceIndices, + std::vector *instancerCtxs) const override; + virtual bool PopulateSelection( HdSelection::HighlightMode const& highlightMode, SdfPath const &cachePath, diff --git a/pxr/usdImaging/usdImaging/primAdapter.cpp b/pxr/usdImaging/usdImaging/primAdapter.cpp index 8eb0984b7c..1fc2157d58 100644 --- a/pxr/usdImaging/usdImaging/primAdapter.cpp +++ b/pxr/usdImaging/usdImaging/primAdapter.cpp @@ -478,6 +478,17 @@ UsdImagingPrimAdapter::GetScenePrimPath( return cachePath; } +/*virtual*/ +SdfPathVector +UsdImagingPrimAdapter::GetScenePrimPaths(SdfPath const& cachePath, + std::vector const& instanceIndices, + std::vector *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*/ bool UsdImagingPrimAdapter::PopulateSelection( diff --git a/pxr/usdImaging/usdImaging/primAdapter.h b/pxr/usdImaging/usdImaging/primAdapter.h index 4480942142..9869db0165 100644 --- a/pxr/usdImaging/usdImaging/primAdapter.h +++ b/pxr/usdImaging/usdImaging/primAdapter.h @@ -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 const& instanceIndices, + std::vector *instancerCtxs) const; // Add the given usdPrim to the HdSelection object, to mark it for // selection highlighting. cachePath is the path of the object referencing