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
86 template <typename T>
88 return CheckForRegistration(typeid(T));
89 }
90
95 VDF_API
96 static TfType CheckForRegistration(const std::type_info &typeInfo);
97
103 VDF_API
105
108 VDF_API
109 static void FillVector(TfType type, size_t numElements, VdfVector *vector);
110
111private:
112
115
116 // Provides functionality common to both overloads of Define().
117 template <typename T>
118 void _Define(const T &fallback, TfType scalarType);
119
120 // A very simple type-erased container used to hold fallback values.
121 class _Value;
122
123 // Inserts fallback as the value for type.
124 //
125 // Attempting to register a fallback with unknown type is a fatal error.
126 //
127 VDF_API
128 std::pair<const _Value &, bool> _InsertRegistration(
129 TfType type, _Value &&fallback);
130
131 // Helper method to share code for looking up fallback values that is
132 // common to all instantiations of GetFallback.
133 //
134 VDF_API
135 const _Value &_GetFallback(TfType type) const;
136
137 // Typed implementation of CreateEmptyVector.
138 template <typename T>
139 struct _CreateEmptyVector {
140 static VdfVector Call() {
141 return VdfTypedVector<T>();
142 }
143 };
144
145 // Typed implementation of FillVector.
146 template <typename T>
147 struct _FillVector {
148 static bool Call(
149 const _Value &fallback, size_t numElements, VdfVector *vector);
150 };
151
152private:
153
154 // Map of (scalar) value types to their type-erased fallback values and
155 // mutex that serializes access to it.
156 //
157 // Writes occur once per type definition but reads occur many times during
158 // various phases of execution.
159 std::map<TfType, _Value> _fallbackMap;
160 mutable tbb::spin_rw_mutex _fallbackMapMutex;
161
162 VdfTypeDispatchTable<_CreateEmptyVector> _createEmptyVectorTable;
163 VdfTypeDispatchTable<_FillVector> _fillVectorDispatchTable;
164};
165
166// A very simple type-erased container.
167//
168// This provides only functionality that is relevant to storing execution
169// fallback values. Other, more general type-erased containers can cause
170// substantial compilation time increases because we store many types and
171// their unused functionality must still be emitted.
172//
173class VdfExecutionTypeRegistry::_Value
174{
175public:
176 template <typename T>
177 explicit _Value(const T &fallback)
178 : _ptr(TfAnyUniquePtr::New(fallback))
179 {}
180
181 // Returns a reference to the held value.
182 //
183 // There is no checked Get. The registry must ensure that nobody is
184 // able to register values for the wrong type.
185 //
186 template <typename T>
187 const T & UncheckedGet() const {
188 return *static_cast<const T*>(_ptr.Get());
189 }
190
191 // Compares values for types that define equality comparision; returns
192 // true if not equality comparable.
193 //
194 template <typename T>
195 bool Equals(const T &rhs) const {
196 if constexpr (VdfIsEqualityComparable<T>) {
197 return UncheckedGet<T>() == rhs;
198 }
199 else {
200 return true;
201 }
202 }
203
204private:
205 TfAnyUniquePtr _ptr;
206};
207
208template <typename T>
209TfType
211{
212 TfAutoMallocTag mallocTag("Vdf", "VdfExecutionTypeRegistry::Define");
213 // Define type with Tf if needed.
214 TfType scalarType = TfType::Find<T>();
215 if (scalarType.IsUnknown() ||
216 !TF_VERIFY(scalarType.GetTypeid() != typeid(void),
217 "Type '%s' was declared but not defined",
218 scalarType.GetTypeName().c_str())) {
219
220 scalarType = TfType::Define<T>();
221 }
222
223 VdfExecutionTypeRegistry::GetInstance()._Define(fallback, scalarType);
224 return scalarType;
225}
226
227template <typename T, typename B>
228TfType
230{
231 TfAutoMallocTag mallocTag("Vdf", "VdfExecutionTypeRegistry::Define");
232 // Define type with Tf if needed.
233 TfType scalarType = TfType::Find<T>();
234 if (scalarType.IsUnknown() ||
235 !TF_VERIFY(scalarType.GetTypeid() != typeid(void),
236 "Type '%s' was declared but not defined",
237 scalarType.GetTypeName().c_str())) {
238
239 scalarType = TfType::Define<T, B>();
240 }
241
242 GetInstance()._Define(fallback, scalarType);
243 return scalarType;
244}
245
246template <typename T>
247void
248VdfExecutionTypeRegistry::_Define(const T &fallback, TfType scalarType)
249{
250 // Use the presence of an entry in the fallback map to avoid redundant
251 // registration with other maps in cases where multiple plugins register
252 // the same type, which is allowed.
253 if (const auto [registeredFallback, inserted] = _InsertRegistration(
254 scalarType, _Value(fallback)); !inserted) {
255 TF_VERIFY(
256 registeredFallback.Equals(fallback),
257 "Type %s registered more than once with different fallback "
258 "values.",
259 scalarType.GetTypeName().c_str());
260 return;
261 }
262
263 VdfOutputSpec::_RegisterType<T>();
264 _createEmptyVectorTable.RegisterType<T>();
265 _fillVectorDispatchTable.RegisterType<T>();
266}
267
268template <typename T>
269const T &
271{
272 const _Value &fallback = _GetFallback(TfType::Find<T>());
273 return fallback.UncheckedGet<T>();
274}
275
276template <typename T>
277bool
278VdfExecutionTypeRegistry::_FillVector<T>::Call(
279 const _Value &fallback,
280 size_t numElements,
281 VdfVector *vector)
282{
283 const T &fallbackValue = fallback.UncheckedGet<T>();
284
285 vector->Resize<T>(numElements);
287 vector->GetReadWriteAccessor<T>();
288 for (size_t i = 0; i < numElements; ++i) {
289 accessor[i] = fallbackValue;
290 }
291
292 return true;
293}
294
295PXR_NAMESPACE_CLOSE_SCOPE
296
297#endif
A simple type-erased container that provides only destruction, moves and immutable,...
Definition: anyUniquePtr.h:27
Scoped (i.e.
Definition: mallocTag.h:249
Manage a single instance of an object (see.
Definition: singleton.h:105
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 VDF_API void FillVector(TfType type, size_t numElements, VdfVector *vector)
Fills vector with the fallback value registered for the given 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 TfType CheckForRegistration(const std::type_info &typeInfo)
Checks if ti is defined as an execution value type.
static TfType CheckForRegistration()
Checks if T is defined as an execution value type.
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:403
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:449
#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.