All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
inheritedCache.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef USDIMAGING_INHERITEDCACHE_H
25 #define USDIMAGING_INHERITEDCACHE_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usdImaging/usdImaging/api.h"
31 #include "pxr/usd/usd/prim.h"
32 #include "pxr/usd/usd/primRange.h"
33 #include "pxr/usd/usdShade/tokens.h"
34 #include "pxr/usd/sdf/path.h"
35 
36 #include "pxr/base/work/utils.h"
37 
38 #include <boost/functional/hash.hpp>
39 #include <tbb/concurrent_unordered_map.h>
40 #include <functional>
41 
42 PXR_NAMESPACE_OPEN_SCOPE
43 
67 template<typename Strategy, typename ImplData=bool>
68 class UsdImaging_InheritedCache
69 {
70  friend Strategy;
71  struct _Entry;
72  typedef tbb::concurrent_unordered_map<UsdPrim,
73  _Entry,
74  boost::hash<UsdPrim> > _CacheMap;
75 public:
76  typedef typename Strategy::value_type value_type;
77  typedef typename Strategy::query_type query_type;
78 
79  typedef TfHashMap<UsdPrim, value_type, boost::hash<UsdPrim> >
80  ValueOverridesMap;
81 
83  explicit UsdImaging_InheritedCache(
84  const UsdTimeCode time,
85  ImplData *implData=nullptr,
86  const ValueOverridesMap valueOverrides=ValueOverridesMap())
87  : _time(time)
88  , _rootPath(SdfPath::AbsoluteRootPath())
89  , _cacheVersion(_GetInitialCacheVersion())
90  , _valueOverrides(valueOverrides)
91  , _implData(implData)
92  {
93  }
94 
96  UsdImaging_InheritedCache()
97  : _time(UsdTimeCode::Default())
98  , _rootPath(SdfPath::AbsoluteRootPath())
99  , _cacheVersion(1)
100  {
101  }
102 
103  ~UsdImaging_InheritedCache()
104  {
105  WorkSwapDestroyAsync(_cache);
106  }
107 
108 
111  value_type GetValue(const UsdPrim& prim) const
112  {
113  TRACE_FUNCTION();
114  if (!prim.GetPath().HasPrefix(_rootPath)
115  && !prim.IsInMaster()) {
116  TF_CODING_ERROR("Attempt to get value for: %s "
117  "which is not within the specified root: %s",
118  prim.GetPath().GetString().c_str(),
119  _rootPath.GetString().c_str());
120  return Strategy::MakeDefault();
121  }
122 
123  return *_GetValue(prim);
124  }
125 
129  query_type const*
130  GetQuery(const UsdPrim& prim) const {
131  return &_GetCacheEntryForPrim(prim)->query;
132  }
133 
135  void Clear() {
136  _cache.clear();
137  _cacheVersion = _GetInitialCacheVersion();
138  }
139 
143  void SetTime(UsdTimeCode time) {
144  if (time == _time)
145  return;
146 
147  if (Strategy::ValueMightBeTimeVarying()) {
148  // Mark all cached entries as invalid, but leave the queries behind.
149  // We increment by 2 here and always keep the version an odd number,
150  // this enables the use of even versions as a per-entry spin lock.
151  _cacheVersion += 2;
152  }
153 
154  // Update to correct time.
155  _time = time;
156  }
157 
159  UsdTimeCode GetTime() const { return _time; }
160 
169  void SetRootPath(const SdfPath& rootPath) {
170  if (!rootPath.IsAbsolutePath()) {
171  TF_CODING_ERROR("Invalid root path: %s",
172  rootPath.GetString().c_str());
173  return;
174  }
175 
176  if (rootPath == _rootPath)
177  return;
178 
179  Clear();
180  _rootPath = rootPath;
181  }
182 
185  const SdfPath & GetRootPath() const { return _rootPath; }
186 
197  void UpdateValueOverrides(const ValueOverridesMap &valueOverrides,
198  const std::vector<UsdPrim> &overridesToRemove,
199  std::vector<SdfPath> *dirtySubtreeRoots)
200  {
201  TRACE_FUNCTION();
202 
203  if (valueOverrides.empty() && overridesToRemove.empty())
204  return;
205 
206  ValueOverridesMap valueOverridesToProcess;
207  SdfPathVector processedOverridePaths;
208  TF_FOR_ALL(it, valueOverrides) {
209  const UsdPrim &prim = it->first;
210  const value_type &value = it->second;
211 
212  // If the existing value matches the incoming value, skip
213  // the update and dirtying.
214  if (*_GetValue(prim) == value)
215  continue;
216 
217  valueOverridesToProcess[prim] = value;
218  }
219 
220  TF_FOR_ALL(it, valueOverridesToProcess) {
221  const UsdPrim &prim = it->first;
222  const value_type &value = it->second;
223 
224  // XXX: performance
225  // We could probably make this faster by using a hash table of
226  // prefixes. This hasn't showed up in traces much though as it's not
227  // common to update value overrides for more than one path at a
228  // time.
229  bool isDescendantOfProcessedOverride = false;
230  for (const SdfPath &processedPath : processedOverridePaths) {
231  if (prim.GetPath().HasPrefix(processedPath)) {
232  isDescendantOfProcessedOverride = true;
233  break;
234  }
235  }
236 
237  // Invalidate cache entries if the prim is not a descendant of a
238  // path that has already been processed.
239  if (!isDescendantOfProcessedOverride) {
240  for (UsdPrim descendant: UsdPrimRange(prim)) {
241  if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
242  entry->version = _GetInvalidVersion();
243  }
244  }
245  processedOverridePaths.push_back(prim.GetPath());
246  dirtySubtreeRoots->push_back(prim.GetPath());
247  }
248 
249  // Update overrides in the internal value overrides map.
250  _valueOverrides[prim] = value;
251  }
252 
253  for (const UsdPrim &prim : overridesToRemove) {
254 
255  // Erase the entry from the map of overrides.
256  size_t numErased = _valueOverrides.erase(prim);
257 
258  // If the override doesn't exist, then there's nothing to do.
259  if (numErased == 0) {
260  continue;
261  }
262 
263  bool isDescendantOfProcessedOverride = false;
264  for (const SdfPath &processedPath : processedOverridePaths) {
265  if (prim.GetPath().HasPrefix(processedPath)) {
266  isDescendantOfProcessedOverride = true;
267  break;
268  }
269  }
270 
271  // Invalidate cache entries if the prim is not a descendant of a
272  // path that has already been processed.
273  if (!isDescendantOfProcessedOverride) {
274  for (UsdPrim descendant: UsdPrimRange(prim)) {
275  if (_Entry* entry = _GetCacheEntryForPrim(descendant)) {
276  entry->version = _GetInvalidVersion();
277  }
278  }
279  dirtySubtreeRoots->push_back(prim.GetPath());
280  processedOverridePaths.push_back(prim.GetPath());
281  }
282  }
283  }
284 
285 private:
286  // Cached value entries. Note that because query objects may be caching
287  // non-time varying data, entries may exist in the cache with invalid
288  // values. The version is used to determine validity.
289  struct _Entry {
290  _Entry()
291  : value(Strategy::MakeDefault())
292  , version(_GetInitialEntryVersion())
293  { }
294 
295  _Entry(const query_type & query_,
296  const value_type& value_,
297  unsigned version_)
298  : query(query_)
299  , value(value_)
300  , version(version_)
301  { }
302 
303  query_type query;
304  value_type value;
305  tbb::atomic<unsigned> version;
306  };
307 
308  // Returns the version number for a valid cache entry
309  unsigned _GetValidVersion() const { return _cacheVersion + 1; }
310 
311  // Returns the version number for an invalid cache entry
312  unsigned _GetInvalidVersion() const { return _cacheVersion - 1; }
313 
314  // Initial version numbers
315  static unsigned _GetInitialCacheVersion() { return 1; }
316  static unsigned _GetInitialEntryVersion() {
317  return _GetInitialCacheVersion()-1;
318  }
319 
320  // Traverse the hierarchy (order is strategy dependent) and compute the
321  // inherited value.
322  value_type const* _GetValue(const UsdPrim& prim) const;
323 
324  // Helper function to get or create a new entry for a prim in the cache.
325  _Entry* _GetCacheEntryForPrim(const UsdPrim &prim) const;
326 
327  // Sets the value of the given cache entry. If multiple threads attempt to
328  // set the same entry, the first in wins and other threads spin until the
329  // new value is set.
330  void _SetCacheEntryForPrim(const UsdPrim &prim,
331  value_type const& value,
332  _Entry* entry) const;
333 
334  // Mutable is required here to allow const methods to update the cache when
335  // it is thread safe, however not all mutations of this map are thread safe.
336  // See underlying map documentation for details.
337  mutable _CacheMap _cache;
338 
339  // The time at which this stack is querying and caching attribute values.
340  UsdTimeCode _time;
341  SdfPath _rootPath;
342 
343  // A serial number indicating the valid state of entries in the cache. When
344  // an entry has an equal or greater value, the entry is valid.
345  tbb::atomic<unsigned> _cacheVersion;
346 
347  // Value overrides for a set of descendents.
348  ValueOverridesMap _valueOverrides;
349 
350  // Supplemental cache if used by this inherited cache.
351  ImplData *_implData;
352 };
353 
354 template<typename Strategy, typename ImplData>
355 void
356 UsdImaging_InheritedCache<Strategy,ImplData>::_SetCacheEntryForPrim(
357  const UsdPrim &prim,
358  value_type const& value,
359  _Entry* entry) const
360 {
361  // Note: _cacheVersion is not allowed to change during cache access.
362  unsigned v = entry->version;
363  if (v < _cacheVersion
364  && entry->version.compare_and_swap(_cacheVersion, v) == v)
365  {
366  entry->value = value;
367  entry->version = _GetValidVersion();
368  } else {
369  while (entry->version != _GetValidVersion()) {
370  // Future work: A suggestion is that rather than literally spinning
371  // here, we should use the pause instruction, which sleeps for one
372  // cycle while allowing hyper threads to continue. Folly has a nice
373  // implementation of this packaged up as "sleeper", which we could
374  // also implement in Work and Arch.
375  }
376  }
377 }
378 
379 template<typename Strategy, typename ImplData>
380 typename UsdImaging_InheritedCache<Strategy, ImplData>::_Entry*
381 UsdImaging_InheritedCache<Strategy, ImplData>::_GetCacheEntryForPrim(
382  const UsdPrim &prim) const
383 {
384  typename _CacheMap::const_iterator it = _cache.find(prim);
385  if (it != _cache.end()) {
386  return &it->second;
387  }
388 
389  _Entry e;
390  e.query = Strategy::MakeQuery(prim, _implData);
391  e.value = Strategy::MakeDefault();
392  e.version = _GetInvalidVersion();
393  return &(_cache.insert(
394  typename _CacheMap::value_type(prim, e)).first->second);
395 }
396 
397 template<typename Strategy, typename ImplData>
398 typename UsdImaging_InheritedCache<Strategy, ImplData>::value_type const*
399 UsdImaging_InheritedCache<Strategy, ImplData>::_GetValue(
400  const UsdPrim& prim) const
401 {
402  static value_type const default_ = Strategy::MakeDefault();
403 
404  // Base case.
405  if (!prim || prim.IsMaster() || prim.GetPath() == _rootPath)
406  return &default_;
407 
408  _Entry* entry = _GetCacheEntryForPrim(prim);
409  if (entry->version == _GetValidVersion()) {
410  // Cache hit
411  return &entry->value;
412  }
413 
414  // Future work: Suggestion is that when multiple threads are computing the
415  // same value, we could block all but one thread here, possibly rescheduling
416  // blocked threads as continuations, rather than allowing all threads to
417  // continue to race until a cache hit is encountered.
418 
419  // Future work: A suggestion is that we make this iterative instead of
420  // recursive.
421  typename ValueOverridesMap::const_iterator it =
422  _valueOverrides.find(prim);
423  if (it != _valueOverrides.end()) {
424  _SetCacheEntryForPrim(prim, it->second, entry);
425  } else {
426  _SetCacheEntryForPrim(prim,
427  Strategy::Inherit(this, prim, &entry->query),
428  entry);
429  }
430  return &entry->value;
431 }
432 
433 PXR_NAMESPACE_CLOSE_SCOPE
434 
435 // -------------------------------------------------------------------------- //
436 // Xform Cache
437 // -------------------------------------------------------------------------- //
438 
439 #include "pxr/usd/usdGeom/xformable.h"
440 #include "pxr/base/gf/matrix4d.h"
441 
442 PXR_NAMESPACE_OPEN_SCOPE
443 
444 struct UsdImaging_XfStrategy;
445 typedef UsdImaging_InheritedCache<UsdImaging_XfStrategy> UsdImaging_XformCache;
446 
447 struct UsdImaging_XfStrategy {
448  typedef GfMatrix4d value_type;
449  typedef UsdGeomXformable::XformQuery query_type;
450 
451  static
452  bool ValueMightBeTimeVarying() { return true; }
453  static
454  value_type MakeDefault() { return GfMatrix4d(1); }
455 
456  static
457  query_type MakeQuery(UsdPrim prim, bool *) {
458  if (UsdGeomXformable xf = UsdGeomXformable(prim))
459  return query_type(xf);
460  return query_type();
461  }
462 
463  static
464  value_type
465  Inherit(UsdImaging_XformCache const* owner,
466  UsdPrim prim,
467  query_type const* query)
468  {
469  value_type xform = MakeDefault();
470  // No need to check query validity here because XformQuery doesn't
471  // support it.
472  query->GetLocalTransformation(&xform, owner->GetTime());
473 
474  return !query->GetResetXformStack()
475  ? (xform * (*owner->_GetValue(prim.GetParent())))
476  : xform;
477  }
478 
479  // Compute the full transform, this is not part of the interface required by
480  // the cache.
481  static
482  value_type
483  ComputeTransform(UsdPrim const& prim,
484  SdfPath const& rootPath,
485  UsdTimeCode time,
486  const TfHashMap<SdfPath, GfMatrix4d, SdfPath::Hash> &ctmOverrides)
487  {
488  bool reset = false;
489  GfMatrix4d ctm(1.0);
490  GfMatrix4d localXf(1.0);
491  UsdPrim p = prim;
492  while (p && p.GetPath() != rootPath) {
493  const auto &overIt = ctmOverrides.find(p.GetPath());
494  // If there's a ctm override, use it and break out of the loop.
495  if (overIt != ctmOverrides.end()) {
496  ctm *= overIt->second;
497  break;
498  } else if (UsdGeomXformable xf = UsdGeomXformable(p)) {
499  if (xf.GetLocalTransformation(&localXf, &reset, time))
500  ctm *= localXf;
501  if (reset)
502  break;
503  }
504  p = p.GetParent();
505  }
506  return ctm;
507  }
508 };
509 
510 PXR_NAMESPACE_CLOSE_SCOPE
511 
512 // -------------------------------------------------------------------------- //
513 // Visibility Cache
514 // -------------------------------------------------------------------------- //
515 
516 #include "pxr/usd/usdGeom/imageable.h"
517 #include "pxr/base/tf/token.h"
518 #include "pxr/usdImaging/usdImaging/debugCodes.h"
519 
520 PXR_NAMESPACE_OPEN_SCOPE
521 
522 struct UsdImaging_VisStrategy;
523 typedef UsdImaging_InheritedCache<UsdImaging_VisStrategy> UsdImaging_VisCache;
524 
525 struct UsdImaging_VisStrategy {
526  typedef TfToken value_type; // invisible, inherited
527  typedef UsdAttributeQuery query_type;
528 
529  static
530  bool ValueMightBeTimeVarying() { return true; }
531  static
532  value_type MakeDefault() { return UsdGeomTokens->inherited; }
533 
534  static
535  query_type MakeQuery(UsdPrim prim, bool *) {
536  if (UsdGeomImageable xf = UsdGeomImageable(prim))
537  return query_type(xf.GetVisibilityAttr());
538  return query_type();
539  }
540 
541  static
542  value_type
543  Inherit(UsdImaging_VisCache const* owner,
544  UsdPrim prim,
545  query_type const* query)
546  {
547  value_type v = *owner->_GetValue(prim.GetParent());
548  if (v == UsdGeomTokens->invisible)
549  return v;
550  if (*query)
551  query->Get(&v, owner->GetTime());
552  return v;
553  }
554 
555  static
556  value_type
557  ComputeVisibility(UsdPrim const& prim, UsdTimeCode time)
558  {
559  return UsdGeomImageable(prim).ComputeVisibility(time);
560  }
561 };
562 
563 // -------------------------------------------------------------------------- //
564 // Purpose Cache
565 // -------------------------------------------------------------------------- //
566 
567 struct UsdImaging_PurposeStrategy;
568 typedef UsdImaging_InheritedCache<UsdImaging_PurposeStrategy>
569  UsdImaging_PurposeCache;
570 
571 struct UsdImaging_PurposeStrategy {
572  typedef TfToken value_type; // purpose, inherited
573  typedef UsdAttributeQuery query_type;
574 
575  static
576  value_type MakeDefault() { return UsdGeomTokens->default_; }
577 
578  static
579  query_type MakeQuery(UsdPrim prim, bool *) {
581  return im ? query_type(im.GetPurposeAttr()) : query_type();
582  }
583 
584  static
585  value_type
586  Inherit(UsdImaging_PurposeCache const* owner,
587  UsdPrim prim,
588  query_type const* query)
589  {
590 
591  value_type v = *owner->_GetValue(prim.GetParent());
592 
593  if (v != UsdGeomTokens->default_)
594  return v;
595 
596  if (*query)
597  query->Get(&v);
598  return v;
599  }
600 
601  static
602  value_type
603  ComputePurpose(UsdPrim const& prim)
604  {
605  return UsdGeomImageable(prim).ComputePurpose();
606  }
607 };
608 
609 PXR_NAMESPACE_CLOSE_SCOPE
610 
611 // -------------------------------------------------------------------------- //
612 // Hydra MaterialBinding Cache
613 // -------------------------------------------------------------------------- //
614 
615 #include "pxr/usd/usdShade/material.h"
616 #include "pxr/usd/usdShade/materialBindingAPI.h"
617 
618 PXR_NAMESPACE_OPEN_SCOPE
619 
620 struct UsdImaging_MaterialBindingImplData {
623  UsdImaging_MaterialBindingImplData(const TfToken &materialPurpose):
624  _materialPurpose(materialPurpose)
625  { }
626 
629  ~UsdImaging_MaterialBindingImplData() {
630  ClearCaches();
631  }
632 
634  const TfToken &GetMaterialPurpose() const {
635  return _materialPurpose;
636  }
637 
640  UsdShadeMaterialBindingAPI::BindingsCache & GetBindingsCache()
641  { return _bindingsCache; }
642 
645  UsdShadeMaterialBindingAPI::CollectionQueryCache & GetCollectionQueryCache()
646  { return _collQueryCache; }
647 
649  void ClearCaches();
650 
651 private:
652  const TfToken _materialPurpose;
655 };
656 
657 struct UsdImaging_MaterialStrategy;
658 typedef UsdImaging_InheritedCache<UsdImaging_MaterialStrategy,
659  UsdImaging_MaterialBindingImplData>
660  UsdImaging_MaterialBindingCache;
661 
662 struct UsdImaging_MaterialStrategy {
663  typedef SdfPath value_type; // inherited path to bound shader
664  typedef UsdShadeMaterial query_type;
665 
666  using ImplData = UsdImaging_MaterialBindingImplData;
667 
668  static
669  bool ValueMightBeTimeVarying() { return false; }
670  static
671  value_type MakeDefault() { return SdfPath(); }
672 
673  static
674  query_type MakeQuery(
675  UsdPrim prim,
676  ImplData *implData)
677  {
679  &implData->GetBindingsCache(),
680  &implData->GetCollectionQueryCache(),
681  implData->GetMaterialPurpose());
682  }
683 
684  static
685  value_type
686  Inherit(UsdImaging_MaterialBindingCache const* owner,
687  UsdPrim prim,
688  query_type const* query)
689  {
690  TF_DEBUG(USDIMAGING_SHADERS).Msg("Looking for \"preview\" material "
691  "binding for %s\n", prim.GetPath().GetText());
692  if (*query) {
693  SdfPath binding = query->GetPath();
694  if (!binding.IsEmpty()) {
695  return binding;
696  }
697  }
698  // query already contains the resolved material binding for the prim.
699  // Hence, we don't need to inherit the binding from the parent here.
700  // Futhermore, it may be wrong to inherit the binding from the parent,
701  // because in the new scheme, a child of a bound prim can be unbound.
702  return value_type();
703  }
704 
705  static
706  value_type
707  ComputeMaterialPath(UsdPrim const& prim, ImplData *implData) {
708  // We don't need to walk up the namespace here since
709  // ComputeBoundMaterial does it for us.
711  ComputeBoundMaterial(&implData->GetBindingsCache(),
712  &implData->GetCollectionQueryCache(),
713  implData->GetMaterialPurpose())) {
714  return mat.GetPath();
715  }
716  return value_type();
717  }
718 };
719 
720 PXR_NAMESPACE_CLOSE_SCOPE
721 
722 // -------------------------------------------------------------------------- //
723 // ModelDrawMode Cache
724 // -------------------------------------------------------------------------- //
725 
726 #include "pxr/usd/usdGeom/modelAPI.h"
727 
728 PXR_NAMESPACE_OPEN_SCOPE
729 
730 struct UsdImaging_DrawModeStrategy;
731 typedef UsdImaging_InheritedCache<UsdImaging_DrawModeStrategy>
732  UsdImaging_DrawModeCache;
733 
734 struct UsdImaging_DrawModeStrategy
735 {
736  typedef TfToken value_type; // origin, bounds, cards, default
737  typedef UsdAttributeQuery query_type;
738 
739  static
740  bool ValueMightBeTimeVarying() { return false; }
741  static
742  value_type MakeDefault() { return UsdGeomTokens->default_; }
743 
744  static
745  query_type MakeQuery(UsdPrim prim, bool *) {
746  if (UsdAttribute a = UsdGeomModelAPI(prim).GetModelDrawModeAttr())
747  return query_type(a);
748  return query_type();
749  }
750 
751  static
752  value_type
753  Inherit(UsdImaging_DrawModeCache const* owner,
754  UsdPrim prim,
755  query_type const* query)
756  {
757  value_type v = UsdGeomTokens->default_;
758  if (*query) {
759  query->Get(&v);
760  return v;
761  }
762  return *owner->_GetValue(prim.GetParent());
763  }
764 
765  static
766  value_type
767  ComputeDrawMode(UsdPrim const& prim)
768  {
769  return UsdGeomModelAPI(prim).ComputeModelDrawMode();
770  }
771 };
772 
773 PXR_NAMESPACE_CLOSE_SCOPE
774 
775 // -------------------------------------------------------------------------- //
776 // CoordSysBinding Cache
777 // -------------------------------------------------------------------------- //
778 
779 #include "pxr/usd/usdShade/coordSysAPI.h"
780 #include "pxr/imaging/hd/coordSys.h"
781 
782 PXR_NAMESPACE_OPEN_SCOPE
783 
784 struct UsdImaging_CoordSysBindingImplData {
785  // Helper provided by the scene delegate to pre-convert
786  // the binding paths to the equivalent Hydra ID.
787  std::function<SdfPath(SdfPath)> usdToHydraPath;
788 };
789 
790 struct UsdImaging_CoordSysBindingStrategy;
791 
792 typedef UsdImaging_InheritedCache<
793  UsdImaging_CoordSysBindingStrategy,
794  UsdImaging_CoordSysBindingImplData>
795  UsdImaging_CoordSysBindingCache;
796 
797 struct UsdImaging_CoordSysBindingStrategy
798 {
799  using ImplData = UsdImaging_CoordSysBindingImplData;
800 
801  typedef std::vector<UsdShadeCoordSysAPI::Binding> UsdBindingVec;
802  typedef std::shared_ptr<UsdBindingVec> UsdBindingVecPtr;
803  typedef std::shared_ptr<SdfPathVector> IdVecPtr;
804 
805  struct value_type {
806  IdVecPtr idVecPtr;
807  UsdBindingVecPtr usdBindingVecPtr;
808  };
809  struct query_type {
810  UsdShadeCoordSysAPI coordSysAPI;
811  ImplData *implData;
812 
813  // Convert a USD binding relationship to a Hydra ID
814  SdfPath
815  _IdForBinding(UsdShadeCoordSysAPI::Binding const& binding) const {
816  return implData->usdToHydraPath(binding.bindingRelPath);
817  }
818  };
819 
820  static
821  bool ValueMightBeTimeVarying() { return false; }
822 
823  static
824  value_type MakeDefault() {
825  return value_type();
826  }
827 
828  static
829  query_type MakeQuery(UsdPrim prim, ImplData *implData) {
830  return query_type({ UsdShadeCoordSysAPI(prim), implData });
831  }
832 
833  static
834  value_type
835  Inherit(UsdImaging_CoordSysBindingCache const* owner,
836  UsdPrim prim,
837  query_type const* query)
838  {
839  value_type v;
840  if (query->coordSysAPI) {
841  // Pull inherited bindings first.
842  if (UsdPrim parentPrim = prim.GetParent()) {
843  v = *owner->_GetValue(parentPrim);
844  }
845  // Merge any local bindings.
846  if (query->coordSysAPI.HasLocalBindings()) {
847  SdfPathVector hdIds;
848  UsdBindingVec usdBindings;
849  if (v.idVecPtr) {
850  hdIds = *v.idVecPtr;
851  }
852  if (v.usdBindingVecPtr) {
853  usdBindings = *v.usdBindingVecPtr;
854  }
855  for (auto const& binding:
856  query->coordSysAPI.GetLocalBindings()) {
857  bool found = false;
858  for (size_t i=0, n=hdIds.size(); i<n; ++i) {
859  if (usdBindings[i].name == binding.name) {
860  // Found an override -- replace this binding.
861  usdBindings[i] = binding;
862  hdIds[i] = query->_IdForBinding(binding);
863  found = true;
864  break;
865  }
866  }
867  if (!found) {
868  // New binding, so append.
869  usdBindings.push_back(binding);
870  hdIds.push_back(query->_IdForBinding(binding));
871  }
872  }
873  v.idVecPtr.reset(new SdfPathVector(hdIds));
874  v.usdBindingVecPtr.reset(new UsdBindingVec(usdBindings));
875  }
876  }
877  return v;
878  }
879 };
880 
881 PXR_NAMESPACE_CLOSE_SCOPE
882 
883 // -------------------------------------------------------------------------- //
884 // Inherited Primvar Cache
885 // -------------------------------------------------------------------------- //
886 
887 #include "pxr/usd/usdGeom/primvarsAPI.h"
888 
889 PXR_NAMESPACE_OPEN_SCOPE
890 
891 struct UsdImaging_InheritedPrimvarStrategy;
892 typedef UsdImaging_InheritedCache<UsdImaging_InheritedPrimvarStrategy>
893  UsdImaging_InheritedPrimvarCache;
894 
895 struct UsdImaging_InheritedPrimvarStrategy
896 {
897  struct PrimvarRecord {
898  std::vector<UsdGeomPrimvar> primvars;
899  bool variable;
900  };
901  typedef std::shared_ptr<PrimvarRecord> value_type;
902  typedef UsdGeomPrimvarsAPI query_type;
903 
904  // While primvar data might be time-varying, the set of primvars applying
905  // to a prim will not.
906  static
907  bool ValueMightBeTimeVarying() { return false; }
908 
909  static
910  value_type MakeDefault() {
911  return value_type();
912  }
913 
914  static
915  query_type MakeQuery(UsdPrim prim, bool *) {
916  return query_type(UsdGeomPrimvarsAPI(prim));
917  }
918 
919  static
920  value_type Inherit(UsdImaging_InheritedPrimvarCache const* owner,
921  UsdPrim prim,
922  query_type const* query)
923  {
924  value_type v;
925  if (*query) {
926  // Pull inherited bindings first.
927  if (UsdPrim parentPrim = prim.GetParent()) {
928  v = *owner->_GetValue(parentPrim);
929  }
930  // Merge any local bindings.
931  std::vector<UsdGeomPrimvar> primvars =
932  query->FindIncrementallyInheritablePrimvars(
933  v ? v->primvars : std::vector<UsdGeomPrimvar>());
934  if (!primvars.empty()) {
935  v = std::make_shared<PrimvarRecord>();
936  v->primvars = std::move(primvars);
937  v->variable = false;
938  for (UsdGeomPrimvar const& pv : v->primvars) {
939  if (pv.ValueMightBeTimeVarying()) {
940  v->variable = true;
941  break;
942  }
943  }
944  }
945  }
946  return v;
947  }
948 };
949 
950 PXR_NAMESPACE_CLOSE_SCOPE
951 
952 #endif // USDIMAGING_INHERITEDCACHE_H
bool IsInMaster() const
Return true if this prim is located in a subtree of prims rooted at a master prim, false otherwise.
Definition: prim.h:1104
UsdShadeCoordSysAPI provides a way to designate, name, and discover coordinate systems.
Definition: coordSysAPI.h:79
UsdGeomModelAPI extends the generic UsdModelAPI schema with geometry specific concepts such as cached...
Definition: modelAPI.h:146
USDGEOM_API UsdAttribute GetPurposeAttr() const
Purpose is a concept we have found useful in our pipeline for classifying geometry into categories th...
bool IsMaster() const
Return true if this prim is a master prim, false otherwise.
Definition: prim.h:1097
UsdPrim GetParent() const
Return this prim&#39;s parent prim.
Definition: prim.h:644
Object for efficiently making repeated queries for attribute values.
tbb::concurrent_unordered_map< SdfPath, std::unique_ptr< UsdCollectionAPI::MembershipQuery >, SdfPath::Hash > CollectionQueryCache
An unordered list of collection paths mapped to the associated collection&#39;s MembershipQuery object...
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:87
SdfPath GetPath() const
Return the complete scene path to this object on its UsdStage, which may (UsdPrim) or may not (all ot...
Definition: object.h:193
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.
Definition: attribute.h:176
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.
Definition: coordSysAPI.h:163
UsdShadeMaterialBindingAPI is an API schema that provides an interface for binding materials to prims...
UsdGeomPrimvarsAPI encodes geometric &quot;primitive variables&quot;, as UsdGeomPrimvar, which interpolate ac...
Definition: primvarsAPI.h:82
void WorkSwapDestroyAsync(T &obj)
Swap obj with a default-constructed T instance, return and arrange for the swapped-out instance to be...
Definition: utils.h:83
Helper class that caches the ordered vector of UsGeomXformOps that contribute to the local transforma...
Definition: xformable.h:377
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:89
USDGEOM_API TfToken ComputeModelDrawMode(const TfToken &parentDrawMode=TfToken()) const
Calculate the effective model:drawMode of this prim, as defined by its closest ancestral authored opi...
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.
Definition: iterator.h:390
Stores a 4x4 matrix of double elements.
Definition: matrix4d.h:88
Represent a time value, which may be either numeric, holding a double value, or a sentinel value UsdT...
Definition: timeCode.h:85
USDGEOM_API TfStaticData< UsdGeomTokensType > UsdGeomTokens
A global variable with static, efficient TfTokens for use in all public USD API.
#define TRACE_FUNCTION()
Records a timestamp when constructed and a timespan event when destructed, using the name of the func...
Definition: trace.h:43
UsdPrim is the sole persistent scenegraph object on a UsdStage, and is the embodiment of a &quot;Prim&quot; as ...
Definition: prim.h:131
USDGEOM_API bool ValueMightBeTimeVarying() const
Return true if it is possible, but not certain, that this primvar&#39;s value changes over time...
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:287
#define TF_DEBUG(enumVal)
Evaluate and print debugging message msg if enumVal is enabled for debugging.
Definition: debug.h:497
USDGEOM_API TfToken ComputePurpose() const
Calculate the effective purpose of this prim, as defined by its most ancestral authored non-&quot;default&quot;...
SDF_API const std::string & GetString() const
Returns the string representation of this path as a std::string.
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...
Definition: primRange.h:118
A Material provides a container into which multiple &quot;render targets&quot; can add data that defines a &quot;sha...
Definition: material.h:111
Schema wrapper for UsdAttribute for authoring and introspecting attributes that are primvars...
Definition: primvar.h:260
USDGEOM_API TfToken ComputeVisibility(UsdTimeCode const &time=UsdTimeCode::Default()) const
Calculate the effective visibility of this prim, as defined by its most ancestral authored &quot;invisible...
bool IsEmpty() const noexcept
Returns true if this is the empty path (SdfPath::EmptyPath()).
Definition: path.h:409
Base class for all prims that may require rendering or visualization of some sort.
Definition: imageable.h:74
Base class for all transformable prims, which allows arbitrary sequences of component affine transfor...
Definition: xformable.h:252
SDF_API const char * GetText() const
Returns the string representation of this path as a c string.