@@ -7515,20 +7515,56 @@ class UsdStage_ResolveInfoAccess
75157515// Helper structure populated by _GetResolveInfo and _ResolveInfoResolver
75167516// with extra information accumulated in the process. This allows clients to
75177517// avoid redoing work.
7518- template <class T >
75197518struct UsdStage ::_ExtraResolveInfo
75207519{
7521- static_assert (std::is_same_v<T, SdfAbstractDataValue> ||
7522- std::is_same_v<T, VtValue>);
7523-
7520+ // Create an _ExtraResolveInfo but with space for the _ResolveInfoResolver
7521+ // to populate default or fallback values into. This is used as an
7522+ // optimization when we're getting resolve info for the purposes of serving
7523+ // UsdAttribute::Get(), when we know we're going to fetch the value
7524+ // eventually.
7525+ static _ExtraResolveInfo WithDefaultOrFallbackValueStorage () {
7526+ _ExtraResolveInfo ret;
7527+ ret._defaultOrFallback .emplace ();
7528+ return ret;
7529+ }
7530+
75247531 _ExtraResolveInfo *_AddNextWeakerInfo () {
75257532 if (!TF_VERIFY (!nextWeaker, " Cannot add weaker info to an "
75267533 " _ExtraResolveInfo that already has it." )) {
75277534 return this ;
75287535 }
75297536 nextWeaker = std::make_shared<_ExtraResolveInfo>();
7537+ // Propagate _defaultOrFallback's existence.
7538+ if (_defaultOrFallback) {
7539+ nextWeaker->_defaultOrFallback .emplace ();
7540+ }
75307541 return nextWeaker.get ();
75317542 }
7543+
7544+ // If this object was created by WithDefaultOrFallbackValueStorage(), return
7545+ // a pointer to a VtValue to store a default or fallback value into. This
7546+ // is a value resolution optimization that avoids a double fetch in case
7547+ // there's just one strongest default or fallback.
7548+ VtValue *GetDefaultOrFallbackStorage () {
7549+ return _defaultOrFallback
7550+ ? std::addressof (_defaultOrFallback.value ())
7551+ : nullptr ;
7552+ }
7553+
7554+ // If this object was created by WithDefaultOrFallbackValueStorage() and a
7555+ // non-empty VtValue was stored to it move the stored value to `val`, delete
7556+ // this object's storage for a default or fallback value, and return true.
7557+ // Otherwise do nothing and return false. After a call to this function,
7558+ // subsequent calls to GetDefaultOrFallbackStorage() return nullptr and this
7559+ // function always returns false.
7560+ bool MoveDefaultOrFallbackValueTo (VtValue *val) const {
7561+ if (_defaultOrFallback && !_defaultOrFallback.value ().IsEmpty ()) {
7562+ *val = std::move (_defaultOrFallback.value ());
7563+ _defaultOrFallback.reset ();
7564+ return true ;
7565+ }
7566+ return false ;
7567+ }
75327568
75337569 // If we're chaining together _ExtraResolveInfos to represent composing
75347570 // value types, this points to the next weaker extra resolve info.
@@ -7545,6 +7581,13 @@ struct UsdStage::_ExtraResolveInfo
75457581 // If the resolve info source is UsdResolveInfoSourceValueClips this will
75467582 // be the Usd_ClipSet containing values for the attribute.
75477583 Usd_ClipSetRefPtr clipSet;
7584+
7585+ private:
7586+ // If not empty, then GetDefaultOrFallbackStorage() returns the address of
7587+ // _defaultOrFallback, so the _ResolveInfoResolver can store one there.
7588+ // It's the raw value from the layer, not transformed to the stage's
7589+ // name/time-space, normally _GetValueFromResolveInfoImpl does that.
7590+ mutable std::optional<VtValue> _defaultOrFallback;
75487591};
75497592
75507593Usd_AssetPathContext
@@ -7619,14 +7662,13 @@ UsdStage::_GetAssetPathContext(UsdTimeCode time, const UsdAttribute &attr) const
76197662//
76207663// Otherwise compute the full resolve info at `time`, and fill both `infoOut`
76217664// and `extraInfoOut` and return true.
7622- template <class T >
76237665bool
76247666UsdStage::_GetCompletedResolveInfo (const UsdAttribute &attr,
76257667 UsdTimeCode time,
76267668 const UsdResolveTarget *resolveTarget,
76277669 const UsdResolveInfo &infoIn,
76287670 UsdResolveInfo *infoOut,
7629- _ExtraResolveInfo<T> *extraInfoOut) const
7671+ _ExtraResolveInfo *extraInfoOut) const
76307672{
76317673 if (infoIn._source == UsdResolveInfoSourceNone ||
76327674 infoIn._source == UsdResolveInfoSourceFallback) {
@@ -7726,7 +7768,7 @@ UsdStage::_GetValueFromResolveInfoImpl(
77267768 UsdTimeCode time, const UsdAttribute &attr,
77277769 Usd_Interpolator const &interpolator,
77287770 const UsdResolveInfo &infoIn, const UsdResolveTarget *resolveTarget,
7729- const _ExtraResolveInfo<T> *extraInfo, T *result) const
7771+ const _ExtraResolveInfo *extraInfo, T *result) const
77307772{
77317773 static_assert (std::is_same_v<T, VtValue> ||
77327774 std::is_same_v<T, SdfAbstractDataValue>);
@@ -7738,10 +7780,11 @@ UsdStage::_GetValueFromResolveInfoImpl(
77387780 // or a nullary call to UsdAttribute::GetResolveInfo(). In this case we
77397781 // need to "complete" the resolveInfo for `time` and fill in an `extraInfo`.
77407782 UsdResolveInfo completedInfo_;
7741- _ExtraResolveInfo<T> completedExtraInfo_;
7783+ _ExtraResolveInfo completedExtraInfo_ =
7784+ _ExtraResolveInfo::WithDefaultOrFallbackValueStorage ();
77427785 const auto &[resolveInfo, extraResolveInfo] =
77437786 [&]() -> std::tuple<const UsdResolveInfo &,
7744- const _ExtraResolveInfo<T> &> {
7787+ const _ExtraResolveInfo &> {
77457788 if (!extraInfo) {
77467789 if (_GetCompletedResolveInfo (
77477790 attr, time, resolveTarget, infoIn,
@@ -7766,7 +7809,7 @@ UsdStage::_GetValueFromResolveInfoImpl(
77667809 // interpolate the final samples.
77677810
77687811 UsdResolveInfo const *curResolveInfo = &resolveInfo;
7769- _ExtraResolveInfo<T> const *curExtraResolveInfo = &extraResolveInfo;
7812+ _ExtraResolveInfo const *curExtraResolveInfo = &extraResolveInfo;
77707813
77717814 Usd_InterpolationSampleSeries composedSamples;
77727815 Usd_InterpolationSampleSeries curSamples;
@@ -7948,10 +7991,16 @@ UsdStage::_GetValueFromResolveInfoImpl(
79487991 SdfPath specPath = curResolveInfo->
79497992 _primPathInLayerStack.AppendProperty (attr.GetName ());
79507993 Usd_InterpolationSampleSeries defaultSeries (1 );
7951- Usd_DefaultValueResult defValue = Usd_HasDefault (
7952- curResolveInfo->_layer , specPath, &defaultSeries.front ().value );
7953- TF_VERIFY (defValue == Usd_DefaultValueResult::Found,
7954- " Resolve info source default has no default value" );
7994+ // Fetch a value from curExtraResolveInfo if we have one, otherwise
7995+ // call Usd_HasDefault().
7996+ if (!curExtraResolveInfo->
7997+ MoveDefaultOrFallbackValueTo (&defaultSeries.front ().value )) {
7998+ Usd_DefaultValueResult defValue = Usd_HasDefault (
7999+ curResolveInfo->_layer , specPath,
8000+ &defaultSeries.front ().value );
8001+ TF_VERIFY (defValue == Usd_DefaultValueResult::Found,
8002+ " Resolve info source default has no default value" );
8003+ }
79558004 // Translate to the stage.
79568005 xfValueToStage (defaultSeries.front ().value , &specPath);
79578006 // Compose samples over.
@@ -7966,11 +8015,14 @@ UsdStage::_GetValueFromResolveInfoImpl(
79668015 else if (curResolveInfo->_source == UsdResolveInfoSourceFallback) {
79678016 VtValue fallbackValue;
79688017 Usd_InterpolationSampleSeries fallbackSeries (1 );
7969- const bool hasFallback = attr._Prim ()->GetPrimDefinition ()
7970- .GetAttributeFallbackValue (
7971- attr.GetName (), &fallbackSeries.front ().value );
7972- TF_VERIFY (hasFallback,
7973- " Resolve info source fallback has no fallback value" );
8018+ if (!curExtraResolveInfo->
8019+ MoveDefaultOrFallbackValueTo (&fallbackSeries.front ().value )) {
8020+ const bool hasFallback = attr._Prim ()->GetPrimDefinition ()
8021+ .GetAttributeFallbackValue (
8022+ attr.GetName (), &fallbackSeries.front ().value );
8023+ TF_VERIFY (hasFallback,
8024+ " Resolve info source fallback has no fallback value" );
8025+ }
79748026 // Fallback values require no transformation to the stage space, but
79758027 // they can be composed-over. Fallbacks are always weakest, so we
79768028 // can always break out here.
@@ -8014,7 +8066,8 @@ UsdStage::_GetValueImpl(UsdTimeCode time, const UsdAttribute &attr,
80148066 std::is_same_v<T, SdfAbstractDataValue>);
80158067
80168068 UsdResolveInfo resolveInfo;
8017- _ExtraResolveInfo<T> extraResolveInfo;
8069+ _ExtraResolveInfo extraResolveInfo =
8070+ _ExtraResolveInfo::WithDefaultOrFallbackValueStorage ();
80188071
80198072 TfErrorMark m;
80208073 _GetResolveInfo (attr, &resolveInfo, &time, &extraResolveInfo);
@@ -8842,12 +8895,8 @@ UsdStage::_GetTimeSampleMap(const UsdAttribute &attr,
88428895}
88438896
88448897// A 'Resolver' for filling UsdResolveInfo.
8845- template <typename T>
88468898struct UsdStage ::_ResolveInfoResolver
88478899{
8848- static_assert (std::is_same_v<T, SdfAbstractDataValue> ||
8849- std::is_same_v<T, VtValue>);
8850-
88518900 // Helper to set the value source. Normally this just sets the source from
88528901 // None to `source`, but in the case where we're getting resolve info at no
88538902 // specific time and we encounter a composing default, we continue looking
@@ -8876,7 +8925,7 @@ struct UsdStage::_ResolveInfoResolver
88768925
88778926 explicit _ResolveInfoResolver (const UsdAttribute& attr,
88788927 UsdResolveInfo* resolveInfo,
8879- UsdStage::_ExtraResolveInfo<T> * extraInfo)
8928+ UsdStage::_ExtraResolveInfo* extraInfo)
88808929 : _attr(attr)
88818930 , _resolveInfo(resolveInfo)
88828931 , _extraInfo(extraInfo)
@@ -8886,10 +8935,8 @@ struct UsdStage::_ResolveInfoResolver
88868935 bool
88878936 ProcessFallback ()
88888937 {
8889- if (const bool hasFallback =
8890- _attr._Prim ()->GetPrimDefinition ()
8891- .template GetAttributeFallbackValue <VtValue>(
8892- _attr.GetName (), nullptr )) {
8938+ if (_attr._Prim ()->GetPrimDefinition ().GetAttributeFallbackValue (
8939+ _attr.GetName (), _extraInfo->GetDefaultOrFallbackStorage ())) {
88938940 _SetSource (_resolveInfo, UsdResolveInfoSourceFallback);
88948941 return true ;
88958942 }
@@ -8922,7 +8969,7 @@ struct UsdStage::_ResolveInfoResolver
89228969 }
89238970
89248971 UsdResolveInfo *nextWeaker = nullptr ;
8925- UsdStage::_ExtraResolveInfo<T>* nextWeakerExtra = nullptr ;
8972+ UsdStage::_ExtraResolveInfo * nextWeakerExtra = nullptr ;
89268973
89278974 UsdResolveInfoSource thisSource = UsdResolveInfoSourceNone;
89288975 bool didSetSource = false ;
@@ -8993,8 +9040,9 @@ struct UsdStage::_ResolveInfoResolver
89939040 } else {
89949041 const std::type_info *valueType = &typeid (void );
89959042
8996- Usd_DefaultValueResult defValue =
8997- Usd_HasDefault<VtValue>(layer, specPath, nullptr , &valueType);
9043+ Usd_DefaultValueResult defValue = Usd_HasDefault (
9044+ layer, specPath, _extraInfo->GetDefaultOrFallbackStorage (),
9045+ &valueType);
89989046
89999047 if (defValue == Usd_DefaultValueResult::Found) {
90009048 *foundOpinion = true ;
@@ -9070,8 +9118,9 @@ struct UsdStage::_ResolveInfoResolver
90709118 // at the default time. We never get here when resolving a value a
90719119 // numeric time.
90729120 const std::type_info *valueType = &typeid (void );
9073- Usd_DefaultValueResult defValue =
9074- Usd_HasDefault<VtValue>(layer, specPath, nullptr , &valueType);
9121+ Usd_DefaultValueResult defValue = Usd_HasDefault (
9122+ layer, specPath, _extraInfo->GetDefaultOrFallbackStorage (),
9123+ &valueType);
90759124
90769125 if (defValue == Usd_DefaultValueResult::Found) {
90779126 _resolveInfo->_source = UsdResolveInfoSourceDefault;
@@ -9171,9 +9220,9 @@ struct UsdStage::_ResolveInfoResolver
91719220 }
91729221
91739222private:
9174- const UsdAttribute& _attr;
9175- UsdResolveInfo* _resolveInfo;
9176- UsdStage::_ExtraResolveInfo<T>* _extraInfo;
9223+ const UsdAttribute & _attr;
9224+ UsdResolveInfo * _resolveInfo;
9225+ UsdStage::_ExtraResolveInfo * _extraInfo;
91779226
91789227 // For composing value types, when we find a lower-time sample value that
91799228 // doesn't compose and an upper-time sample value that does, that
@@ -9193,49 +9242,47 @@ struct UsdStage::_ResolveInfoResolver
91939242 bool _processingAnimationBlock = false ;
91949243};
91959244
9196- template <class T >
91979245void
91989246UsdStage::_GetResolveInfo (const UsdAttribute &attr,
91999247 UsdResolveInfo *resolveInfo,
92009248 const UsdTimeCode *time,
9201- _ExtraResolveInfo<T> *extraInfo) const
9249+ _ExtraResolveInfo *extraInfo) const
92029250{
92039251 auto makeUsdResolverFn = [&attr](bool skipEmptyNodes) {
92049252 return Usd_Resolver (&attr._Prim ()->GetPrimIndex (), skipEmptyNodes);
92059253 };
92069254 _GetResolveInfoImpl (attr, resolveInfo, time, extraInfo, makeUsdResolverFn);
92079255}
92089256
9209- template <class T >
92109257void
92119258UsdStage::_GetResolveInfoWithResolveTarget (
92129259 const UsdAttribute &attr,
92139260 const UsdResolveTarget &resolveTarget,
92149261 UsdResolveInfo *resolveInfo,
92159262 const UsdTimeCode *time,
9216- _ExtraResolveInfo<T> *extraInfo) const
9263+ _ExtraResolveInfo *extraInfo) const
92179264{
92189265 auto makeUsdResolverFn = [&resolveTarget](bool skipEmptyNodes) {
92199266 return Usd_Resolver (&resolveTarget, skipEmptyNodes);
92209267 };
92219268 _GetResolveInfoImpl (attr, resolveInfo, time, extraInfo, makeUsdResolverFn);
92229269}
92239270
9224- template <class T , class MakeUsdResolverFn >
9271+ template <class MakeUsdResolverFn >
92259272void
92269273UsdStage::_GetResolveInfoImpl (
92279274 const UsdAttribute &attr,
92289275 UsdResolveInfo *resolveInfo,
92299276 const UsdTimeCode *time,
9230- _ExtraResolveInfo<T> *extraInfo,
9277+ _ExtraResolveInfo *extraInfo,
92319278 const MakeUsdResolverFn &makeUsdResolverFn) const
92329279{
9233- _ExtraResolveInfo<T> localExtraInfo;
9280+ _ExtraResolveInfo localExtraInfo;
92349281 if (!extraInfo) {
92359282 extraInfo = &localExtraInfo;
92369283 }
92379284
9238- _ResolveInfoResolver<T> resolver (attr, resolveInfo, extraInfo);
9285+ _ResolveInfoResolver resolver (attr, resolveInfo, extraInfo);
92399286 if (!time) {
92409287 _GetResolvedValueAtTimeImpl (
92419288 attr, &resolver, nullptr , makeUsdResolverFn);
@@ -9413,25 +9460,6 @@ UsdStage::_GetResolvedValueAtTimeImpl(
94139460 }
94149461}
94159462
9416- void
9417- UsdStage::_GetResolveInfo (const UsdAttribute &attr,
9418- UsdResolveInfo *resolveInfo,
9419- const UsdTimeCode *time) const
9420- {
9421- _GetResolveInfo<VtValue>(attr, resolveInfo, time);
9422- }
9423-
9424- void
9425- UsdStage::_GetResolveInfoWithResolveTarget (
9426- const UsdAttribute &attr,
9427- const UsdResolveTarget &resolveTarget,
9428- UsdResolveInfo *resolveInfo,
9429- const UsdTimeCode *time) const
9430- {
9431- _GetResolveInfoWithResolveTarget<VtValue>(
9432- attr, resolveTarget, resolveInfo, time);
9433- }
9434-
94359463bool
94369464UsdStage::_GetValueFromResolveInfo (const UsdResolveInfo &info,
94379465 UsdTimeCode time, const UsdAttribute &attr,
0 commit comments