Skip to content

Commit 2380a03

Browse files
adamrwoodburypixar-oss
authored andcommitted
OpenExec: Add the IncomingConnections computation input parameter, which allows
computations to take input from computations on attributes that have connections that target the consuming computation's provider object. (Internal change: 2399176)
1 parent 43fc05f commit 2380a03

19 files changed

Lines changed: 781 additions & 23 deletions

pxr/exec/esf/editReason.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ EsfEditReason::_GetBitDescription(EsfEditReason::_BitIndex bitIndex)
2222
return "ChangedPropertyList";
2323
case EsfEditReason::_BitIndex::ChangedConnectionPaths:
2424
return "ChangedConnectionPaths";
25+
case EsfEditReason::_BitIndex::ChangedIncomingConnections:
26+
return "ChangedIncomingConnections";
2527
case EsfEditReason::_BitIndex::ChangedTargetPaths:
2628
return "ChangedTargetPaths";
2729
case EsfEditReason::_BitIndex::Max:

pxr/exec/esf/editReason.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ class EsfEditReason
5252
///
5353
static const EsfEditReason ChangedConnectionPaths;
5454

55+
/// The set of connections that target an object has changed.
56+
///
57+
static const EsfEditReason ChangedIncomingConnections;
58+
5559
/// The list of target paths on a relationship has changed.
5660
///
5761
static const EsfEditReason ChangedTargetPaths;
@@ -128,6 +132,7 @@ class EsfEditReason
128132
ResyncedObject,
129133
ChangedPropertyList,
130134
ChangedConnectionPaths,
135+
ChangedIncomingConnections,
131136
ChangedTargetPaths,
132137
Max
133138
};
@@ -154,6 +159,9 @@ inline constexpr EsfEditReason EsfEditReason::ChangedPropertyList(
154159
inline constexpr EsfEditReason EsfEditReason::ChangedConnectionPaths(
155160
EsfEditReason::_BitIndex::ChangedConnectionPaths);
156161

162+
inline constexpr EsfEditReason EsfEditReason::ChangedIncomingConnections(
163+
EsfEditReason::_BitIndex::ChangedIncomingConnections);
164+
157165
inline constexpr EsfEditReason EsfEditReason::ChangedTargetPaths(
158166
EsfEditReason::_BitIndex::ChangedTargetPaths);
159167

pxr/exec/esf/object.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,8 @@ EsfObjectInterface::GetIncomingConnections(EsfJournal *const journal) const
6666
if (journal) {
6767
journal->Add(
6868
_GetPath(),
69-
// TODO:
70-
// EsfEditReason::ResyncedObject |
71-
// EsfEditReason::ChangedIncomingConnections);
72-
EsfEditReason::ResyncedObject);
69+
EsfEditReason::ResyncedObject |
70+
EsfEditReason::ChangedIncomingConnections);
7371
}
7472
return _GetIncomingConnections();
7573
}

pxr/exec/esfUsd/stageData.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ EsfUsdStageData::UpdateForResync(
329329
// Note that as long as an owning attribute has a given connection, the
330330
// incoming connection map entry remains populated, regardless of whether
331331
// the targeted object exists in the scene.
332-
if (!resyncedPrim || !UsdPrimDefaultPredicate(resyncedPrim)) {
332+
if (!UsdPrimDefaultPredicate(resyncedPrim)) {
333333
TRACE_FUNCTION_SCOPE("Update for expired resynced prim");
334334

335335
for (auto it = _outgoing.lower_bound(resyncedPath);

pxr/exec/exec/computationBuilders.h

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,19 @@ struct Exec_ComputationBuilderAccessor
508508
ExecProviderResolution::DynamicTraversal::Local});
509509
}
510510

511+
/// See [IncomingConnections()](#exec_registration::IncomingConnections)
512+
template <typename ResultType>
513+
ValueSpecifier
514+
IncomingConnections(const TfToken &computationName)
515+
{
516+
return ValueSpecifier(
517+
computationName,
518+
ExecTypeRegistry::GetInstance().CheckForRegistration<ResultType>(),
519+
{Exec_ComputationBuilderAccessorBase::_GetLocalTraversal(),
520+
ExecProviderResolution::DynamicTraversal::
521+
IncomingConnectionOwningAttributes});
522+
}
523+
511524
/// See [Metadata()](#exec_registration::Metadata)
512525
template <typename ResultType>
513526
ValueSpecifier
@@ -552,8 +565,7 @@ struct Exec_ComputationBuilderAttributeAccessor
552565
/// \addtogroup group_Exec_ValueSpecifiers
553566
/// @{
554567

555-
/// See
556-
/// [Connections()](#exec_registration::Connections)
568+
/// See [Connections()](#exec_registration::Connections)
557569
template <typename ResultType>
558570
ValueSpecifier
559571
Connections(const TfToken &computationName)
@@ -569,7 +581,7 @@ struct Exec_ComputationBuilderAttributeAccessor
569581
/// @}
570582

571583
// XXX:TODO
572-
// Accessors for AnimSpline, IncomingConnections
584+
// Accessors for AnimSpline, etc.
573585
};
574586

575587
/// Relationship accessor
@@ -1180,9 +1192,7 @@ AttributeValue(const TfToken &attributeName)
11801192
/// it requests the named computation from the objects that are targeted by
11811193
/// those connections. The reason we choose "Connections" as the name, rather
11821194
/// than "ConnectionTargetedObjects," is to allow for future expansion of USD to
1183-
/// allow for value-transforming behaviors on attribute connections. This
1184-
/// concept exists in Presto and is extremely useful for rigging, so there's a
1185-
/// good chance it will be introduced in the future in USD and OpenExec.
1195+
/// allow for value-transforming behaviors on attribute connections themselves.
11861196
///
11871197
/// The default input name is \p computationName; use `InputName` to specify a
11881198
/// different input name.
@@ -1223,6 +1233,57 @@ Connections(const TfToken &computationName)
12231233
ConnectionTargetedObjects});
12241234
}
12251235

1236+
/// On any provider, requests input values from the computation \p
1237+
/// computationName of type \p ResultType on the attributes that own any
1238+
/// attribute connections that target the provider object.
1239+
///
1240+
/// When this input parameter produces multiple input values, there is no
1241+
/// deterministic ordering.
1242+
///
1243+
/// \note
1244+
/// Conceptually, this input registration provides access to the connections
1245+
/// that target the provider, but as outlined in the paragraph above, in
1246+
/// practice it requests the named computation from the attributes that own
1247+
/// those connections. The reason we choose "IncomingConnections" as the name,
1248+
/// rather than "IncomingConnectionOwningAttributes," is to allow for future
1249+
/// expansion of USD to allow for value-transforming behaviors on attribute
1250+
/// connections themselves.
1251+
///
1252+
/// The default input name is \p computationName; use `InputName` to specify a
1253+
/// different input name.
1254+
///
1255+
/// # Example
1256+
///
1257+
/// ```{.cpp}
1258+
/// EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA(MySchemaType)
1259+
/// {
1260+
/// // Register a prim computation that sums the values of the
1261+
/// // integer-valued attributes that own connections that target the
1262+
/// // provider prim.
1263+
/// self.PrimComputation(_tokens->computeSum)
1264+
/// .Callback<int>(+[](const VdfContext &ctx) {
1265+
/// VdfReadIteratorRange<int> range(
1266+
/// ctx, ExecBuiltinComputations->computeValue);
1267+
/// return std::accumulate(range.begin(), range.end(), 0);
1268+
/// })
1269+
/// .Inputs(
1270+
/// IncomingConnections<int>(ExecBuiltinComputations->computeValue));
1271+
/// }
1272+
/// ```
1273+
///
1274+
template <typename ResultType>
1275+
auto
1276+
IncomingConnections(const TfToken &computationName)
1277+
{
1278+
return Exec_ComputationBuilderComputationValueSpecifier<
1279+
Exec_ComputationBuilderProviderTypes::Any>(
1280+
computationName,
1281+
ExecTypeRegistry::GetInstance().CheckForRegistration<ResultType>(),
1282+
{SdfPath::ReflexiveRelativePath(),
1283+
ExecProviderResolution::DynamicTraversal::
1284+
IncomingConnectionOwningAttributes});
1285+
}
1286+
12261287
/// @} // Value Specifiers
12271288

12281289
} // namespace exec_registration

pxr/exec/exec/definitionRegistry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ Exec_DefinitionRegistry::_ValidateComputationRegistration(
510510
{
511511
if (schemaType.IsUnknown()) {
512512
TF_CODING_ERROR(
513-
"Attempt to register computation '%s' using an unknown type.",
513+
"Attempt to register computation '%s' using an unknown schema type.",
514514
computationName.GetText());
515515
return false;
516516
}

pxr/exec/exec/inputResolver.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,49 @@ class _InputResolver
396396
return outputKeys;
397397
}
398398

399+
// Returns the ouput keys for the attributes that own connections that
400+
// target the currrent object, for the computation of the given name and
401+
// result type.
402+
//
403+
// The current object must be valid prior to calling this method.
404+
//
405+
Exec_OutputKeyVector _TraverseToIncomingConnectionOwningAttributes(
406+
const TfToken &computationName,
407+
const TfType resultType,
408+
const TfToken &disambiguatingId)
409+
{
410+
if (!TF_VERIFY(_currentObject->IsValid(_journal))) {
411+
return {};
412+
}
413+
414+
Exec_OutputKeyVector outputKeys;
415+
416+
for (const SdfPath &path :
417+
_currentObject->GetIncomingConnections(_journal)) {
418+
if (!_TraverseToAbsolutePath(path)) {
419+
continue;
420+
}
421+
422+
if (const Exec_ComputationDefinition *const computationDefinition =
423+
_FindComputationDefinition(
424+
computationName,
425+
resultType,
426+
disambiguatingId)) {
427+
outputKeys.emplace_back(
428+
_currentObject->AsObject(),
429+
_GetDispatchingConfigKeyForOutputKey(computationDefinition),
430+
computationDefinition);
431+
}
432+
}
433+
434+
// Clear the current object since the traversal has terminated.
435+
_currentObjectVariant = std::monostate{};
436+
_currentObject = nullptr;
437+
_currentAttribute = nullptr;
438+
439+
return outputKeys;
440+
}
441+
399442
// Updates the current object to the nearest namespace ancestor that
400443
// a computation named \p computationName with the given \p resultType.
401444
//
@@ -563,6 +606,13 @@ class _InputResolver
563606
inputKey.resultType,
564607
inputKey.disambiguatingId);
565608

609+
case ExecProviderResolution::DynamicTraversal::
610+
IncomingConnectionOwningAttributes:
611+
return _TraverseToIncomingConnectionOwningAttributes(
612+
inputKey.computationName,
613+
inputKey.resultType,
614+
inputKey.disambiguatingId);
615+
566616
case ExecProviderResolution::DynamicTraversal::NamespaceAncestor:
567617
if (!_TraverseToNamespaceAncestor(
568618
inputKey.computationName,

pxr/exec/exec/providerResolution.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ struct ExecProviderResolution {
5050
/// they target.
5151
ConnectionTargetedObjects,
5252

53+
/// Find providers by traversing incoming attribute connections to the
54+
/// attributes that own them.
55+
IncomingConnectionOwningAttributes,
56+
5357
/// Find the provider by traversing upward in namespace
5458
NamespaceAncestor,
5559
};

pxr/exec/exec/systemChangeProcessor.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,18 @@ ExecSystem::_ChangeProcessor::DidResync(const SdfPath &path)
5353
{
5454
// TODO: Resyncs on an object may trigger edit reasons on related objects.
5555
// (E.g. resync on /Prim.attr would trigger a ChangedPropertyList on /Prim)
56-
// That would be handled here. For now, resync is the only supported edit
57-
// reason.
56+
// That would be handled here.
5857
_state->uncompiler.UncompileForSceneChange(
5958
path, EsfEditReason::ResyncedObject);
6059
}
6160

61+
void
62+
ExecSystem::_ChangeProcessor::DidChangeIncomingConnections(const SdfPath &path)
63+
{
64+
_state->uncompiler.UncompileForSceneChange(
65+
path, EsfEditReason::ChangedIncomingConnections);
66+
}
67+
6268
void
6369
ExecSystem::_ChangeProcessor::DidChangeInfoOnly(
6470
const SdfPath &path,

pxr/exec/exec/systemChangeProcessor.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ class ExecSystem::_ChangeProcessor
5454
const SdfPath &path,
5555
const TfTokenVector &changedFields);
5656

57+
/// Notifies the ExecSystem that the set of attribute connections that
58+
/// target a scene object has changed.
59+
///
60+
EXEC_API
61+
void DidChangeIncomingConnections(const SdfPath &path);
62+
5763
private:
5864
// Processes accumulated state from changes before the processor goes out of
5965
// scope.
@@ -70,4 +76,4 @@ class ExecSystem::_ChangeProcessor
7076

7177
PXR_NAMESPACE_CLOSE_SCOPE
7278

73-
#endif
79+
#endif

0 commit comments

Comments
 (0)