7#ifndef PXR_USD_IMAGING_USD_IMAGING_RESOLVED_ATTRIBUTE_CACHE_H
8#define PXR_USD_IMAGING_USD_IMAGING_RESOLVED_ATTRIBUTE_CACHE_H
13#include "pxr/usdImaging/usdImaging/api.h"
15#include "pxr/usd/usd/primRange.h"
17#include "pxr/usd/sdf/path.h"
24#include <tbb/concurrent_unordered_map.h>
27PXR_NAMESPACE_OPEN_SCOPE
51template<
typename Strategy,
typename ImplData=
bool>
52class UsdImaging_ResolvedAttributeCache
56 using _CacheMap = tbb::concurrent_unordered_map<UsdPrim, _Entry, TfHash>;
58 typedef typename Strategy::value_type value_type;
59 typedef typename Strategy::query_type query_type;
61 using ValueOverridesMap = TfHashMap<UsdPrim, value_type, TfHash>;
64 explicit UsdImaging_ResolvedAttributeCache(
66 ImplData *implData=
nullptr,
67 const ValueOverridesMap valueOverrides=ValueOverridesMap())
69 , _rootPath(
SdfPath::AbsoluteRootPath())
70 , _cacheVersion(_GetInitialCacheVersion())
71 , _valueOverrides(valueOverrides)
77 UsdImaging_ResolvedAttributeCache()
79 , _rootPath(
SdfPath::AbsoluteRootPath())
84 ~UsdImaging_ResolvedAttributeCache()
92 value_type GetValue(
const UsdPrim& prim)
const
97 "which is not within the specified root: %s",
99 _rootPath.GetString().c_str());
100 return Strategy::MakeDefault();
103 return *_GetValue(prim);
110 GetQuery(
const UsdPrim& prim)
const {
111 return &_GetCacheEntryForPrim(prim)->query;
117 _cacheVersion = _GetInitialCacheVersion();
127 if (Strategy::ValueMightBeTimeVarying()) {
149 void SetRootPath(
const SdfPath& rootPath) {
156 if (rootPath == _rootPath)
160 _rootPath = rootPath;
165 const SdfPath & GetRootPath()
const {
return _rootPath; }
177 void UpdateValueOverrides(
const ValueOverridesMap &valueOverrides,
178 const std::vector<UsdPrim> &overridesToRemove,
179 std::vector<SdfPath> *dirtySubtreeRoots)
183 if (valueOverrides.empty() && overridesToRemove.empty())
186 ValueOverridesMap valueOverridesToProcess;
187 SdfPathVector processedOverridePaths;
189 const UsdPrim &prim = it->first;
190 const value_type &value = it->second;
194 if (*_GetValue(prim) == value)
197 valueOverridesToProcess[prim] = value;
201 const UsdPrim &prim = it->first;
202 const value_type &value = it->second;
209 bool isDescendantOfProcessedOverride =
false;
210 for (
const SdfPath &processedPath : processedOverridePaths) {
212 isDescendantOfProcessedOverride =
true;
219 if (!isDescendantOfProcessedOverride) {
221 if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
222 entry->version = _GetInvalidVersion();
225 processedOverridePaths.push_back(prim.
GetPath());
226 dirtySubtreeRoots->push_back(prim.
GetPath());
230 _valueOverrides[prim] = value;
233 for (
const UsdPrim &prim : overridesToRemove) {
236 size_t numErased = _valueOverrides.erase(prim);
239 if (numErased == 0) {
243 bool isDescendantOfProcessedOverride =
false;
244 for (
const SdfPath &processedPath : processedOverridePaths) {
246 isDescendantOfProcessedOverride =
true;
253 if (!isDescendantOfProcessedOverride) {
255 if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
256 entry->version = _GetInvalidVersion();
259 dirtySubtreeRoots->push_back(prim.
GetPath());
260 processedOverridePaths.push_back(prim.
GetPath());
271 : value(Strategy::MakeDefault())
272 , version(_GetInitialEntryVersion())
275 _Entry(
const query_type & query_,
276 const value_type& value_,
283 _Entry(
const _Entry &other)
287 version.store(other.version.load());
290 _Entry(_Entry &&other)
291 : query(
std::move(other.query))
292 , value(
std::move(other.value))
294 version.store(other.version.load());
299 std::atomic<unsigned> version;
303 unsigned _GetValidVersion()
const {
return _cacheVersion + 1; }
306 unsigned _GetInvalidVersion()
const {
return _cacheVersion - 1; }
309 static unsigned _GetInitialCacheVersion() {
return 1; }
310 static unsigned _GetInitialEntryVersion() {
311 return _GetInitialCacheVersion()-1;
316 value_type
const* _GetValue(
const UsdPrim& prim)
const;
319 _Entry* _GetCacheEntryForPrim(
const UsdPrim &prim)
const;
324 void _SetCacheEntryForPrim(
const UsdPrim &prim,
325 value_type
const& value,
326 _Entry* entry)
const;
331 mutable _CacheMap _cache;
339 std::atomic<unsigned> _cacheVersion;
342 ValueOverridesMap _valueOverrides;
348template<
typename Strategy,
typename ImplData>
350UsdImaging_ResolvedAttributeCache<Strategy,ImplData>::_SetCacheEntryForPrim(
352 value_type
const& value,
356 unsigned v = entry->version;
357 if (v < _cacheVersion
358 && entry->version.compare_exchange_strong(v,_cacheVersion.load()))
360 entry->value = value;
361 entry->version = _GetValidVersion();
363 while (entry->version != _GetValidVersion()) {
373template<
typename Strategy,
typename ImplData>
374typename UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_Entry*
375UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_GetCacheEntryForPrim(
378 typename _CacheMap::iterator it = _cache.find(prim);
379 if (it != _cache.end()) {
384 e.query = Strategy::MakeQuery(prim, _implData);
385 e.value = Strategy::MakeDefault();
386 e.version = _GetInvalidVersion();
387 return &(_cache.insert(
388 typename _CacheMap::value_type(prim, e)).first->second);
391template<
typename Strategy,
typename ImplData>
392typename UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::value_type
const*
393UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_GetValue(
396 static value_type
const default_ = Strategy::MakeDefault();
402 _Entry* entry = _GetCacheEntryForPrim(prim);
403 if (entry->version == _GetValidVersion()) {
405 return &entry->value;
415 typename ValueOverridesMap::const_iterator it =
416 _valueOverrides.find(prim);
417 if (it != _valueOverrides.end()) {
418 _SetCacheEntryForPrim(prim, it->second, entry);
420 _SetCacheEntryForPrim(prim,
421 Strategy::Compute(
this, prim, &entry->query),
424 return &entry->value;
427PXR_NAMESPACE_CLOSE_SCOPE
436PXR_NAMESPACE_OPEN_SCOPE
438struct UsdImaging_XfStrategy;
439typedef UsdImaging_ResolvedAttributeCache<UsdImaging_XfStrategy> UsdImaging_XformCache;
441struct UsdImaging_XfStrategy {
446 bool ValueMightBeTimeVarying() {
return true; }
448 value_type MakeDefault() {
return GfMatrix4d(1); }
451 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
453 return query_type(xf);
460 Compute(UsdImaging_XformCache
const* owner,
462 query_type
const* query)
464 value_type xform = MakeDefault();
467 query->GetLocalTransformation(&xform, owner->GetTime());
469 return !query->GetResetXformStack()
470 ? (xform * (*owner->_GetValue(prim.
GetParent())))
478 ComputeTransform(
UsdPrim const& prim,
481 const TfHashMap<SdfPath, GfMatrix4d, SdfPath::Hash> &ctmOverrides)
487 while (p && p.
GetPath() != rootPath) {
488 const auto &overIt = ctmOverrides.find(p.
GetPath());
490 if (overIt != ctmOverrides.end()) {
491 ctm *= overIt->second;
494 if (xf.GetLocalTransformation(&localXf, &reset, time))
505PXR_NAMESPACE_CLOSE_SCOPE
513#include "pxr/usdImaging/usdImaging/debugCodes.h"
515PXR_NAMESPACE_OPEN_SCOPE
517struct UsdImaging_VisStrategy;
518using UsdImaging_VisCache =
519 UsdImaging_ResolvedAttributeCache<UsdImaging_VisStrategy>;
524struct UsdImaging_VisStrategy {
529 bool ValueMightBeTimeVarying() {
return true; }
532 value_type MakeDefault() {
return UsdGeomTokens->inherited; }
535 query_type MakeQuery(
UsdPrim const& prim,
bool *)
538 return query_type(xf.GetVisibilityAttr());
545 Compute(UsdImaging_VisCache
const* owner,
547 query_type
const* query)
549 value_type v = *owner->_GetValue(prim.
GetParent());
559 query->Get(&v, owner->GetTime());
576struct UsdImaging_PurposeStrategy;
577typedef UsdImaging_ResolvedAttributeCache<UsdImaging_PurposeStrategy>
578 UsdImaging_PurposeCache;
580struct UsdImaging_PurposeStrategy {
588 value_type MakeDefault() {
594 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
596 return query_type(im.GetPurposeAttr());
603 Compute(UsdImaging_PurposeCache
const* owner,
605 query_type
const* query)
611 return *(owner->_GetValue(prim.
GetParent()));
615 if (query->HasAuthoredValue()) {
617 query->Get(&info.purpose);
618 info.isInheritable =
true;
625 const value_type *v = owner->_GetValue(prim.
GetParent());
626 if (v->isInheritable) {
633 query->Get(&info.purpose);
639 ComputePurposeInfo(
UsdPrim const& prim)
645PXR_NAMESPACE_CLOSE_SCOPE
654PXR_NAMESPACE_OPEN_SCOPE
656struct UsdImaging_MaterialBindingImplData {
659 UsdImaging_MaterialBindingImplData(
const TfToken &materialPurpose):
660 _materialPurpose(materialPurpose)
665 ~UsdImaging_MaterialBindingImplData() {
670 const TfToken &GetMaterialPurpose()
const {
671 return _materialPurpose;
677 {
return _bindingsCache; }
682 {
return _collQueryCache; }
688 const TfToken _materialPurpose;
693struct UsdImaging_MaterialStrategy;
694typedef UsdImaging_ResolvedAttributeCache<UsdImaging_MaterialStrategy,
695 UsdImaging_MaterialBindingImplData>
696 UsdImaging_MaterialBindingCache;
698struct UsdImaging_MaterialStrategy {
709 using ImplData = UsdImaging_MaterialBindingImplData;
712 bool ValueMightBeTimeVarying() {
return false; }
714 value_type MakeDefault() {
return SdfPath(); }
717 query_type MakeQuery(
724 &implData->GetBindingsCache(),
725 &implData->GetCollectionQueryCache(),
726 implData->GetMaterialPurpose(),
742 Compute(UsdImaging_MaterialBindingCache
const* owner,
744 query_type
const* query)
746 TF_DEBUG(USDIMAGING_SHADERS).Msg(
"Looking for \"preview\" material "
761 ComputeMaterialPath(
UsdPrim const& prim, ImplData *implData) {
766 &implData->GetBindingsCache(),
767 &implData->GetCollectionQueryCache(),
768 implData->GetMaterialPurpose(),
781PXR_NAMESPACE_CLOSE_SCOPE
789PXR_NAMESPACE_OPEN_SCOPE
791struct UsdImaging_DrawModeStrategy;
792typedef UsdImaging_ResolvedAttributeCache<UsdImaging_DrawModeStrategy>
793 UsdImaging_DrawModeCache;
795struct UsdImaging_DrawModeStrategy
801 bool ValueMightBeTimeVarying() {
return false; }
806 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
808 return query_type(modelApi.GetModelDrawModeAttr());
815 Compute(UsdImaging_DrawModeCache
const* owner,
817 query_type
const* query)
839 ComputeDrawMode(
UsdPrim const& prim)
845PXR_NAMESPACE_CLOSE_SCOPE
853PXR_NAMESPACE_OPEN_SCOPE
855struct UsdImaging_PointInstancerIndicesStrategy;
856typedef UsdImaging_ResolvedAttributeCache<UsdImaging_PointInstancerIndicesStrategy>
857 UsdImaging_PointInstancerIndicesCache;
859struct UsdImaging_PointInstancerIndicesStrategy
864 typedef int query_type;
877 bool ValueMightBeTimeVarying() {
return true; }
879 value_type MakeDefault() {
return value_type(); }
882 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
888 Compute(UsdImaging_PointInstancerIndicesCache
const* owner,
890 query_type
const* query)
892 return ComputePerPrototypeIndices(prim, owner->GetTime());
902 VtIntArray protoIndices;
903 if (!pi.GetProtoIndicesAttr().Get(&protoIndices, time)) {
904 TF_WARN(
"Failed to read point instancer protoIndices");
908 std::vector<bool> mask = pi.ComputeMaskAtTime(time);
910 for (
size_t instanceId = 0; instanceId < protoIndices.size(); ++instanceId) {
911 size_t protoIndex = protoIndices.AsConst()[instanceId];
913 if (protoIndex >= v.size()) {
914 v.resize(protoIndex + 1);
917 if (mask.size() == 0 || mask[instanceId]) {
918 v[protoIndex].push_back(instanceId);
926PXR_NAMESPACE_CLOSE_SCOPE
933#include "pxr/imaging/hd/coordSys.h"
935PXR_NAMESPACE_OPEN_SCOPE
937struct UsdImaging_CoordSysBindingStrategy;
939typedef UsdImaging_ResolvedAttributeCache<UsdImaging_CoordSysBindingStrategy>
940 UsdImaging_CoordSysBindingCache;
942struct UsdImaging_CoordSysBindingStrategy
944 typedef std::vector<UsdShadeCoordSysAPI::Binding> UsdBindingVec;
945 typedef std::shared_ptr<UsdBindingVec> UsdBindingVecPtr;
946 typedef std::shared_ptr<SdfPathVector> IdVecPtr;
950 UsdBindingVecPtr usdBindingVecPtr;
952 typedef int query_type;
955 bool ValueMightBeTimeVarying() {
return false; }
958 value_type MakeDefault() {
963 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
969 Compute(UsdImaging_CoordSysBindingCache
const* owner,
971 query_type
const* query)
977 v = *owner->_GetValue(parentPrim);
980 auto _IterateLocalBindings = [&prim](
const UsdBindingVec &localBindings,
981 SdfPathVector &hdIds, UsdBindingVec &usdBindings) {
983 if (!prim.
GetStage()->GetPrimAtPath(
984 binding.coordSysPrimPath).IsValid()) {
987 TF_WARN(
"UsdImaging: Ignore coordinate system binding to "
988 "non-existent prim <%s>\n",
989 binding.coordSysPrimPath.GetText());
993 for (
size_t id = 0, n = hdIds.size();
id < n; ++
id) {
994 if (usdBindings[
id].name == binding.name) {
996 usdBindings[id] = binding;
997 hdIds[id] = binding.bindingRelPath;
1004 usdBindings.push_back(binding);
1005 hdIds.push_back(binding.bindingRelPath);
1018 if (hasLocalBindings && !localBindings.empty()) {
1019 SdfPathVector hdIds;
1020 UsdBindingVec usdBindings;
1022 hdIds = *v.idVecPtr;
1024 if (v.usdBindingVecPtr) {
1025 usdBindings = *v.usdBindingVecPtr;
1027 _IterateLocalBindings(localBindings, hdIds, usdBindings);
1028 v.idVecPtr.reset(
new SdfPathVector(std::move(hdIds)));
1029 v.usdBindingVecPtr.reset(
new UsdBindingVec(std::move(usdBindings)));
1036PXR_NAMESPACE_CLOSE_SCOPE
1044PXR_NAMESPACE_OPEN_SCOPE
1046struct UsdImaging_NonlinearSampleCountStrategy;
1047typedef UsdImaging_ResolvedAttributeCache<
1048 UsdImaging_NonlinearSampleCountStrategy>
1049 UsdImaging_NonlinearSampleCountCache;
1051struct UsdImaging_NonlinearSampleCountStrategy
1053 typedef int value_type;
1058 static constexpr value_type invalidValue = -1;
1061 bool ValueMightBeTimeVarying() {
return true; }
1064 value_type MakeDefault() {
1065 return invalidValue;
1069 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
1071 return query_type(motionAPI.GetNonlinearSampleCountAttr());
1073 return query_type();
1078 Compute(UsdImaging_NonlinearSampleCountCache
const* owner,
1080 query_type
const* query)
1082 if (query->HasAuthoredValue()) {
1084 if (query->Get(&value, owner->GetTime())) {
1089 return *owner->_GetValue(prim.
GetParent());
1100PXR_NAMESPACE_CLOSE_SCOPE
1108PXR_NAMESPACE_OPEN_SCOPE
1110struct UsdImaging_BlurScaleStrategy;
1111typedef UsdImaging_ResolvedAttributeCache<UsdImaging_BlurScaleStrategy>
1112 UsdImaging_BlurScaleCache;
1114struct UsdImaging_BlurScaleStrategy
1125 static const value_type invalidValue;
1128 bool ValueMightBeTimeVarying() {
return true; }
1131 value_type MakeDefault() {
1132 return invalidValue;
1136 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
1138 return query_type(motionAPI.GetMotionBlurScaleAttr());
1140 return query_type();
1145 Compute(UsdImaging_BlurScaleCache
const* owner,
1147 query_type
const* query)
1149 if (query->HasAuthoredValue()) {
1151 if (query->Get(&value, owner->GetTime())) {
1152 return { value,
true };
1156 return *owner->_GetValue(prim.
GetParent());
1167PXR_NAMESPACE_CLOSE_SCOPE
1175PXR_NAMESPACE_OPEN_SCOPE
1177struct UsdImaging_InheritedPrimvarStrategy;
1178typedef UsdImaging_ResolvedAttributeCache<UsdImaging_InheritedPrimvarStrategy>
1179 UsdImaging_InheritedPrimvarCache;
1181struct UsdImaging_InheritedPrimvarStrategy
1183 struct PrimvarRecord {
1184 std::vector<UsdGeomPrimvar> primvars;
1187 typedef std::shared_ptr<PrimvarRecord> value_type;
1193 bool ValueMightBeTimeVarying() {
return false; }
1196 value_type MakeDefault() {
1197 return value_type();
1201 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
1206 value_type Compute(UsdImaging_InheritedPrimvarCache
const* owner,
1208 query_type
const* query)
1214 v = *owner->_GetValue(parentPrim);
1217 std::vector<UsdGeomPrimvar> primvars =
1218 query->FindIncrementallyInheritablePrimvars(
1219 v ? v->primvars : std::vector<UsdGeomPrimvar>());
1220 if (!primvars.empty()) {
1221 v = std::make_shared<PrimvarRecord>();
1222 v->primvars = std::move(primvars);
1223 v->variable =
false;
1236PXR_NAMESPACE_CLOSE_SCOPE
void WorkSwapDestroyAsync(T &obj)
Swap obj with a default-constructed T instance, return and arrange for the swapped-out instance to be...
Stores a 4x4 matrix of double elements.
A path value used to locate objects in layers or scenegraphs.
SDF_API const std::string & GetString() const
Return the string representation of this path as a std::string.
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
SDF_API bool IsAbsolutePath() const
Returns whether the path is absolute.
SDF_API bool HasPrefix(const SdfPath &prefix) const
Return true if both this path and prefix are not the empty path and this path has prefix as a prefix.
Token for efficient comparison, assignment, and hashing of known strings.
Object for efficiently making repeated queries for attribute values.
Base class for all prims that may require rendering or visualization of some sort.
USDGEOM_API PurposeInfo ComputePurposeInfo() const
Calculate the effective purpose information about this prim which includes final computed purpose val...
USDGEOM_API TfToken ComputeVisibility(UsdTimeCode const &time=UsdTimeCode::Default()) const
Calculate the effective visibility of this prim, as defined by its most ancestral authored "invisible...
UsdGeomModelAPI extends the generic UsdModelAPI schema with geometry specific concepts such as cached...
USDGEOM_API TfToken ComputeModelDrawMode(const TfToken &parentDrawMode=TfToken()) const
Calculate the effective model:drawMode of this prim.
UsdGeomMotionAPI encodes data that can live on any prim that may affect computations involving:
USDGEOM_API float ComputeMotionBlurScale(UsdTimeCode time=UsdTimeCode::Default()) const
Compute the inherited value of motion:blurScale at time, i.e.
USDGEOM_API int ComputeNonlinearSampleCount(UsdTimeCode time=UsdTimeCode::Default()) const
Compute the inherited value of nonlinearSampleCount at time, i.e.
Encodes vectorized instancing of multiple, potentially animated, prototypes (object/instance masters)...
Schema wrapper for UsdAttribute for authoring and introspecting attributes that are primvars.
USDGEOM_API bool ValueMightBeTimeVarying() const
Return true if it is possible, but not certain, that this primvar's value changes over time,...
UsdGeomPrimvarsAPI encodes geometric "primitive variables", as UsdGeomPrimvar, which interpolate acro...
SdfPath GetPath() const
Return the complete scene path to this object on its UsdStage, which may (UsdPrim) or may not (all ot...
USD_API UsdStageWeakPtr GetStage() const
Return the stage that owns the object, and to whose state and lifetime this object's validity is tied...
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
UsdPrim GetParent() const
Return this prim's parent prim.
bool IsPrototype() const
Return true if this prim is an instancing prototype prim, false otherwise.
bool IsInPrototype() const
Return true if this prim is a prototype prim or a descendant of a prototype prim, false otherwise.
An forward-iterable range that traverses a subtree of prims rooted at a given prim in depth-first ord...
A UsdRelationship creates dependencies between scenegraph objects by allowing a prim to target other ...
SdfPath GetPath() const
Shorthand for GetPrim()->GetPath().
UsdShadeCoordSysAPI provides a way to designate, name, and discover coordinate systems.
USDSHADE_API std::vector< Binding > GetLocalBindings() const
Get the list of coordinate system bindings local to this prim.
USDSHADE_API bool HasLocalBindings() const
Returns true if the prim has local coordinate system relationship exists.
A coordinate system binding.
UsdShadeMaterialBindingAPI is an API schema that provides an interface for binding materials to prims...
tbb::concurrent_unordered_map< SdfPath, std::unique_ptr< UsdCollectionAPI::MembershipQuery >, SdfPath::Hash > CollectionQueryCache
An unordered list of collection paths mapped to the associated collection's MembershipQuery object.
static USDSHADE_API const SdfPath GetResolvedTargetPathFromBindingRel(const UsdRelationship &bindingRel)
returns the path of the resolved target identified by bindingRel.
tbb::concurrent_unordered_map< SdfPath, std::unique_ptr< BindingsAtPrim >, SdfPath::Hash > BindingsCache
An unordered list of prim-paths mapped to the corresponding set of bindings at the associated prim.
USDSHADE_API UsdShadeMaterial ComputeBoundMaterial(BindingsCache *bindingsCache, CollectionQueryCache *collectionQueryCache, const TfToken &materialPurpose=UsdShadeTokens->allPurpose, UsdRelationship *bindingRel=nullptr, bool supportLegacyBindings=true) const
Computes the resolved bound material for this prim, for the given material purpose.
A Material provides a container into which multiple "render contexts" can add data that defines a "sh...
Represent a time value, which may be either numeric, holding a double value, or a sentinel value UsdT...
Represents an arbitrary dimensional rectangular container class.
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
#define TF_DEBUG(enumVal)
Evaluate and print debugging message msg if enumVal is enabled for debugging.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
#define TF_WARN(...)
Issue a warning, but continue execution.
Value type containing information about a prim's computed effective purpose as well as storing whethe...
TfToken class for efficient string referencing and hashing, plus conversions to and from stl string c...
USDGEOM_API TfStaticData< UsdGeomTokensType > UsdGeomTokens
A global variable with static, efficient TfTokens for use in all public USD API.