24 #ifndef PXR_USD_IMAGING_USD_IMAGING_RESOLVED_ATTRIBUTE_CACHE_H
25 #define PXR_USD_IMAGING_USD_IMAGING_RESOLVED_ATTRIBUTE_CACHE_H
30 #include "pxr/usdImaging/usdImaging/api.h"
32 #include "pxr/usd/usd/primRange.h"
34 #include "pxr/usd/sdf/path.h"
38 #include <boost/functional/hash.hpp>
39 #include <tbb/concurrent_unordered_map.h>
42 PXR_NAMESPACE_OPEN_SCOPE
66 template<
typename Strategy,
typename ImplData=
bool>
67 class UsdImaging_ResolvedAttributeCache
71 typedef tbb::concurrent_unordered_map<
UsdPrim,
73 boost::hash<UsdPrim> > _CacheMap;
75 typedef typename Strategy::value_type value_type;
76 typedef typename Strategy::query_type query_type;
78 typedef TfHashMap<UsdPrim, value_type, boost::hash<UsdPrim> >
82 explicit UsdImaging_ResolvedAttributeCache(
84 ImplData *implData=
nullptr,
85 const ValueOverridesMap valueOverrides=ValueOverridesMap())
87 , _rootPath(
SdfPath::AbsoluteRootPath())
88 , _cacheVersion(_GetInitialCacheVersion())
89 , _valueOverrides(valueOverrides)
95 UsdImaging_ResolvedAttributeCache()
97 , _rootPath(
SdfPath::AbsoluteRootPath())
102 ~UsdImaging_ResolvedAttributeCache()
110 value_type GetValue(
const UsdPrim& prim)
const
116 "which is not within the specified root: %s",
118 _rootPath.GetString().c_str());
119 return Strategy::MakeDefault();
122 return *_GetValue(prim);
129 GetQuery(
const UsdPrim& prim)
const {
130 return &_GetCacheEntryForPrim(prim)->query;
136 _cacheVersion = _GetInitialCacheVersion();
146 if (Strategy::ValueMightBeTimeVarying()) {
168 void SetRootPath(
const SdfPath& rootPath) {
175 if (rootPath == _rootPath)
179 _rootPath = rootPath;
184 const SdfPath & GetRootPath()
const {
return _rootPath; }
196 void UpdateValueOverrides(
const ValueOverridesMap &valueOverrides,
197 const std::vector<UsdPrim> &overridesToRemove,
198 std::vector<SdfPath> *dirtySubtreeRoots)
202 if (valueOverrides.empty() && overridesToRemove.empty())
205 ValueOverridesMap valueOverridesToProcess;
206 SdfPathVector processedOverridePaths;
208 const UsdPrim &prim = it->first;
209 const value_type &value = it->second;
213 if (*_GetValue(prim) == value)
216 valueOverridesToProcess[prim] = value;
220 const UsdPrim &prim = it->first;
221 const value_type &value = it->second;
228 bool isDescendantOfProcessedOverride =
false;
229 for (
const SdfPath &processedPath : processedOverridePaths) {
231 isDescendantOfProcessedOverride =
true;
238 if (!isDescendantOfProcessedOverride) {
240 if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
241 entry->version = _GetInvalidVersion();
244 processedOverridePaths.push_back(prim.
GetPath());
245 dirtySubtreeRoots->push_back(prim.
GetPath());
249 _valueOverrides[prim] = value;
252 for (
const UsdPrim &prim : overridesToRemove) {
255 size_t numErased = _valueOverrides.erase(prim);
258 if (numErased == 0) {
262 bool isDescendantOfProcessedOverride =
false;
263 for (
const SdfPath &processedPath : processedOverridePaths) {
265 isDescendantOfProcessedOverride =
true;
272 if (!isDescendantOfProcessedOverride) {
274 if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
275 entry->version = _GetInvalidVersion();
278 dirtySubtreeRoots->push_back(prim.
GetPath());
279 processedOverridePaths.push_back(prim.
GetPath());
290 : value(Strategy::MakeDefault())
291 , version(_GetInitialEntryVersion())
294 _Entry(
const query_type & query_,
295 const value_type& value_,
304 tbb::atomic<unsigned> version;
308 unsigned _GetValidVersion()
const {
return _cacheVersion + 1; }
311 unsigned _GetInvalidVersion()
const {
return _cacheVersion - 1; }
314 static unsigned _GetInitialCacheVersion() {
return 1; }
315 static unsigned _GetInitialEntryVersion() {
316 return _GetInitialCacheVersion()-1;
321 value_type
const* _GetValue(
const UsdPrim& prim)
const;
324 _Entry* _GetCacheEntryForPrim(
const UsdPrim &prim)
const;
329 void _SetCacheEntryForPrim(
const UsdPrim &prim,
330 value_type
const& value,
331 _Entry* entry)
const;
336 mutable _CacheMap _cache;
344 tbb::atomic<unsigned> _cacheVersion;
347 ValueOverridesMap _valueOverrides;
353 template<
typename Strategy,
typename ImplData>
355 UsdImaging_ResolvedAttributeCache<Strategy,ImplData>::_SetCacheEntryForPrim(
357 value_type
const& value,
361 unsigned v = entry->version;
362 if (v < _cacheVersion
363 && entry->version.compare_and_swap(_cacheVersion, v) == v)
365 entry->value = value;
366 entry->version = _GetValidVersion();
368 while (entry->version != _GetValidVersion()) {
378 template<
typename Strategy,
typename ImplData>
379 typename UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_Entry*
380 UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_GetCacheEntryForPrim(
383 typename _CacheMap::const_iterator it = _cache.find(prim);
384 if (it != _cache.end()) {
389 e.query = Strategy::MakeQuery(prim, _implData);
390 e.value = Strategy::MakeDefault();
391 e.version = _GetInvalidVersion();
392 return &(_cache.insert(
393 typename _CacheMap::value_type(prim, e)).first->second);
396 template<
typename Strategy,
typename ImplData>
397 typename UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::value_type
const*
398 UsdImaging_ResolvedAttributeCache<Strategy, ImplData>::_GetValue(
401 static value_type
const default_ = Strategy::MakeDefault();
407 _Entry* entry = _GetCacheEntryForPrim(prim);
408 if (entry->version == _GetValidVersion()) {
410 return &entry->value;
420 typename ValueOverridesMap::const_iterator it =
421 _valueOverrides.find(prim);
422 if (it != _valueOverrides.end()) {
423 _SetCacheEntryForPrim(prim, it->second, entry);
425 _SetCacheEntryForPrim(prim,
426 Strategy::Compute(
this, prim, &entry->query),
429 return &entry->value;
432 PXR_NAMESPACE_CLOSE_SCOPE
441 PXR_NAMESPACE_OPEN_SCOPE
443 struct UsdImaging_XfStrategy;
444 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_XfStrategy> UsdImaging_XformCache;
446 struct UsdImaging_XfStrategy {
451 bool ValueMightBeTimeVarying() {
return true; }
453 value_type MakeDefault() {
return GfMatrix4d(1); }
456 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
458 return query_type(xf);
464 Compute(UsdImaging_XformCache
const* owner,
466 query_type
const* query)
468 value_type xform = MakeDefault();
471 query->GetLocalTransformation(&xform, owner->GetTime());
473 return !query->GetResetXformStack()
474 ? (xform * (*owner->_GetValue(prim.
GetParent())))
482 ComputeTransform(
UsdPrim const& prim,
485 const TfHashMap<SdfPath, GfMatrix4d, SdfPath::Hash> &ctmOverrides)
491 while (p && p.
GetPath() != rootPath) {
492 const auto &overIt = ctmOverrides.find(p.
GetPath());
494 if (overIt != ctmOverrides.end()) {
495 ctm *= overIt->second;
498 if (xf.GetLocalTransformation(&localXf, &reset, time))
509 PXR_NAMESPACE_CLOSE_SCOPE
517 #include "pxr/usdImaging/usdImaging/debugCodes.h"
519 PXR_NAMESPACE_OPEN_SCOPE
521 struct UsdImaging_VisStrategy;
522 using UsdImaging_VisCache =
523 UsdImaging_ResolvedAttributeCache<UsdImaging_VisStrategy>;
528 struct UsdImaging_VisStrategy {
533 bool ValueMightBeTimeVarying() {
return true; }
536 value_type MakeDefault() {
return UsdGeomTokens->inherited; }
539 query_type MakeQuery(
UsdPrim const& prim,
bool *)
542 return query_type(xf.GetVisibilityAttr());
549 Compute(UsdImaging_VisCache
const* owner,
551 query_type
const* query)
553 value_type v = *owner->_GetValue(prim.
GetParent());
563 query->Get(&v, owner->GetTime());
580 struct UsdImaging_PurposeStrategy;
581 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_PurposeStrategy>
582 UsdImaging_PurposeCache;
584 struct UsdImaging_PurposeStrategy {
592 value_type MakeDefault() {
598 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
605 Compute(UsdImaging_PurposeCache
const* owner,
607 query_type
const* query)
613 return *(owner->_GetValue(prim.
GetParent()));
617 if (query->HasAuthoredValue()) {
619 query->Get(&info.purpose);
620 info.isInheritable =
true;
627 const value_type *v = owner->_GetValue(prim.
GetParent());
628 if (v->isInheritable) {
635 query->Get(&info.purpose);
641 ComputePurposeInfo(
UsdPrim const& prim)
647 PXR_NAMESPACE_CLOSE_SCOPE
656 PXR_NAMESPACE_OPEN_SCOPE
658 struct UsdImaging_MaterialBindingImplData {
661 UsdImaging_MaterialBindingImplData(
const TfToken &materialPurpose):
662 _materialPurpose(materialPurpose)
667 ~UsdImaging_MaterialBindingImplData() {
672 const TfToken &GetMaterialPurpose()
const {
673 return _materialPurpose;
679 {
return _bindingsCache; }
684 {
return _collQueryCache; }
690 const TfToken _materialPurpose;
695 struct UsdImaging_MaterialStrategy;
696 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_MaterialStrategy,
697 UsdImaging_MaterialBindingImplData>
698 UsdImaging_MaterialBindingCache;
700 struct UsdImaging_MaterialStrategy {
704 using ImplData = UsdImaging_MaterialBindingImplData;
707 bool ValueMightBeTimeVarying() {
return false; }
709 value_type MakeDefault() {
return SdfPath(); }
712 query_type MakeQuery(
717 &implData->GetBindingsCache(),
718 &implData->GetCollectionQueryCache(),
719 implData->GetMaterialPurpose());
724 Compute(UsdImaging_MaterialBindingCache
const* owner,
726 query_type
const* query)
728 TF_DEBUG(USDIMAGING_SHADERS).Msg(
"Looking for \"preview\" material "
731 SdfPath binding = query->GetPath();
745 ComputeMaterialPath(
UsdPrim const& prim, ImplData *implData) {
749 ComputeBoundMaterial(&implData->GetBindingsCache(),
750 &implData->GetCollectionQueryCache(),
751 implData->GetMaterialPurpose())) {
752 return mat.GetPath();
758 PXR_NAMESPACE_CLOSE_SCOPE
766 PXR_NAMESPACE_OPEN_SCOPE
768 struct UsdImaging_DrawModeStrategy;
769 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_DrawModeStrategy>
770 UsdImaging_DrawModeCache;
772 struct UsdImaging_DrawModeStrategy
778 bool ValueMightBeTimeVarying() {
return false; }
783 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
785 return query_type(a);
791 Compute(UsdImaging_DrawModeCache
const* owner,
793 query_type
const* query)
815 ComputeDrawMode(
UsdPrim const& prim)
821 PXR_NAMESPACE_CLOSE_SCOPE
829 PXR_NAMESPACE_OPEN_SCOPE
831 struct UsdImaging_PointInstancerIndicesStrategy;
832 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_PointInstancerIndicesStrategy>
833 UsdImaging_PointInstancerIndicesCache;
835 struct UsdImaging_PointInstancerIndicesStrategy
840 typedef int query_type;
853 bool ValueMightBeTimeVarying() {
return true; }
855 value_type MakeDefault() {
return value_type(); }
858 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
864 Compute(UsdImaging_PointInstancerIndicesCache
const* owner,
866 query_type
const* query)
868 return ComputePerPrototypeIndices(prim, owner->GetTime());
878 VtIntArray protoIndices;
879 if (!pi.GetProtoIndicesAttr().Get(&protoIndices, time)) {
880 TF_WARN(
"Failed to read point instancer protoIndices");
884 std::vector<bool> mask = pi.ComputeMaskAtTime(time);
886 for (
size_t instanceId = 0; instanceId < protoIndices.size(); ++instanceId) {
887 size_t protoIndex = protoIndices[instanceId];
889 if (protoIndex >= v.size()) {
890 v.resize(protoIndex + 1);
893 if (mask.size() == 0 || mask[instanceId]) {
894 v[protoIndex].push_back(instanceId);
902 PXR_NAMESPACE_CLOSE_SCOPE
909 #include "pxr/imaging/hd/coordSys.h"
911 PXR_NAMESPACE_OPEN_SCOPE
913 struct UsdImaging_CoordSysBindingImplData {
916 std::function<SdfPath(SdfPath)> usdToHydraPath;
919 struct UsdImaging_CoordSysBindingStrategy;
921 typedef UsdImaging_ResolvedAttributeCache<
922 UsdImaging_CoordSysBindingStrategy,
923 UsdImaging_CoordSysBindingImplData>
924 UsdImaging_CoordSysBindingCache;
926 struct UsdImaging_CoordSysBindingStrategy
928 using ImplData = UsdImaging_CoordSysBindingImplData;
930 typedef std::vector<UsdShadeCoordSysAPI::Binding> UsdBindingVec;
931 typedef std::shared_ptr<UsdBindingVec> UsdBindingVecPtr;
932 typedef std::shared_ptr<SdfPathVector> IdVecPtr;
936 UsdBindingVecPtr usdBindingVecPtr;
945 return implData->usdToHydraPath(binding.bindingRelPath);
950 bool ValueMightBeTimeVarying() {
return false; }
953 value_type MakeDefault() {
958 query_type MakeQuery(
UsdPrim const& prim, ImplData *implData) {
964 Compute(UsdImaging_CoordSysBindingCache
const* owner,
966 query_type
const* query)
969 if (query->coordSysAPI) {
972 v = *owner->_GetValue(parentPrim);
975 if (query->coordSysAPI.HasLocalBindings()) {
977 UsdBindingVec usdBindings;
981 if (v.usdBindingVecPtr) {
982 usdBindings = *v.usdBindingVecPtr;
984 for (
auto const& binding:
985 query->coordSysAPI.GetLocalBindings()) {
986 if (!prim.
GetStage()->GetPrimAtPath(
987 binding.coordSysPrimPath).IsValid()) {
990 TF_WARN(
"UsdImaging: Ignoring coordinate system "
991 "binding to non-existent prim <%s>\n",
992 binding.coordSysPrimPath.
GetText());
996 for (
size_t i=0, n=hdIds.size(); i<n; ++i) {
997 if (usdBindings[i].name == binding.name) {
999 usdBindings[i] = binding;
1000 hdIds[i] = query->_IdForBinding(binding);
1007 usdBindings.push_back(binding);
1008 hdIds.push_back(query->_IdForBinding(binding));
1011 v.idVecPtr.reset(
new SdfPathVector(hdIds));
1012 v.usdBindingVecPtr.reset(
new UsdBindingVec(usdBindings));
1019 PXR_NAMESPACE_CLOSE_SCOPE
1027 PXR_NAMESPACE_OPEN_SCOPE
1029 struct UsdImaging_InheritedPrimvarStrategy;
1030 typedef UsdImaging_ResolvedAttributeCache<UsdImaging_InheritedPrimvarStrategy>
1031 UsdImaging_InheritedPrimvarCache;
1033 struct UsdImaging_InheritedPrimvarStrategy
1035 struct PrimvarRecord {
1036 std::vector<UsdGeomPrimvar> primvars;
1039 typedef std::shared_ptr<PrimvarRecord> value_type;
1045 bool ValueMightBeTimeVarying() {
return false; }
1048 value_type MakeDefault() {
1049 return value_type();
1053 query_type MakeQuery(
UsdPrim const& prim,
bool *) {
1058 value_type Compute(UsdImaging_InheritedPrimvarCache
const* owner,
1060 query_type
const* query)
1066 v = *owner->_GetValue(parentPrim);
1069 std::vector<UsdGeomPrimvar> primvars =
1070 query->FindIncrementallyInheritablePrimvars(
1071 v ? v->primvars : std::vector<UsdGeomPrimvar>());
1072 if (!primvars.empty()) {
1073 v = std::make_shared<PrimvarRecord>();
1074 v->primvars = std::move(primvars);
1075 v->variable =
false;
1088 PXR_NAMESPACE_CLOSE_SCOPE
USD_API UsdStageWeakPtr GetStage() const
Return the stage that owns the object, and to whose state and lifetime this object's validity is tied...
UsdShadeCoordSysAPI provides a way to designate, name, and discover coordinate systems.
UsdGeomModelAPI extends the generic UsdModelAPI schema with geometry specific concepts such as cached...
USDGEOM_API UsdAttribute GetPurposeAttr() const
Purpose is a classification of geometry into categories that can each be independently included or ex...
UsdPrim GetParent() const
Return this prim's parent prim.
Object for efficiently making repeated queries for attribute values.
#define TF_WARN(...)
Issue a warning, but continue execution.
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...
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
SdfPath GetPath() const
Return the complete scene path to this object on its UsdStage, which may (UsdPrim) or may not (all ot...
SDF_API bool IsAbsolutePath() const
Returns whether the path is absolute.
Scenegraph object for authoring and retrieving numeric, string, and array valued data, sampled over time.
bool IsPrototype() const
Return true if this prim is an instancing prototype prim, false otherwise.
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...
A coordinate system binding.
UsdShadeMaterialBindingAPI is an API schema that provides an interface for binding materials to prims...
UsdGeomPrimvarsAPI encodes geometric "primitive variables", as UsdGeomPrimvar, which interpolate ac...
bool IsInPrototype() const
Return true if this prim is a prototype prim or a descendant of a prototype prim, false otherwise...
Token for efficient comparison, assignment, and hashing of known strings.
USDGEOM_API TfToken ComputeModelDrawMode(const TfToken &parentDrawMode=TfToken()) const
Calculate the effective model:drawMode of this prim.
USDSHADE_API UsdShadeMaterial ComputeBoundMaterial(BindingsCache *bindingsCache, CollectionQueryCache *collectionQueryCache, const TfToken &materialPurpose=UsdShadeTokens->allPurpose, UsdRelationship *bindingRel=nullptr) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Stores a 4x4 matrix of double elements.
Represent a time value, which may be either numeric, holding a double value, or a sentinel value UsdT...
USDGEOM_API TfStaticData< UsdGeomTokensType > UsdGeomTokens
A global variable with static, efficient TfTokens for use in all public USD API.
Value type containing information about a prim's computed effective purpose as well as storing whethe...
#define TRACE_FUNCTION()
Records a timestamp when constructed and a timespan event when destructed, using the name of the func...
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a "Prim" as ...
USDGEOM_API bool ValueMightBeTimeVarying() const
Return true if it is possible, but not certain, that this primvar's value changes over time...
Represents an arbitrary dimensional rectangular container class.
A path value used to locate objects in layers or scenegraphs.
#define TF_DEBUG(enumVal)
Evaluate and print debugging message msg if enumVal is enabled for debugging.
SDF_API const std::string & GetString() const
Return the string representation of this path as a std::string.
USDGEOM_API PurposeInfo ComputePurposeInfo() const
Calculate the effective purpose information about this prim which includes final computed purpose val...
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...
An forward-iterable range that traverses a subtree of prims rooted at a given prim in depth-first ord...
A Material provides a container into which multiple "render targets" can add data that defines a "sha...
Encodes vectorized instancing of multiple, potentially animated, prototypes (object/instance masters)...
Schema wrapper for UsdAttribute for authoring and introspecting attributes that are primvars...
void WorkSwapDestroyAsync(T &obj)
Swap obj with a default-constructed T instance, return and arrange for the swapped-out instance to be...
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...
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Base class for all prims that may require rendering or visualization of some sort.
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.
TfToken class for efficient string referencing and hashing, plus conversions to and from stl string c...