Loading...
Searching...
No Matches
executionTypeRegistry.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_VDF_EXECUTION_TYPE_REGISTRY_H
8#define PXR_EXEC_VDF_EXECUTION_TYPE_REGISTRY_H
9
11
12#include "pxr/pxr.h"
13
14#include "pxr/exec/vdf/api.h"
17
18#include "pxr/base/tf/anyUniquePtr.h"
21#include "pxr/base/tf/type.h"
22
23#include <tbb/spin_rw_mutex.h>
24
25#include <map>
26#include <utility>
27
28PXR_NAMESPACE_OPEN_SCOPE
29
38{
39public:
40
41 // Non-copyable
42 //
44 VdfExecutionTypeRegistry& operator=(
45 const VdfExecutionTypeRegistry &) = delete;
46
47 VDF_API
49
52 VDF_API
54
64 template <typename T>
65 static TfType Define(const T &fallback);
66
70 template <typename T, typename B>
71 static TfType Define(const T &fallback);
72
77 template <typename T>
78 inline const T &GetFallback() const;
79
89 template <typename T>
91 const char *const additionalErrorMsg=nullptr) {
92 return CheckForRegistration(typeid(T), additionalErrorMsg);
93 }
94
99 VDF_API
101 const std::type_info &typeInfo,
102 const char *const additionalErrorMsg);
103
109 VDF_API
111
114 VDF_API
115 static void FillVector(TfType type, size_t numElements, VdfVector *vector);
116
117private:
118
121
122 // Provides functionality common to both overloads of Define().
123 template <typename T>
124 void _Define(const T &fallback, TfType scalarType);
125
126 // A very simple type-erased container used to hold fallback values.
127 class _Value;
128
129 // Inserts fallback as the value for type.
130 //
131 // Attempting to register a fallback with unknown type is a fatal error.
132 //
133 VDF_API
134 std::pair<const _Value &, bool> _InsertRegistration(
135 TfType type, _Value &&fallback);
136
137 // Helper method to share code for looking up fallback values that is
138 // common to all instantiations of GetFallback.
139 //
140 VDF_API
141 const _Value &_GetFallback(TfType type) const;
142
143 // Typed implementation of CreateEmptyVector.
144 template <typename T>
145 struct _CreateEmptyVector {
146 static VdfVector Call() {
147 return VdfTypedVector<T>();
148 }
149 };
150
151 // Typed implementation of FillVector.
152 template <typename T>
153 struct _FillVector {
154 static bool Call(
155 const _Value &fallback, size_t numElements, VdfVector *vector);
156 };
157
158private:
159
160 // Map of (scalar) value types to their type-erased fallback values and
161 // mutex that serializes access to it.
162 //
163 // Writes occur once per type definition but reads occur many times during
164 // various phases of execution.
165 std::map<TfType, _Value> _fallbackMap;
166 mutable tbb::spin_rw_mutex _fallbackMapMutex;
167
168 VdfTypeDispatchTable<_CreateEmptyVector> _createEmptyVectorTable;
169 VdfTypeDispatchTable<_FillVector> _fillVectorDispatchTable;
170};
171
172// A very simple type-erased container.
173//
174// This provides only functionality that is relevant to storing execution
175// fallback values. Other, more general type-erased containers can cause
176// substantial compilation time increases because we store many types and
177// their unused functionality must still be emitted.
178//
179class VdfExecutionTypeRegistry::_Value
180{
181public:
182 template <typename T>
183 explicit _Value(const T &fallback)
184 : _ptr(TfAnyUniquePtr::New(fallback))
185 {}
186
187 // Returns a reference to the held value.
188 //
189 // There is no checked Get. The registry must ensure that nobody is
190 // able to register values for the wrong type.
191 //
192 template <typename T>
193 const T & UncheckedGet() const {
194 return *static_cast<const T*>(_ptr.Get());
195 }
196
197 // Compares values for types that define equality comparision; returns
198 // true if not equality comparable.
199 //
200 template <typename T>
201 bool Equals(const T &rhs) const {
202 if constexpr (VdfIsEqualityComparable<T>) {
203 return UncheckedGet<T>() == rhs;
204 }
205 else {
206 return true;
207 }
208 }
209
210private:
211 TfAnyUniquePtr _ptr;
212};
213
214template <typename T>
215TfType
217{
218 TfAutoMallocTag mallocTag("Vdf", "VdfExecutionTypeRegistry::Define");
219 // Define type with Tf if needed.
220 TfType scalarType = TfType::Find<T>();
221 if (scalarType.IsUnknown() ||
222 !TF_VERIFY(scalarType.GetTypeid() != typeid(void),
223 "Type '%s' was declared but not defined",
224 scalarType.GetTypeName().c_str())) {
225
226 scalarType = TfType::Define<T>();
227 }
228
229 VdfExecutionTypeRegistry::GetInstance()._Define(fallback, scalarType);
230 return scalarType;
231}
232
233template <typename T, typename B>
234TfType
236{
237 TfAutoMallocTag mallocTag("Vdf", "VdfExecutionTypeRegistry::Define");
238 // Define type with Tf if needed.
239 TfType scalarType = TfType::Find<T>();
240 if (scalarType.IsUnknown() ||
241 !TF_VERIFY(scalarType.GetTypeid() != typeid(void),
242 "Type '%s' was declared but not defined",
243 scalarType.GetTypeName().c_str())) {
244
245 scalarType = TfType::Define<T, B>();
246 }
247
248 GetInstance()._Define(fallback, scalarType);
249 return scalarType;
250}
251
252template <typename T>
253void
254VdfExecutionTypeRegistry::_Define(const T &fallback, TfType scalarType)
255{
256 // Use the presence of an entry in the fallback map to avoid redundant
257 // registration with other maps in cases where multiple plugins register
258 // the same type, which is allowed.
259 if (const auto [registeredFallback, inserted] = _InsertRegistration(
260 scalarType, _Value(fallback)); !inserted) {
261 TF_VERIFY(
262 registeredFallback.Equals(fallback),
263 "Type %s registered more than once with different fallback "
264 "values.",
265 scalarType.GetTypeName().c_str());
266 return;
267 }
268
269 VdfOutputSpec::_RegisterType<T>();
270 _createEmptyVectorTable.RegisterType<T>();
271 _fillVectorDispatchTable.RegisterType<T>();
272}
273
274template <typename T>
275const T &
277{
278 const _Value &fallback = _GetFallback(TfType::Find<T>());
279 return fallback.UncheckedGet<T>();
280}
281
282template <typename T>
283bool
284VdfExecutionTypeRegistry::_FillVector<T>::Call(
285 const _Value &fallback,
286 size_t numElements,
287 VdfVector *vector)
288{
289 const T &fallbackValue = fallback.UncheckedGet<T>();
290
291 vector->Resize<T>(numElements);
293 vector->GetReadWriteAccessor<T>();
294 for (size_t i = 0; i < numElements; ++i) {
295 accessor[i] = fallbackValue;
296 }
297
298 return true;
299}
300
301PXR_NAMESPACE_CLOSE_SCOPE
302
303#endif
A simple type-erased container that provides only destruction, moves and immutable,...
Definition: anyUniquePtr.h:27
Scoped (i.e.
Definition: mallocTag.h:251
Manage a single instance of an object (see.
Definition: singleton.h:107
TfType represents a dynamic runtime type.
Definition: type.h:48
TF_API const std::string & GetTypeName() const
Return the machine-independent name for this type.
TF_API const std::type_info & GetTypeid() const
Return a C++ RTTI type_info for this type.
bool IsUnknown() const
Return true if this is the unknown type, representing a type unknown to the TfType system.
Definition: type.h:374
Manages low-level value type functionality used within execution.
static TfType CheckForRegistration(const char *const additionalErrorMsg=nullptr)
Checks if T is defined as an execution value type.
static VDF_API void FillVector(TfType type, size_t numElements, VdfVector *vector)
Fills vector with the fallback value registered for the given type.
static VDF_API TfType CheckForRegistration(const std::type_info &typeInfo, const char *const additionalErrorMsg)
Checks if ti is defined as an execution value type.
static TfType Define(const T &fallback)
Registers T with execution's runtime type dispatch system.
const T & GetFallback() const
Returns the registered fallback value for T from the registry.
static VDF_API VdfVector CreateEmptyVector(TfType type)
Create an empty VdfVector holding empty data of the given TfType.
static VDF_API VdfExecutionTypeRegistry & GetInstance()
Returns the VdfExecutionTypeRegistry singleton instance.
Dispatches calls to template instantiations based on a TfType that is determined at runtime.
bool RegisterType()
Register an additional type with the type dispatch table.
A VdfTypedVector implements a VdfVector with a specific type.
Definition: typedVector.h:23
A read/write accessor for low-level access to the contents of the VdfVector.
Definition: vector.h:410
This class is used to abstract away knowledge of the cache data used for each node.
Definition: vector.h:56
void Resize(size_t size)
Allocates space for size number of elements.
Definition: vector.h:218
ReadWriteAccessor< TYPE > GetReadWriteAccessor() const
GetReadWriteAccessor() allows low level access to the content of the VdfVector via the Vdf_VectorData...
Definition: vector.h:456
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:266
Manage a single instance of an object.