HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
typeRegistry.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_EXEC_TYPE_REGISTRY_H
8 #define PXR_EXEC_EXEC_TYPE_REGISTRY_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/exec/api.h"
17 #include "pxr/exec/vdf/mask.h"
19 #include "pxr/exec/vdf/vector.h"
20 
21 #include "pxr/base/tf/singleton.h"
22 #include "pxr/base/tf/type.h"
23 #include "pxr/base/vt/array.h"
24 #include "pxr/base/vt/traits.h"
25 #include "pxr/base/vt/types.h"
26 #include "pxr/base/vt/value.h"
27 
28 #include <tbb/concurrent_unordered_map.h>
29 
30 #include <algorithm>
31 
33 
34 class Exec_ValueExtractor;
35 class VdfMask;
36 
37 /// Singleton used to register and access value types used by exec computations.
38 ///
39 /// Value types that are used for exec computation input and output values must
40 /// be registered with this registry.
41 ///
42 /// The registry is initialized with all value types that Sdf suports for
43 /// attribute and metadata values.
44 ///
46 {
47 public:
48  ExecTypeRegistry(ExecTypeRegistry const&) = delete;
50 
52 
53  /// Provides access to the singleton instance, first ensuring it is
54  /// constructed.
55  ///
56  EXEC_API
57  static const ExecTypeRegistry &GetInstance();
58 
59  /// Registers \p ValueType as a value type that exec computations can use
60  /// for input and output values, with the fallback value \p fallback.
61  ///
62  /// In any circumstance that requires a fallback value, i.e., when an
63  /// arbitrary value of type \p ValueType must be produced, \p fallback will
64  /// be used.
65  ///
66  /// All types that can be used to author attribute and metadata values in
67  /// USD are known to exec by default. User-defined types must be registered
68  /// using this function.
69  ///
70  /// \note
71  /// Exec value types must be equality comparable.
72  ///
73  /// \warning
74  /// If a given \p ValueType is registered more than once, all calls must
75  /// specify the same \p fallback; otherwise, which fallback value wins is
76  /// indeterminate. If an equality operator is defined for \p ValueType, that
77  /// operator will be used to verify that all fallback values have the same
78  /// value. Otherwise, multiple registrations are allowed, with no
79  /// verification that the fallback values match.
80  ///
81  /// # Example
82  ///
83  /// ```cpp
84  /// struct CustomType {
85  /// int i;
86  /// std::string s;
87  ///
88  /// friend
89  /// bool operator==(const CustomType &a, const CustomType &b) {
90  /// return a.i == b.i && a.s == b.s;
91  /// }
92  /// };
93  ///
94  /// TF_REGISTRY_FUNCTION(ExecTypeRegistry)
95  /// {
96  /// ExecTypeRegistry::RegisterType(CustomType{});
97  /// }
98  /// ```
99  ///
100  template <typename ValueType>
101  static void RegisterType(const ValueType &fallback) {
102  static_assert(
104  "VtArray is not a supported execution value type.");
105  static_assert(
106  VdfIsEqualityComparable<ValueType>,
107  "Equality comparison is required for execution value types.");
108  _GetInstanceForRegistration()._RegisterType(fallback);
109  }
110 
111  /// Confirms that \p ValueType has been registered.
112  ///
113  /// If \p ValueType has been registered with the ExecTypeRegistry, the
114  /// corresponding TfType is returned.
115  ///
116  /// \warning
117  /// If \p ValueType has not been registerd, a fatal error is emitted.
118  ///
119  template <typename ValueType>
121  return VdfExecutionTypeRegistry::CheckForRegistration<ValueType>(
122  "Use ExecTypeRegistry::RegisterType<T>() to register execution "
123  "value types.");
124  }
125 
126  /// Construct a VdfVector whose value is copied from \p value.
127  EXEC_API
128  VdfVector CreateVector(const VtValue &value) const;
129 
130  /// Returns an extractor that produces a VtValue from values held in
131  /// execution.
132  ///
133  /// Note that \p type is the type that should be held in the VtValue
134  /// extraction result. This is distinct from the execution data-flow
135  /// type.
136  ///
137  EXEC_API
138  Exec_ValueExtractor GetExtractor(TfType type) const;
139 
140 private:
141  // Only TfSingleton can create instances.
143 
144  // Provides access for registraion of types only.
145  EXEC_API
146  static ExecTypeRegistry& _GetInstanceForRegistration();
147 
149 
150  template <typename ValueType>
151  void _RegisterType(ValueType const &fallback);
152 
153  template <typename T>
154  struct _CreateVector {
155  // Interface for VdfTypeDispatchTable.
156  static VdfVector Call(const VtValue &value) {
157  return Create(value.UncheckedGet<T>());
158  }
159  // Typed implementation of CreateVector.
160  //
161  // This is separate from Call so that it can be shared with the
162  // Vt known type optimization in CreateVector.
163  static VdfVector Create(const T &value);
164  };
165 
166  // Returns the appropriate value extractor for T.
167  //
168  // When T is a VtArray type, the returned extractor expects a VdfVector
169  // holding T::value_type elements as its input.
170  //
171  template <typename T>
172  static auto _MakeExtractorFunction();
173 
174  // Specify that values of \p type should be extracted using \p function.
175  EXEC_API
176  void _RegisterExtractor(
177  TfType type,
178  Exec_ValueExtractorFunction &extractor);
179 
180 private:
181 
183 
184  // Type-erased conversions from VdfVector to VtValue.
185  //
186  // Inside of execution, there is no distinction between a scalar value and
187  // an array value of length 1. However, systems that interact with
188  // execution may desire single values be returned directly in VtValue or
189  // as a VtValue holding a VtArray depending on the context. The type key
190  // specifies the type held in the resulting VtValue. There are separate
191  // extractors for T and VtArray<T> but they both accepts VdfVectors
192  // holding T.
193  //
194  // Note that this must support the possibility that one thread is querying
195  // extractors at the same time that another thread is registering
196  // additional types.
197  //
198  tbb::concurrent_unordered_map<TfType, Exec_ValueExtractor, TfHash>
199  _extractors;
200 };
201 
202 template <typename ValueType>
203 void
204 ExecTypeRegistry::_RegisterType(ValueType const &fallback)
205 {
206  const TfType type = VdfExecutionTypeRegistry::Define(fallback);
207 
208  // CreateVector has internal handling for value types known to Vt so we do
209  // not need to register them here.
210  if constexpr (!VtIsKnownValueType<ValueType>()) {
211  _createVector.RegisterType<ValueType>();
212  }
213 
214  _RegisterExtractor(type, *+_MakeExtractorFunction<ValueType>());
215 }
216 
217 template <typename T>
218 VdfVector
219 ExecTypeRegistry::_CreateVector<T>::Create(const T &value)
220 {
221  if constexpr (!VtIsArray<T>::value) {
223  v.Set(value);
224  return v;
225  }
226  else {
227  using ElementType = typename T::value_type;
228 
229  const size_t size = value.size();
230 
231  Vdf_BoxedContainer<ElementType> execValue(size);
232  std::copy_n(value.cdata(), size, execValue.data());
233 
235  v.Set(std::move(execValue));
236  return v;
237  }
238 }
239 
240 template <typename T>
241 auto
242 ExecTypeRegistry::_MakeExtractorFunction()
243 {
244  if constexpr (!VtIsArray<T>::value) {
245  return [](const VdfVector &v, const VdfMask::Bits &mask) {
247  v.GetReadAccessor<T>();
248 
249  if (access.IsEmpty()) {
250  TF_VERIFY(mask.GetNumSet() == 0);
251  return VtValue();
252  }
253 
254  if (!TF_VERIFY(mask.GetNumSet() == 1)) {
255  return VtValue();
256  }
257 
258  const int offset = mask.GetFirstSet();
259  return VtValue(access[offset]);
260  };
261  }
262  else {
263  return [](const VdfVector &v, const VdfMask::Bits &mask) {
264  using ElementType = typename T::value_type;
265 
266  if (!TF_VERIFY(mask.AreContiguouslySet())) {
267  return VtValue();
268  }
269 
270  const VdfVector::ReadAccessor access =
271  v.GetReadAccessor<ElementType>();
272 
273  const int offset = mask.GetFirstSet();
274  const size_t numValues = access.IsBoxed()
275  ? access.GetNumValues()
276  : mask.GetNumSet();
277  return VtValue(v.ExtractAsVtArray<ElementType>(numValues, offset));
278  };
279  }
280 }
281 
283 
284 #endif
void Set(TYPE &&data)
Definition: vector.h:162
T const & UncheckedGet() const &
Definition: value.h:1046
const GLdouble * v
Definition: glcorearb.h:837
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
A VdfMask is placed on connections to specify the data flowing through them.
Definition: mask.h:36
uint64 value_type
Definition: GA_PrimCompat.h:29
Fast, compressed bit array which is capable of performing logical operations without first decompress...
VtArray< T > ExtractAsVtArray(const size_t size, const int offset) const
Definition: vector.h:377
static TfType Define(const T &fallback)
VtValue(const VdfVector &, const VdfMask::Bits &) Exec_ValueExtractorFunction
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
GLintptr offset
Definition: glcorearb.h:665
GLuint GLint GLboolean GLint GLenum access
Definition: glcorearb.h:2222
EXEC_API Exec_ValueExtractor GetExtractor(TfType type) const
GLint GLuint mask
Definition: glcorearb.h:124
#define EXEC_API
Definition: api.h:25
ExecTypeRegistry & operator=(ExecTypeRegistry const &)=delete
static EXEC_API const ExecTypeRegistry & GetInstance()
A trait to detect instantiations of VtArray, specialized in array.h.
Definition: traits.h:22
TfType CheckForRegistration() const
Definition: typeRegistry.h:120
GLsizeiptr size
Definition: glcorearb.h:664
ReadAccessor< TYPE > GetReadAccessor() const
Definition: vector.h:521
EXEC_API VdfVector CreateVector(const VtValue &value) const
Construct a VdfVector whose value is copied from value.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
Definition: type.h:47
static void RegisterType(const ValueType &fallback)
Definition: typeRegistry.h:101
bool IsBoxed() const
Definition: vector.h:494
size_t GetNumValues() const
Definition: vector.h:489
bool IsEmpty() const
Definition: vector.h:485
bool ValueType
Definition: NanoVDB.h:5729
Definition: value.h:89