Skip to content

Commit aa9efa2

Browse files
adamrwoodburypixar-oss
authored andcommitted
OpenExec: Implement dispatched prim computations
A dispatched prim computation is only visible to computations on the prim that does the dispatching. I.e., the computation registrations for a schema can include dispatched computations and inputs to computations registered on the same schema can request the dispatched computations, using the input option FallsBackToDispatched(), from *other provider prims* and find them there. *Other schema computation registrations* are not be able to find the dispatched computations, however. Dispatched computations can be restricted as to which prims they can dispatch onto, based on the typed and applied schemas of a given target prims. The second parameter to the DispatchedPrimComputation registration function can be used to specify zero or more schema types (as TfType%s). If any types are given, the dispatched computation will only be found on a target prim if that prim's typed schema type (or one of its base type) is among the given schema types or if the fully expanded list of API schemas applied to the prim includes a schema that is among the given schema types. (Internal change: 2371457)
1 parent 1e064a1 commit aa9efa2

30 files changed

+1451
-122
lines changed

pxr/exec/exec/computationBuilders.cpp

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ PXR_NAMESPACE_OPEN_SCOPE
1616
// Exec_ComputationBuilderValueSpecifierBase
1717
//
1818

19+
// This struct exists just to keep Exec_InputKey private.
1920
struct Exec_ComputationBuilderValueSpecifierBase::_Data
2021
{
2122
Exec_InputKey inputKey;
@@ -26,13 +27,15 @@ Exec_ComputationBuilderValueSpecifierBase(
2627
const TfToken &computationName,
2728
TfType resultType,
2829
ExecProviderResolution &&providerResolution,
29-
const TfToken &inputName)
30+
const TfToken &inputName,
31+
bool fallsBackToDispatched)
3032
: _data(
3133
new _Data{
3234
inputName,
3335
computationName,
3436
resultType,
3537
std::move(providerResolution),
38+
fallsBackToDispatched,
3639
/* optional */ true})
3740
{}
3841

@@ -43,8 +46,7 @@ Exec_ComputationBuilderValueSpecifierBase(
4346
{}
4447

4548
Exec_ComputationBuilderValueSpecifierBase::
46-
~Exec_ComputationBuilderValueSpecifierBase()
47-
{}
49+
~Exec_ComputationBuilderValueSpecifierBase() = default;
4850

4951
void
5052
Exec_ComputationBuilderValueSpecifierBase::_SetInputName(
@@ -60,6 +62,13 @@ Exec_ComputationBuilderValueSpecifierBase::_SetOptional(
6062
_data->inputKey.optional = optional;
6163
}
6264

65+
void
66+
Exec_ComputationBuilderValueSpecifierBase::_SetFallsBackToDispatched(
67+
const bool fallsBackToDispatched)
68+
{
69+
_data->inputKey.fallsBackToDispatched = true;
70+
}
71+
6372
void
6473
Exec_ComputationBuilderValueSpecifierBase::_GetInputKey(
6574
Exec_InputKey *const inputKey) const
@@ -75,35 +84,57 @@ struct Exec_PrimComputationBuilder::_Data
7584
{
7685
_Data(
7786
const TfType schemaType_,
78-
const TfToken &computationName_)
87+
const TfToken &computationName_,
88+
const bool dispatched_,
89+
ExecDispatchesOntoSchemas &&dispatchesOntoSchemas_)
7990
: schemaType(schemaType_)
8091
, computationName(computationName_)
92+
, dispatched(dispatched_)
93+
, dispatchesOntoSchemas(std::move(dispatchesOntoSchemas_))
8194
, inputKeys(Exec_InputKeyVector::MakeShared())
8295
{
8396
}
8497

8598
const TfType schemaType;
8699
const TfToken computationName;
100+
const bool dispatched;
101+
ExecDispatchesOntoSchemas dispatchesOntoSchemas;
87102
TfType resultType;
88103
ExecCallbackFn callback;
89104
Exec_InputKeyVectorRefPtr inputKeys;
90105
};
91106

92107
Exec_PrimComputationBuilder::Exec_PrimComputationBuilder(
93108
const TfType schemaType,
94-
const TfToken &computationName)
95-
: _data(std::make_unique<_Data>(schemaType, computationName))
109+
const TfToken &computationName,
110+
const bool dispatched,
111+
ExecDispatchesOntoSchemas &&dispatchesOntoSchemas)
112+
: _data(std::make_unique<_Data>(
113+
schemaType, computationName,
114+
dispatched, std::move(dispatchesOntoSchemas)))
96115
{
97116
}
98117

99118
Exec_PrimComputationBuilder::~Exec_PrimComputationBuilder()
100119
{
120+
// A null pointer indicates the computation is not dispatched; otherwise,
121+
// the pointed-to vector contains the list of the schemas onto which the
122+
// dispatched computation dispatches, which can be empty, to indicate that
123+
// the computation dispatches onto all prims.
124+
std::unique_ptr<ExecDispatchesOntoSchemas> dispatchesOntoSchemas;
125+
if (_data->dispatched) {
126+
dispatchesOntoSchemas.reset(
127+
new ExecDispatchesOntoSchemas(
128+
std::move(_data->dispatchesOntoSchemas)));
129+
}
130+
101131
Exec_DefinitionRegistry::ComputationBuilderAccess::_RegisterPrimComputation(
102132
_data->schemaType,
103133
_data->computationName,
104134
_data->resultType,
105135
std::move(_data->callback),
106-
std::move(_data->inputKeys));
136+
std::move(_data->inputKeys),
137+
std::move(dispatchesOntoSchemas));
107138
}
108139

109140
void
@@ -145,4 +176,28 @@ Exec_ComputationBuilder::PrimComputation(
145176
return Exec_PrimComputationBuilder(_schemaType, computationName);
146177
}
147178

179+
// Exec_PrimComputationBuilder
180+
// Exec_ComputationBuilder::DispatchedPrimComputation(
181+
// const TfToken &computationName,
182+
// const TfType &ontoSchema)
183+
// {
184+
// return Exec_PrimComputationBuilder(
185+
// _schemaType,
186+
// computationName,
187+
// /* dispatched */ true,
188+
// {ontoSchema});
189+
// }
190+
191+
Exec_PrimComputationBuilder
192+
Exec_ComputationBuilder::DispatchedPrimComputation(
193+
const TfToken &computationName,
194+
ExecDispatchesOntoSchemas &&ontoSchemas)
195+
{
196+
return Exec_PrimComputationBuilder(
197+
_schemaType,
198+
computationName,
199+
/* dispatched */ true,
200+
std::move(ontoSchemas));
201+
}
202+
148203
PXR_NAMESPACE_CLOSE_SCOPE

pxr/exec/exec/computationBuilders.h

Lines changed: 130 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ class Exec_ComputationBuilderValueSpecifierBase
224224
const TfToken &computationName,
225225
TfType resultType,
226226
ExecProviderResolution &&providerResolution,
227-
const TfToken &inputName);
227+
const TfToken &inputName,
228+
bool fallsBackToDispatched);
228229

229230
EXEC_API
230231
Exec_ComputationBuilderValueSpecifierBase(
@@ -240,6 +241,9 @@ class Exec_ComputationBuilderValueSpecifierBase
240241
EXEC_API
241242
void _SetOptional (const bool optional);
242243

244+
EXEC_API
245+
void _SetFallsBackToDispatched(bool fallsBackToDispatched);
246+
243247
private:
244248
// Only computation builders can get the input key.
245249
friend class Exec_PrimComputationBuilder;
@@ -265,12 +269,14 @@ struct Exec_ComputationBuilderComputationValueSpecifier
265269
{
266270
Exec_ComputationBuilderComputationValueSpecifier(
267271
const TfToken &computationName,
268-
TfType resultType,
269-
ExecProviderResolution &&providerResolution)
272+
const TfType resultType,
273+
ExecProviderResolution &&providerResolution,
274+
const bool fallsBackToDispatched = false)
270275
: Exec_ComputationBuilderValueSpecifierBase(
271276
computationName, resultType,
272277
std::move(providerResolution),
273-
computationName)
278+
computationName /* inputName */,
279+
fallsBackToDispatched)
274280
{
275281
}
276282

@@ -339,6 +345,44 @@ struct Exec_ComputationBuilderComputationValueSpecifier
339345
return *this;
340346
}
341347

348+
/// Declares the input can find dispatched computations *if* the requested
349+
/// computation name doesn't match a local computation on the provider.
350+
///
351+
/// \see [DispatchedPrimComputation](#Exec_ComputationBuilder::DispatchedPrimComputation)
352+
///
353+
/// # Example
354+
///
355+
/// ```{.cpp}
356+
/// EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA(MySchemaType)
357+
/// {
358+
/// // Register a dispatched prim computation.
359+
/// self.DispatchedPrimComputation(_tokens->myDispatchedComputation)
360+
/// .Callback<double>(+[](const VdfContext &) { return 11.0; })
361+
///
362+
/// // Register a prim computation that requests the above dispatched
363+
/// // computation via uses relationship targets.
364+
/// self.PrimComputation(_tokens->myComputation)
365+
/// .Callback<double>(+[](const VdfContext &ctx) {
366+
/// const double *const valuePtr =
367+
/// ctx.GetInputValuePtr<double>(
368+
/// _tokens->myDispatchedComputation);
369+
/// return valuePtr ? *valuePtr : -1.0;
370+
/// })
371+
/// .Inputs(
372+
/// Relationship(_tokens->myRelationship)
373+
/// .TargetedObjects<double>(
374+
/// _tokens->myDispatchedComputation)
375+
/// .FallsBackToDispatched())
376+
/// }
377+
/// ```
378+
///
379+
This&
380+
FallsBackToDispatched()
381+
{
382+
_SetFallsBackToDispatched(true);
383+
return *this;
384+
}
385+
342386
/// @}
343387
};
344388

@@ -829,8 +873,71 @@ class Exec_ComputationBuilder
829873
Exec_PrimComputationBuilder
830874
PrimComputation(const TfToken &computationName);
831875

876+
/// Registers a dispatched prim computation named \p computationName.
877+
///
878+
/// A dispatched prim computation is only visible to computations on the
879+
/// prim that does the dispatching. I.e., the computation registrations for
880+
/// a schema can include dispatched computations and inputs to computations
881+
/// registered on the same schema can request the dispatched computations,
882+
/// using the input option FallsBackToDispatched(), from *other provider
883+
/// prims* and find them there. *Other schema computation registrations*
884+
/// will not be able to find the dispatched computations, however.
885+
///
886+
/// Dispatched computations can be restricted as to which prims they can
887+
/// dispatch onto, based on the typed and applied schemas of a given target
888+
/// prim. The second parameter to the DispatchedPrimComputation registration
889+
/// function can be used to specify zero or more schema types (as
890+
/// TfType%s). If any types are given, the dispatched computation will only
891+
/// be found on a target prim if that prim's typed schema type (or one of
892+
/// its base type) is among the given schema types or if the fully expanded
893+
/// list of API schemas applied to the prim includes a schema that is among
894+
/// the given schema types.
895+
///
896+
/// # Example
897+
///
898+
/// ```{.cpp}
899+
/// EXEC_REGISTER_COMPUTATIONS_FOR_SCHEMA(MySchemaType)
900+
/// {
901+
/// // Register a dispatched prim computation that can be found on
902+
/// // scopes.
903+
/// const TfType scopeType = TfType::FindByName("UsdGeomScope");
904+
/// self.DispatchedPrimComputation(_tokens->eleven, scopeType)
905+
/// .Callback<double>(+[](const VdfContext &) { return 11.0; })
906+
///
907+
/// // Register a prim computation that requests the above dispatched
908+
/// // computation via uses relationship targets.
909+
/// self.PrimComputation(_tokens->myComputation)
910+
/// .Callback<double>(+[](const VdfContext &ctx) {
911+
/// const double *const valuePtr =
912+
/// ctx.GetInputValuePtr<double>(_tokens->eleven);
913+
/// return valuePtr ? *valuePtr : -1.0;
914+
/// })
915+
/// .Inputs(
916+
///
917+
/// // This input opts-in to finding dispatched computations.
918+
/// Relationship(_tokens->myRelationship)
919+
/// .TargetedObjects<double>(_tokens->eleven)
920+
/// .FallsBackToDispatched())
921+
/// }
922+
/// ```
923+
///
924+
EXEC_API
925+
Exec_PrimComputationBuilder
926+
DispatchedPrimComputation(
927+
const TfToken &computationName,
928+
ExecDispatchesOntoSchemas &&ontoSchemas);
929+
930+
// Convenience variadic template overload that takes zero or more schema
931+
// types.
932+
template <class... DispatchedOntoSchemaTypes>
933+
Exec_PrimComputationBuilder
934+
DispatchedPrimComputation(
935+
const TfToken &computationName,
936+
DispatchedOntoSchemaTypes &&...schemaTypes);
937+
832938
// XXX:TODO
833-
// AttributeComputation
939+
// - AttributeComputation
940+
// - DispatchedAttributeComputation
834941

835942
/// @}
836943

@@ -849,7 +956,9 @@ class Exec_PrimComputationBuilder
849956
EXEC_API
850957
Exec_PrimComputationBuilder(
851958
TfType schemaType,
852-
const TfToken &computationName);
959+
const TfToken &computationName,
960+
bool dispatched = false,
961+
ExecDispatchesOntoSchemas &&dispatchesOntoSchemas = {});
853962

854963
public:
855964
EXEC_API
@@ -1002,6 +1111,21 @@ Exec_PrimComputationBuilder::_ValidateInputs() {
10021111
"Input is not allowed on a provider of this type.");
10031112
}
10041113

1114+
template <class... DispatchedOntoSchemaTypes>
1115+
Exec_PrimComputationBuilder
1116+
Exec_ComputationBuilder::DispatchedPrimComputation(
1117+
const TfToken &computationName,
1118+
DispatchedOntoSchemaTypes &&...schemaTypes)
1119+
{
1120+
static_assert(
1121+
(std::is_same_v<
1122+
std::decay_t<DispatchedOntoSchemaTypes>, TfType> && ...));
1123+
1124+
return DispatchedPrimComputation(
1125+
computationName,
1126+
{std::forward<DispatchedOntoSchemaTypes>(schemaTypes)...});
1127+
}
1128+
10051129
PXR_NAMESPACE_CLOSE_SCOPE
10061130

10071131
#endif

pxr/exec/exec/computationDefinition.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,10 @@ Exec_ComputationDefinition::GetExtractionType(
3737
return _resultType;
3838
}
3939

40+
bool
41+
Exec_ComputationDefinition::IsDispatched() const
42+
{
43+
return false;
44+
}
45+
4046
PXR_NAMESPACE_CLOSE_SCOPE

pxr/exec/exec/computationDefinition.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class Exec_ComputationDefinition
5454
virtual TfType GetExtractionType(
5555
const EsfObjectInterface &providerObject) const;
5656

57+
/// Returns `true` if this computation is a dispatched computation.
58+
virtual bool IsDispatched() const;
59+
5760
/// Returns the keys that indicate how to source the input values required
5861
/// to evaluate the computation when the provider is \p providerObject.
5962
///

0 commit comments

Comments
 (0)