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 #include "pxr/usdImaging/usdImaging/primAdapter.h"
25 
26 #include "pxr/usdImaging/usdImaging/debugCodes.h"
27 #include "pxr/usdImaging/usdImaging/delegate.h"
28 #include "pxr/usdImaging/usdImaging/indexProxy.h"
29 #include "pxr/usdImaging/usdImaging/resolvedAttributeCache.h"
30 #include "pxr/usdImaging/usdImaging/instancerContext.h"
31 
32 #include "pxr/usd/sdf/schema.h"
33 #include "pxr/usd/usd/collectionAPI.h"
34 #include "pxr/usd/usdGeom/primvarsAPI.h"
35 
36 #include "pxr/imaging/hd/perfLog.h"
37 #include "pxr/imaging/hd/renderDelegate.h"
38 
39 #include "pxr/base/tf/envSetting.h"
40 #include "pxr/base/tf/staticTokens.h"
41 #include "pxr/base/tf/type.h"
42 
43 #include <vector>
44 
45 PXR_NAMESPACE_OPEN_SCOPE
46 
TF_REGISTRY_FUNCTION(TfType)47 TF_REGISTRY_FUNCTION(TfType)
48 {
49     TfType::Define<UsdImagingPrimAdapter>();
50 }
51 
52 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_SHARED_XFORM_CACHE, 1,
53                       "Enable a shared cache for transforms.");
_IsEnabledXformCache()54 static bool _IsEnabledXformCache() {
55     static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_SHARED_XFORM_CACHE) == 1;
56     return _v;
57 }
58 
59 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_BINDING_CACHE, 1,
60                       "Enable a cache for material bindings.");
_IsEnabledBindingCache()61 static bool _IsEnabledBindingCache() {
62     static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_BINDING_CACHE) == 1;
63     return _v;
64 }
65 
66 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_VIS_CACHE, 1,
67                       "Enable a cache for visibility.");
_IsEnabledVisCache()68 static bool _IsEnabledVisCache() {
69     static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_VIS_CACHE) == 1;
70     return _v;
71 }
72 
73 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_PURPOSE_CACHE, 1,
74                       "Enable a cache for purpose.");
_IsEnabledPurposeCache()75 static bool _IsEnabledPurposeCache() {
76     static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_PURPOSE_CACHE) == 1;
77     return _v;
78 }
79 
80 TF_DEFINE_ENV_SETTING(USDIMAGING_ENABLE_POINT_INSTANCER_INDICES_CACHE, 1,
81                       "Enable a cache for point instancer indices.");
_IsEnabledPointInstancerIndicesCache()82 static bool _IsEnabledPointInstancerIndicesCache() {
83     static bool _v = TfGetEnvSetting(USDIMAGING_ENABLE_POINT_INSTANCER_INDICES_CACHE) == 1;
84     return _v;
85 }
86 
~UsdImagingPrimAdapter()87 UsdImagingPrimAdapter::~UsdImagingPrimAdapter()
88 {
89 }
90 
91 /*static*/
92 bool
ShouldCullSubtree(UsdPrim const & prim)93 UsdImagingPrimAdapter::ShouldCullSubtree(UsdPrim const& prim)
94 {
95     // Skip population of non-imageable prims during population traversal
96     // (although they can still be populated by reference).
97     return (!prim.IsA<UsdGeomImageable>() && !prim.GetTypeName().IsEmpty());
98 }
99 
100 /*virtual*/
101 bool
ShouldCullChildren() const102 UsdImagingPrimAdapter::ShouldCullChildren() const
103 {
104     return false;
105 }
106 
107 /*virtual*/
108 bool
ShouldIgnoreNativeInstanceSubtrees() const109 UsdImagingPrimAdapter::ShouldIgnoreNativeInstanceSubtrees() const
110 {
111     return false;
112 }
113 
114 /*virtual*/
115 bool
IsInstancerAdapter() const116 UsdImagingPrimAdapter::IsInstancerAdapter() const
117 {
118     return false;
119 }
120 
121 /*virtual*/
122 bool
CanPopulateUsdInstance() const123 UsdImagingPrimAdapter::CanPopulateUsdInstance() const
124 {
125     return false;
126 }
127 
128 /*virtual*/
129 HdDirtyBits
ProcessPrimChange(UsdPrim const & prim,SdfPath const & cachePath,TfTokenVector const & changedFields)130 UsdImagingPrimAdapter::ProcessPrimChange(UsdPrim const& prim,
131                                          SdfPath const& cachePath,
132                                          TfTokenVector const& changedFields)
133 {
134     // By default, resync the prim if there are any changes to non-plugin
135     // fields and ignore changes to built-in fields. Schemas typically register
136     // their own plugin metadata fields instead of relying on built-in fields.
137     const SdfSchema& schema = SdfSchema::GetInstance();
138     for (const TfToken& field : changedFields) {
139         const SdfSchema::FieldDefinition* fieldDef =
140             schema.GetFieldDefinition(field);
141         if (fieldDef && fieldDef->IsPlugin()) {
142             return HdChangeTracker::AllDirty;
143         }
144     }
145 
146     return HdChangeTracker::Clean;
147 }
148 
149 /*virtual*/
150 void
ProcessPrimResync(SdfPath const & cachePath,UsdImagingIndexProxy * index)151 UsdImagingPrimAdapter::ProcessPrimResync(SdfPath const& cachePath,
152                                          UsdImagingIndexProxy* index)
153 {
154     _RemovePrim(cachePath, index);
155 
156     /// XXX(UsdImagingPaths): We use the cachePath directly as the
157     // usdPath here, but should do the proper transformation.
158     // Maybe we could check the primInfo before its removal.
159     SdfPath const& usdPath = cachePath;
160     if (_GetPrim(usdPath)) {
161         // The prim still exists, so repopulate it.
162         index->Repopulate(/*cachePath*/usdPath);
163     }
164 }
165 
166 /*virtual*/
167 void
_ResyncDependents(SdfPath const & usdPath,UsdImagingIndexProxy * index)168 UsdImagingPrimAdapter::_ResyncDependents(SdfPath const& usdPath,
169                                          UsdImagingIndexProxy* index)
170 {
171     auto const range = _delegate->_dependencyInfo.equal_range(usdPath);
172     for (auto it = range.first; it != range.second; ++it) {
173         SdfPath const& depCachePath = it->second;
174         // If _ResyncDependents is called by the resync method of hydra prim
175         // /Foo, there's a strong chance the hydra prim has a declared
176         // dependency on USD prim /Foo.  (This is true pretty much except for
177         // instancing cases that aren't expected to call this function).
178         //
179         // In order to avoid infinite loops, if the hydra dependency we get has
180         // the same path as the passed in usdPath, skip resyncing it.
181         if (depCachePath == usdPath) {
182             continue;
183         }
184 
185         TF_DEBUG(USDIMAGING_CHANGES)
186             .Msg("<%s> Resyncing dependent %s\n",
187                     usdPath.GetText(), depCachePath.GetText());
188 
189         UsdImagingDelegate::_HdPrimInfo *primInfo =
190             _delegate->_GetHdPrimInfo(depCachePath);
191         if (primInfo != nullptr &&
192             TF_VERIFY(primInfo->adapter != nullptr)) {
193             primInfo->adapter->ProcessPrimResync(depCachePath, index);
194         }
195     }
196 }
197 
198 /*virtual*/
199 void
ProcessPrimRemoval(SdfPath const & cachePath,UsdImagingIndexProxy * index)200 UsdImagingPrimAdapter::ProcessPrimRemoval(SdfPath const& cachePath,
201                                           UsdImagingIndexProxy* index)
202 {
203     _RemovePrim(cachePath, index);
204 }
205 
206 /*virtual*/
207 void
MarkRefineLevelDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)208 UsdImagingPrimAdapter::MarkRefineLevelDirty(UsdPrim const& prim,
209                                             SdfPath const& cachePath,
210                                             UsdImagingIndexProxy* index)
211 {
212 }
213 
214 /*virtual*/
215 void
MarkReprDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)216 UsdImagingPrimAdapter::MarkReprDirty(UsdPrim const& prim,
217                                      SdfPath const& cachePath,
218                                      UsdImagingIndexProxy* index)
219 {
220 }
221 
222 /*virtual*/
223 void
MarkCullStyleDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)224 UsdImagingPrimAdapter::MarkCullStyleDirty(UsdPrim const& prim,
225                                           SdfPath const& cachePath,
226                                           UsdImagingIndexProxy* index)
227 {
228 }
229 
230 /*virtual*/
231 void
MarkRenderTagDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)232 UsdImagingPrimAdapter::MarkRenderTagDirty(UsdPrim const& prim,
233                                           SdfPath const& cachePath,
234                                           UsdImagingIndexProxy* index)
235 {
236 }
237 
238 /*virtual*/
239 void
MarkTransformDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)240 UsdImagingPrimAdapter::MarkTransformDirty(UsdPrim const& prim,
241                                           SdfPath const& cachePath,
242                                           UsdImagingIndexProxy* index)
243 {
244 }
245 
246 /*virtual*/
247 void
MarkVisibilityDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)248 UsdImagingPrimAdapter::MarkVisibilityDirty(UsdPrim const& prim,
249                                            SdfPath const& cachePath,
250                                            UsdImagingIndexProxy* index)
251 {
252 }
253 
254 /*virtual*/
255 void
MarkMaterialDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)256 UsdImagingPrimAdapter::MarkMaterialDirty(UsdPrim const& prim,
257                                          SdfPath const& cachePath,
258                                          UsdImagingIndexProxy* index)
259 {
260 }
261 
262 /*virtual*/
263 void
MarkLightParamsDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)264 UsdImagingPrimAdapter::MarkLightParamsDirty(UsdPrim const& prim,
265                                             SdfPath const& cachePath,
266                                             UsdImagingIndexProxy* index)
267 {
268 }
269 
270 /*virtual*/
271 void
MarkWindowPolicyDirty(UsdPrim const & prim,SdfPath const & cachePath,UsdImagingIndexProxy * index)272 UsdImagingPrimAdapter::MarkWindowPolicyDirty(UsdPrim const& prim,
273                                              SdfPath const& cachePath,
274                                              UsdImagingIndexProxy* index)
275 {
276 }
277 
278 /*virtual*/
279 void
InvokeComputation(SdfPath const & cachePath,HdExtComputationContext * context)280 UsdImagingPrimAdapter::InvokeComputation(SdfPath const& cachePath,
281                                          HdExtComputationContext* context)
282 {
283 }
284 
285 /*virtual*/
286 std::vector<VtArray<TfToken>>
GetInstanceCategories(UsdPrim const & prim)287 UsdImagingPrimAdapter::GetInstanceCategories(UsdPrim const& prim)
288 {
289     return std::vector<VtArray<TfToken>>();
290 }
291 
292 /*virtual*/
293 PxOsdSubdivTags
GetSubdivTags(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const294 UsdImagingPrimAdapter::GetSubdivTags(UsdPrim const& prim,
295                                      SdfPath const& cachePath,
296                                      UsdTimeCode time) const
297 {
298     return PxOsdSubdivTags();
299 }
300 
301 /*virtual*/
302 size_t
SampleInstancerTransform(UsdPrim const & instancerPrim,SdfPath const & instancerPath,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,GfMatrix4d * sampleValues)303 UsdImagingPrimAdapter::SampleInstancerTransform(
304     UsdPrim const& instancerPrim,
305     SdfPath const& instancerPath,
306     UsdTimeCode time,
307     size_t maxNumSamples,
308     float *sampleTimes,
309     GfMatrix4d *sampleValues)
310 {
311     return 0;
312 }
313 
314 /*virtual*/
315 GfMatrix4d
GetInstancerTransform(UsdPrim const & instancerPrim,SdfPath const & instancerPath,UsdTimeCode time) const316 UsdImagingPrimAdapter::GetInstancerTransform(
317     UsdPrim const& instancerPrim,
318     SdfPath const& instancerPath,
319     UsdTimeCode time) const
320 {
321     return GfMatrix4d(1.0);
322 }
323 
324 /*virtual*/
325 SdfPath
GetInstancerId(UsdPrim const & usdPrim,SdfPath const & cachePath) const326 UsdImagingPrimAdapter::GetInstancerId(
327     UsdPrim const& usdPrim,
328     SdfPath const& cachePath) const
329 {
330     return SdfPath::EmptyPath();
331 }
332 
333 /*virtual*/
334 SdfPathVector
GetInstancerPrototypes(UsdPrim const & usdPrim,SdfPath const & cachePath) const335 UsdImagingPrimAdapter::GetInstancerPrototypes(
336     UsdPrim const& usdPrim,
337     SdfPath const& cachePath) const
338 {
339     return SdfPathVector();
340 }
341 
342 /*virtual*/
343 size_t
SamplePrimvar(UsdPrim const & usdPrim,SdfPath const & cachePath,TfToken const & key,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,VtValue * sampleValues,VtIntArray * sampleIndices)344 UsdImagingPrimAdapter::SamplePrimvar(
345     UsdPrim const& usdPrim,
346     SdfPath const& cachePath,
347     TfToken const& key,
348     UsdTimeCode time,
349     size_t maxNumSamples,
350     float *sampleTimes,
351     VtValue *sampleValues,
352     VtIntArray *sampleIndices)
353 {
354     HD_TRACE_FUNCTION();
355 
356     if (maxNumSamples == 0) {
357         return 0;
358     }
359 
360     // Try as USD primvar.
361     // XXX Here we could use the cache.
362     UsdGeomPrimvarsAPI primvars(usdPrim);
363     UsdGeomPrimvar pv = primvars.FindPrimvarWithInheritance(key);
364 
365     GfInterval interval = _GetCurrentTimeSamplingInterval();
366     std::vector<double> timeSamples;
367 
368     if (pv && pv.HasValue()) {
369         if (pv.ValueMightBeTimeVarying()) {
370             pv.GetTimeSamplesInInterval(interval, &timeSamples);
371 
372             // Add time samples at the boundary conditions
373             timeSamples.push_back(interval.GetMin());
374             timeSamples.push_back(interval.GetMax());
375 
376             // Sort here
377             std::sort(timeSamples.begin(), timeSamples.end());
378             timeSamples.erase(
379                 std::unique(timeSamples.begin(),
380                     timeSamples.end()),
381                     timeSamples.end());
382 
383             size_t numSamples = timeSamples.size();
384 
385             // XXX: We should add caching to the transform computation if this shows
386             // up in profiling, but all of our current caches are cleared on time
387             // change so we'd need to write a new structure.
388             size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
389 
390             if (sampleIndices) {
391                 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
392                     sampleTimes[i] = timeSamples[i] - time.GetValue();
393                     if (pv.Get(&sampleValues[i], timeSamples[i])) {
394                         if (!pv.GetIndices(&sampleIndices[i], timeSamples[i])) {
395                             sampleIndices[i].clear();
396                         }
397                     }
398                 }
399             } else {
400                 for (size_t i=0; i < numSamplesToEvaluate; ++i) {
401                     sampleTimes[i] = timeSamples[i] - time.GetValue();
402                     pv.ComputeFlattened(&sampleValues[i], timeSamples[i]);
403                 }
404             }
405             return numSamples;
406         } else {
407             // Return a single sample for non-varying primvars
408             sampleTimes[0] = 0.0f;
409             if (sampleIndices) {
410                 if (pv.Get(sampleValues, time)) {
411                     if (!pv.GetIndices(sampleIndices, time)) {
412                         sampleIndices->clear();
413                     }
414                 }
415             } else {
416                 pv.ComputeFlattened(sampleValues, time);
417             }
418             return 1;
419         }
420     }
421 
422     // Try as USD attribute.  This handles cases like "points" that
423     // are considered primvars by Hydra but non-primvar attributes by USD.
424     if (UsdAttribute attr = usdPrim.GetAttribute(key)) {
425         if (attr.ValueMightBeTimeVarying()) {
426             attr.GetTimeSamplesInInterval(interval, &timeSamples);
427 
428             // Add time samples at the boudary conditions
429             timeSamples.push_back(interval.GetMin());
430             timeSamples.push_back(interval.GetMax());
431 
432             // Sort here
433             std::sort(timeSamples.begin(), timeSamples.end());
434             timeSamples.erase(
435                 std::unique(timeSamples.begin(),
436                     timeSamples.end()),
437                     timeSamples.end());
438 
439             size_t numSamples = timeSamples.size();
440 
441             // XXX: We should add caching to the transform computation if this
442             // shows up in profiling, but all of our current caches are cleared
443             // on time change so we'd need to write a new structure.
444             size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
445             for (size_t i=0; i < numSamplesToEvaluate; ++i) {
446                 sampleTimes[i] = timeSamples[i] - time.GetValue();
447                 attr.Get(&sampleValues[i], timeSamples[i]);
448             }
449             return numSamples;
450         } else {
451             // Return a single sample for non-varying primvars
452             sampleTimes[0] = 0;
453             attr.Get(sampleValues, time);
454             return 1;
455         }
456     }
457 
458     // Fallback for adapters that do not read primvars from USD, but
459     // instead synthesize them -- ex: Cube, Cylinder, Capsule.
460     if (maxNumSamples > 0) {
461         sampleTimes[0] = 0;
462         sampleValues[0] = Get(usdPrim, cachePath, key, time, &sampleIndices[0]);
463         return sampleValues[0].IsEmpty() ? 0 : 1;
464     }
465 
466     return 0;
467 }
468 
469 /*virtual*/
470 SdfPath
GetScenePrimPath(SdfPath const & cachePath,int instanceIndex,HdInstancerContext * instancerCtx) const471 UsdImagingPrimAdapter::GetScenePrimPath(
472     SdfPath const& cachePath,
473     int instanceIndex,
474     HdInstancerContext *instancerCtx) const
475 {
476     // Note: if we end up here, we're not instanced, since primInfo
477     // holds the instance adapter for instanced gprims.
478     return cachePath;
479 }
480 
481 /*virtual*/
482 bool
PopulateSelection(HdSelection::HighlightMode const & mode,SdfPath const & cachePath,UsdPrim const & usdPrim,int const hydraInstanceIndex,VtIntArray const & parentInstanceIndices,HdSelectionSharedPtr const & result) const483 UsdImagingPrimAdapter::PopulateSelection(
484     HdSelection::HighlightMode const& mode,
485     SdfPath const &cachePath,
486     UsdPrim const &usdPrim,
487     int const hydraInstanceIndex,
488     VtIntArray const &parentInstanceIndices,
489     HdSelectionSharedPtr const &result) const
490 {
491     // usdPrim (the original prim selection) might point to a parent node of
492     // this hydra prim; but it's also possible for it to point to dependent
493     // data sources like materials/coord systems/etc.  Only apply the highlight
494     // if usdPrim is a parent of cachePath.
495     // Note: this strategy won't work for native instanced prims, but we expect
496     // those to be handled in the instance adapter PopulateSelection.
497     if (!cachePath.HasPrefix(usdPrim.GetPath())) {
498         return false;
499     }
500 
501     const SdfPath indexPath = _delegate->ConvertCachePathToIndexPath(cachePath);
502 
503     // Insert gprim into the selection map.
504     // If "hydraInstanceIndex" is set, just use that.
505     // Otherwise, parentInstanceIndices either points to an arry of flat indices
506     // to highlight, or (if it's empty) it indicates highlight all indices.
507     if (hydraInstanceIndex != -1) {
508         VtIntArray indices(1, hydraInstanceIndex);
509         result->AddInstance(mode, indexPath, indices);
510     } else if (parentInstanceIndices.size() == 0) {
511         result->AddRprim(mode, indexPath);
512     } else {
513         result->AddInstance(mode, indexPath, parentInstanceIndices);
514     }
515 
516     if (TfDebug::IsEnabled(USDIMAGING_SELECTION)) {
517         std::stringstream ss;
518         if (hydraInstanceIndex != -1) {
519             ss << hydraInstanceIndex;
520         } else {
521             ss << parentInstanceIndices;
522         }
523         TF_DEBUG(USDIMAGING_SELECTION).Msg("PopulateSelection: (prim) %s %s\n",
524             indexPath.GetText(), ss.str().c_str());
525     }
526 
527     return true;
528 }
529 
530 HdVolumeFieldDescriptorVector
GetVolumeFieldDescriptors(UsdPrim const & usdPrim,SdfPath const & id,UsdTimeCode time) const531 UsdImagingPrimAdapter::GetVolumeFieldDescriptors(UsdPrim const& usdPrim,
532 	                                         SdfPath const &id,
533                                                  UsdTimeCode time) const
534 {
535     return HdVolumeFieldDescriptorVector();
536 }
537 
538 void
SetDelegate(UsdImagingDelegate * delegate)539 UsdImagingPrimAdapter::SetDelegate(UsdImagingDelegate* delegate)
540 {
541     _delegate = delegate;
542 }
543 
544 bool
IsChildPath(SdfPath const & path) const545 UsdImagingPrimAdapter::IsChildPath(SdfPath const& path) const
546 {
547     return path.IsPropertyPath();
548 }
549 
550 UsdImagingPrimvarDescCache*
_GetPrimvarDescCache() const551 UsdImagingPrimAdapter::_GetPrimvarDescCache() const
552 {
553     return &_delegate->_primvarDescCache;
554 }
555 
556 GfMatrix4d
GetRootTransform() const557 UsdImagingPrimAdapter::GetRootTransform() const
558 {
559     return _delegate->GetRootTransform();
560 }
561 
562 UsdPrim
_GetPrim(SdfPath const & usdPath) const563 UsdImagingPrimAdapter::_GetPrim(SdfPath const& usdPath) const
564 {
565     // Intentionally not calling _delegate->_GetPrim here because it strictly
566     // requires the prim to exist.
567     return _delegate->_stage->GetPrimAtPath(usdPath);
568 }
569 
570 const UsdImagingPrimAdapterSharedPtr&
_GetPrimAdapter(UsdPrim const & prim,bool ignoreInstancing) const571 UsdImagingPrimAdapter::_GetPrimAdapter(UsdPrim const& prim,
572                                        bool ignoreInstancing) const
573 {
574     return _delegate->_AdapterLookup(prim, ignoreInstancing);
575 }
576 
577 const UsdImagingPrimAdapterSharedPtr&
_GetAdapter(TfToken const & adapterKey) const578 UsdImagingPrimAdapter::_GetAdapter(TfToken const& adapterKey) const
579 {
580     return _delegate->_AdapterLookup(adapterKey);
581 }
582 
583 SdfPath
_GetPrimPathFromInstancerChain(SdfPathVector const & instancerChain) const584 UsdImagingPrimAdapter::_GetPrimPathFromInstancerChain(
585                                      SdfPathVector const& instancerChain) const
586 {
587     // The instancer chain is stored more-to-less local.  For example:
588     //
589     // ProtoCube   <----+
590     //   +-- cube       | (native instance)
591     // ProtoA           |  <--+
592     //   +-- ProtoCube--+     | (native instance)
593     // PointInstancer         |
594     //   +-- ProtoA ----------+
595     //
596     // paths =
597     //    /__Prototype_1/cube
598     //    /__Prototype_2/ProtoCube
599     //    /PointInstancer/ProtoA
600     //
601     // This function uses the path chain to recreate the instance path:
602     //    /PointInstancer/ProtoA/ProtoCube/cube
603 
604     if (instancerChain.size() == 0) {
605         return SdfPath();
606     }
607 
608     SdfPath primPath = instancerChain[0];
609 
610     // Every path except the last path should be a path in prototype.  The idea
611     // is to replace the prototype path with the instance path that comes next
612     // in the chain, and continue until we're back at scene scope.
613     for (size_t i = 1; i < instancerChain.size(); ++i)
614     {
615         UsdPrim prim = _GetPrim(primPath);
616         TF_VERIFY(prim.IsInPrototype());
617 
618         UsdPrim prototype = prim;
619         while (!prototype.IsPrototype()) {
620             prototype = prototype.GetParent();
621         }
622         primPath = primPath.ReplacePrefix(
623             prototype.GetPath(), instancerChain[i]);
624     }
625 
626     return primPath;
627 }
628 
629 UsdTimeCode
_GetTimeWithOffset(float offset) const630 UsdImagingPrimAdapter::_GetTimeWithOffset(float offset) const
631 {
632     return _delegate->GetTimeWithOffset(offset);
633 }
634 
635 SdfPath
_ConvertCachePathToIndexPath(const SdfPath & usdPath) const636 UsdImagingPrimAdapter::_ConvertCachePathToIndexPath(const SdfPath &usdPath) const
637 {
638     return _delegate->ConvertCachePathToIndexPath(usdPath);
639 }
640 
641 SdfPath
_ConvertIndexPathToCachePath(const SdfPath & indexPath) const642 UsdImagingPrimAdapter::_ConvertIndexPathToCachePath(const SdfPath &indexPath) const
643 {
644     return _delegate->ConvertIndexPathToCachePath(indexPath);
645 }
646 
647 TfToken
_GetMaterialBindingPurpose() const648 UsdImagingPrimAdapter::_GetMaterialBindingPurpose() const
649 {
650     return _delegate->GetRenderIndex().GetRenderDelegate()->
651         GetMaterialBindingPurpose();
652 }
653 
654 TfTokenVector
_GetMaterialRenderContexts() const655 UsdImagingPrimAdapter::_GetMaterialRenderContexts() const
656 {
657     return _delegate->GetRenderIndex().GetRenderDelegate()->
658         GetMaterialRenderContexts();
659 }
660 
661 bool
_IsPrimvarFilteringNeeded() const662 UsdImagingPrimAdapter::_IsPrimvarFilteringNeeded() const
663 {
664     return _delegate->GetRenderIndex().GetRenderDelegate()->
665         IsPrimvarFilteringNeeded();
666 }
667 
668 
669 TfTokenVector
_GetShaderSourceTypes() const670 UsdImagingPrimAdapter::_GetShaderSourceTypes() const
671 {
672     return _delegate->GetRenderIndex().GetRenderDelegate()->
673             GetShaderSourceTypes();
674 }
675 
676 bool
_IsInInvisedPaths(SdfPath const & usdPath) const677 UsdImagingPrimAdapter::_IsInInvisedPaths(SdfPath const& usdPath) const
678 {
679     return _delegate->IsInInvisedPaths(usdPath);
680 }
681 
682 void
_MergePrimvar(HdPrimvarDescriptorVector * vec,TfToken const & name,HdInterpolation interp,TfToken const & role,bool indexed) const683 UsdImagingPrimAdapter::_MergePrimvar(
684     HdPrimvarDescriptorVector* vec,
685     TfToken const& name,
686     HdInterpolation interp,
687     TfToken const& role,
688     bool indexed) const
689 {
690     HdPrimvarDescriptor primvar(name, interp, role, indexed);
691     HdPrimvarDescriptorVector::iterator it =
692         std::find(vec->begin(), vec->end(), primvar);
693     if (it == vec->end())
694         vec->push_back(primvar);
695     else
696         *it = primvar;
697 }
698 
699 void
_RemovePrimvar(HdPrimvarDescriptorVector * vec,TfToken const & name) const700 UsdImagingPrimAdapter::_RemovePrimvar(
701     HdPrimvarDescriptorVector* vec,
702     TfToken const& name) const
703 {
704     for (HdPrimvarDescriptorVector::iterator it = vec->begin();
705          it != vec->end(); ++it) {
706         if (it->name == name) {
707             vec->erase(it);
708             return;
709         }
710     }
711 }
712 
713 /* static */
714 HdInterpolation
_UsdToHdInterpolation(TfToken const & usdInterp)715 UsdImagingPrimAdapter::_UsdToHdInterpolation(TfToken const& usdInterp)
716 {
717     if (usdInterp == UsdGeomTokens->uniform) {
718         return HdInterpolationUniform;
719     } else if (usdInterp == UsdGeomTokens->vertex) {
720         return HdInterpolationVertex;
721     } else if (usdInterp == UsdGeomTokens->varying) {
722         return HdInterpolationVarying;
723     } else if (usdInterp == UsdGeomTokens->faceVarying) {
724         return HdInterpolationFaceVarying;
725     } else if (usdInterp == UsdGeomTokens->constant) {
726         return HdInterpolationConstant;
727     }
728     TF_CODING_ERROR("Unknown USD interpolation %s; treating as constant",
729                     usdInterp.GetText());
730     return HdInterpolationConstant;
731 }
732 
733 /* static */
734 TfToken
_UsdToHdRole(TfToken const & usdRole)735 UsdImagingPrimAdapter::_UsdToHdRole(TfToken const& usdRole)
736 {
737     if (usdRole == SdfValueRoleNames->Point) {
738         return HdPrimvarRoleTokens->point;
739     } else if (usdRole == SdfValueRoleNames->Normal) {
740         return HdPrimvarRoleTokens->normal;
741     } else if (usdRole == SdfValueRoleNames->Vector) {
742         return HdPrimvarRoleTokens->vector;
743     } else if (usdRole == SdfValueRoleNames->Color) {
744         return HdPrimvarRoleTokens->color;
745     } else if (usdRole == SdfValueRoleNames->TextureCoordinate) {
746         return HdPrimvarRoleTokens->textureCoordinate;
747     }
748     // Empty token means no role specified
749     return TfToken();
750 }
751 
752 
753 void
_ComputeAndMergePrimvar(UsdPrim const & gprim,UsdGeomPrimvar const & primvar,UsdTimeCode time,HdPrimvarDescriptorVector * primvarDescs,HdInterpolation * interpOverride) const754 UsdImagingPrimAdapter::_ComputeAndMergePrimvar(
755     UsdPrim const& gprim,
756     UsdGeomPrimvar const& primvar,
757     UsdTimeCode time,
758     HdPrimvarDescriptorVector* primvarDescs,
759     HdInterpolation *interpOverride) const
760 {
761     TRACE_FUNCTION();
762 
763     VtValue v;
764     TfToken primvarName = primvar.GetPrimvarName();
765 
766     // Note: we call Get() here to check if the primvar exists.
767     // We can't call HasValue(), since it won't take time-varying
768     // blocks (from value clips) into account. Get() should be
769     // fast as long as we don't touch the returned data.
770     if (primvar.Get(&v, time)) {
771         HdInterpolation interp = interpOverride ? *interpOverride
772             : _UsdToHdInterpolation(primvar.GetInterpolation());
773         TfToken role = _UsdToHdRole(primvar.GetAttr().GetRoleName());
774         TF_DEBUG(USDIMAGING_SHADERS)
775             .Msg("UsdImaging: found primvar (%s) %s, interp %s\n",
776                  gprim.GetPath().GetText(),
777                  primvarName.GetText(),
778                  TfEnum::GetName(interp).c_str());
779         _MergePrimvar(primvarDescs, primvarName, interp, role,
780                       primvar.IsIndexed());
781 
782     } else {
783         TF_DEBUG(USDIMAGING_SHADERS)
784             .Msg( "\t\t No primvar on <%s> named %s\n",
785                   gprim.GetPath().GetText(), primvarName.GetText());
786         _RemovePrimvar(primvarDescs, primvarName);
787     }
788 }
789 
790 namespace {
791 
792 // The types of primvar changes expected
793 enum PrimvarChange {
794     PrimvarChangeValue,
795     PrimvarChangeAdd,
796     PrimvarChangeRemove,
797     PrimvarChangeDesc
798 };
799 
800 // Maps the primvar changes (above) to the dirty bit that needs to be set.
801 /*static*/
802 HdDirtyBits
_GetDirtyBitsForPrimvarChange(PrimvarChange changeType,HdDirtyBits valueChangeDirtyBit)803 _GetDirtyBitsForPrimvarChange(
804     PrimvarChange changeType,
805     HdDirtyBits valueChangeDirtyBit)
806 {
807     HdDirtyBits dirty = HdChangeTracker::Clean;
808 
809     switch (changeType) {
810         case PrimvarChangeAdd:
811         case PrimvarChangeRemove:
812         case PrimvarChangeDesc:
813         {
814             // XXX: Once we have a bit for descriptor changes, we should use
815             // that instead.
816             dirty = HdChangeTracker::DirtyPrimvar;
817             break;
818         }
819         case PrimvarChangeValue:
820         {
821             dirty = valueChangeDirtyBit;
822             break;
823         }
824         default:
825         {
826             TF_CODING_ERROR("Unsupported PrimvarChange %d\n", changeType);
827         }
828     }
829 
830     return dirty;
831 }
832 
833 // Figure out what changed about the primvar and returns the appropriate dirty
834 // bit.
835 /*static*/
836 PrimvarChange
_ProcessPrimvarChange(bool primvarOnPrim,HdInterpolation primvarInterpOnPrim,TfToken const & primvarName,HdPrimvarDescriptorVector * primvarDescs,SdfPath const & cachePath)837 _ProcessPrimvarChange(bool primvarOnPrim,
838                       HdInterpolation primvarInterpOnPrim,
839                       TfToken const& primvarName,
840                       HdPrimvarDescriptorVector* primvarDescs,
841                       SdfPath const& cachePath/*debug*/)
842 {
843     // Determine if primvar is in the value cache.
844     HdPrimvarDescriptorVector::iterator primvarIt = primvarDescs->end();
845     for (HdPrimvarDescriptorVector::iterator it = primvarDescs->begin();
846          it != primvarDescs->end(); it++) {
847         if (it->name == primvarName) {
848             primvarIt = it;
849             break;
850         }
851     }
852     bool primvarInValueCache = primvarIt != primvarDescs->end();
853 
854     PrimvarChange changeType = PrimvarChangeValue;
855     if (primvarOnPrim && !primvarInValueCache) {
856         changeType = PrimvarChangeAdd;
857     } else if (!primvarOnPrim && primvarInValueCache) {
858         changeType = PrimvarChangeRemove;
859 
860         TF_DEBUG(USDIMAGING_CHANGES).Msg(
861             "Removing primvar descriptor %s for cachePath %s.\n",
862             primvarIt->name.GetText(), cachePath.GetText());
863 
864         // Remove the value cache entry.
865         primvarDescs->erase(primvarIt);
866 
867     } else if (primvarInValueCache && primvarOnPrim &&
868                (primvarIt->interpolation != primvarInterpOnPrim)) {
869         changeType = PrimvarChangeDesc;
870     }
871 
872     return changeType;
873 }
874 
875 } // anonymous namespace
876 
877 HdDirtyBits
_ProcessNonPrefixedPrimvarPropertyChange(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & propertyName,TfToken const & primvarName,HdInterpolation const & primvarInterp,HdDirtyBits valueChangeDirtyBit) const878 UsdImagingPrimAdapter::_ProcessNonPrefixedPrimvarPropertyChange(
879         UsdPrim const& prim,
880         SdfPath const& cachePath,
881         TfToken const& propertyName,
882         TfToken const& primvarName,
883         HdInterpolation const& primvarInterp,
884         HdDirtyBits valueChangeDirtyBit
885             /*= HdChangeTracker::DirtyPrimvar*/) const
886 {
887     // Determine if primvar exists on the prim.
888     bool primvarOnPrim = false;
889     UsdAttribute attr = prim.GetAttribute(propertyName);
890     if (attr && attr.HasValue()) {
891         // The expectation is that this method is used for "built-in" attributes
892         // that are treated as primvars.
893         if (UsdGeomPrimvar::IsPrimvar(attr)) {
894             TF_CODING_ERROR("Prefixed primvar (%s) with cache path %s should "
895                 "use _ProcessPrefixedPrimvarPropertyChange instead.\n",
896                 propertyName.GetText(), cachePath.GetText());
897 
898             return HdChangeTracker::AllDirty;
899         }
900 
901         primvarOnPrim = true;
902     }
903 
904     HdPrimvarDescriptorVector& primvarDescs =
905         _GetPrimvarDescCache()->GetPrimvars(cachePath);
906 
907     PrimvarChange changeType =
908         _ProcessPrimvarChange(primvarOnPrim, primvarInterp,
909                               primvarName, &primvarDescs, cachePath);
910 
911     return _GetDirtyBitsForPrimvarChange(changeType, valueChangeDirtyBit);
912 }
913 
914 HdDirtyBits
_ProcessPrefixedPrimvarPropertyChange(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & propertyName,HdDirtyBits valueChangeDirtyBit,bool inherited) const915 UsdImagingPrimAdapter::_ProcessPrefixedPrimvarPropertyChange(
916         UsdPrim const& prim,
917         SdfPath const& cachePath,
918         TfToken const& propertyName,
919         HdDirtyBits valueChangeDirtyBit/*= HdChangeTracker::DirtyPrimvar*/,
920         bool inherited/*=true*/) const
921 {
922     // Determine if primvar exists on the prim.
923     bool primvarOnPrim = false;
924     UsdAttribute attr;
925     TfToken interpOnPrim;
926     HdInterpolation hdInterpOnPrim = HdInterpolationConstant;
927     UsdGeomPrimvarsAPI api(prim);
928     if (inherited) {
929         UsdGeomPrimvar pv = api.FindPrimvarWithInheritance(propertyName);
930         attr = pv;
931         if (pv)
932             interpOnPrim = pv.GetInterpolation();
933     } else {
934         UsdGeomPrimvar localPv = api.GetPrimvar(propertyName);
935         attr = localPv;
936         if (localPv)
937             interpOnPrim = localPv.GetInterpolation();
938     }
939     if (attr && attr.HasValue()) {
940         primvarOnPrim = true;
941         hdInterpOnPrim = _UsdToHdInterpolation(interpOnPrim);
942     }
943 
944     // Determine if primvar is in the value cache.
945     TfToken primvarName = UsdGeomPrimvar::StripPrimvarsName(propertyName);
946     HdPrimvarDescriptorVector& primvarDescs =
947         _GetPrimvarDescCache()->GetPrimvars(cachePath);
948 
949     PrimvarChange changeType = _ProcessPrimvarChange(primvarOnPrim,
950                                  hdInterpOnPrim,
951                                  primvarName, &primvarDescs, cachePath);
952 
953     return _GetDirtyBitsForPrimvarChange(changeType, valueChangeDirtyBit);
954 }
955 
956 UsdImaging_CollectionCache&
_GetCollectionCache() const957 UsdImagingPrimAdapter::_GetCollectionCache() const
958 {
959     return _delegate->_collectionCache;
960 }
961 
962 UsdImaging_CoordSysBindingStrategy::value_type
_GetCoordSysBindings(UsdPrim const & prim) const963 UsdImagingPrimAdapter::_GetCoordSysBindings(UsdPrim const& prim) const
964 {
965     return _delegate->_coordSysBindingCache.GetValue(prim);
966 }
967 
968 UsdImaging_InheritedPrimvarStrategy::value_type
_GetInheritedPrimvars(UsdPrim const & prim) const969 UsdImagingPrimAdapter::_GetInheritedPrimvars(UsdPrim const& prim) const
970 {
971     return _delegate->_inheritedPrimvarCache.GetValue(prim);
972 }
973 
974 bool
_DoesDelegateSupportCoordSys() const975 UsdImagingPrimAdapter::_DoesDelegateSupportCoordSys() const
976 {
977     return _delegate->_coordSysEnabled;
978 }
979 
980 bool
_IsVarying(UsdPrim prim,TfToken const & attrName,HdDirtyBits dirtyFlag,TfToken const & perfToken,HdDirtyBits * dirtyFlags,bool isInherited,bool * exists) const981 UsdImagingPrimAdapter::_IsVarying(UsdPrim prim,
982                                   TfToken const& attrName,
983                                   HdDirtyBits dirtyFlag,
984                                   TfToken const& perfToken,
985                                   HdDirtyBits* dirtyFlags,
986                                   bool isInherited,
987                                   bool *exists) const
988 {
989     HD_TRACE_FUNCTION();
990     HF_MALLOC_TAG_FUNCTION();
991 
992     if (exists != nullptr) {
993         *exists = false;
994     }
995 
996     do {
997         UsdAttribute attr = prim.GetAttribute(attrName);
998 
999         if (attr && exists != nullptr) {
1000             *exists = true;
1001         }
1002         if (attr.ValueMightBeTimeVarying()){
1003             (*dirtyFlags) |= dirtyFlag;
1004             HD_PERF_COUNTER_INCR(perfToken);
1005             return true;
1006         }
1007         prim = prim.GetParent();
1008 
1009     } while (isInherited && prim.GetPath() != SdfPath::AbsoluteRootPath());
1010 
1011     return false;
1012 }
1013 
1014 bool
_IsTransformVarying(UsdPrim prim,HdDirtyBits dirtyFlag,TfToken const & perfToken,HdDirtyBits * dirtyFlags) const1015 UsdImagingPrimAdapter::_IsTransformVarying(UsdPrim prim,
1016                                            HdDirtyBits dirtyFlag,
1017                                            TfToken const& perfToken,
1018                                            HdDirtyBits* dirtyFlags) const
1019 {
1020     HD_TRACE_FUNCTION();
1021     HF_MALLOC_TAG_FUNCTION();
1022 
1023     UsdImaging_XformCache &xfCache = _delegate->_xformCache;
1024 
1025     do {
1026         bool mayXformVary =
1027             xfCache.GetQuery(prim)->TransformMightBeTimeVarying();
1028         if (mayXformVary) {
1029             (*dirtyFlags) |= dirtyFlag;
1030             HD_PERF_COUNTER_INCR(perfToken);
1031             return true;
1032         }
1033 
1034         // If the xformable prim resets the transform stack, then
1035         // we don't have to check the variability of ancestor transforms.
1036         bool resetsXformStack = xfCache.GetQuery(prim)->GetResetXformStack();
1037         if (resetsXformStack) {
1038             break;
1039         }
1040 
1041         prim = prim.GetParent();
1042 
1043     } while (prim.GetPath() != SdfPath::AbsoluteRootPath());
1044 
1045     return false;
1046 }
1047 
1048 GfMatrix4d
GetTransform(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time,bool ignoreRootTransform) const1049 UsdImagingPrimAdapter::GetTransform(UsdPrim const& prim,
1050                                     SdfPath const& cachePath,
1051                                     UsdTimeCode time,
1052                                     bool ignoreRootTransform) const
1053 {
1054     TRACE_FUNCTION();
1055     HF_MALLOC_TAG_FUNCTION();
1056 
1057     UsdImaging_XformCache &xfCache = _delegate->_xformCache;
1058     GfMatrix4d ctm(1.0);
1059 
1060     if (_IsEnabledXformCache() && xfCache.GetTime() == time) {
1061         ctm = xfCache.GetValue(prim);
1062     } else {
1063         ctm = UsdImaging_XfStrategy::ComputeTransform(
1064             prim, xfCache.GetRootPath(), time,
1065             _delegate->_rigidXformOverrides);
1066     }
1067 
1068     return ignoreRootTransform ? ctm : ctm * GetRootTransform();
1069 }
1070 
1071 static
1072 size_t
_GatherAuthoredTransformTimeSamples(UsdPrim const & prim,GfInterval const interval,UsdImaging_XformCache const & xfCache,std::vector<double> * timeSamples)1073 _GatherAuthoredTransformTimeSamples(
1074     UsdPrim const& prim,
1075     GfInterval const interval,
1076     UsdImaging_XformCache const& xfCache,
1077     std::vector<double>* timeSamples)
1078 {
1079     UsdPrim p = prim;
1080     while (p && p.GetPath() != xfCache.GetRootPath()) {
1081         // XXX Add caching here.
1082         if (UsdGeomXformable xf = UsdGeomXformable(p)) {
1083             std::vector<double> localTimeSamples;
1084             xf.GetTimeSamplesInInterval(interval, &localTimeSamples);
1085 
1086             // Join timesamples
1087             timeSamples->insert(
1088                 timeSamples->end(),
1089                 localTimeSamples.begin(),
1090                 localTimeSamples.end());
1091         }
1092         p = p.GetParent();
1093     }
1094 
1095     // Sort here
1096     std::sort(timeSamples->begin(), timeSamples->end());
1097     timeSamples->erase(
1098         std::unique(timeSamples->begin(),
1099             timeSamples->end()),
1100             timeSamples->end());
1101 
1102     return timeSamples->size();
1103 }
1104 
1105 GfInterval
_GetCurrentTimeSamplingInterval()1106 UsdImagingPrimAdapter::_GetCurrentTimeSamplingInterval()
1107 {
1108     return _delegate->GetCurrentTimeSamplingInterval();
1109 }
1110 
1111 Usd_PrimFlagsConjunction
_GetDisplayPredicate() const1112 UsdImagingPrimAdapter::_GetDisplayPredicate() const
1113 {
1114     return _delegate->_GetDisplayPredicate();
1115 }
1116 
1117 Usd_PrimFlagsConjunction
_GetDisplayPredicateForPrototypes() const1118 UsdImagingPrimAdapter::_GetDisplayPredicateForPrototypes() const
1119 {
1120     return _delegate->_GetDisplayPredicateForPrototypes();
1121 }
1122 
1123 size_t
SampleTransform(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time,size_t maxNumSamples,float * sampleTimes,GfMatrix4d * sampleValues)1124 UsdImagingPrimAdapter::SampleTransform(
1125     UsdPrim const& prim,
1126     SdfPath const& cachePath,
1127     UsdTimeCode time,
1128     size_t maxNumSamples,
1129     float *sampleTimes,
1130     GfMatrix4d *sampleValues)
1131 {
1132     HD_TRACE_FUNCTION();
1133 
1134     if (maxNumSamples == 0) {
1135         return 0;
1136     }
1137 
1138     if (!prim) {
1139         // If this is not a literal USD prim, it is an instance of
1140         // other object synthesized by UsdImaging.  Just return
1141         // the single transform sample from the ValueCache.
1142         sampleTimes[0] = 0.0;
1143         sampleValues[0] = GetTransform(prim, prim.GetPath(), 0.0);
1144         return 1;
1145     }
1146 
1147     GfInterval interval = _GetCurrentTimeSamplingInterval();
1148 
1149     // Add time samples at the boudary conditions
1150     std::vector<double> timeSamples;
1151     timeSamples.push_back(interval.GetMin());
1152     timeSamples.push_back(interval.GetMax());
1153 
1154     // Gather authored time samples for transforms
1155     size_t numSamples = _GatherAuthoredTransformTimeSamples(
1156         prim,
1157         interval,
1158         _delegate->_xformCache,
1159         &timeSamples);
1160 
1161     // XXX: We should add caching to the transform computation if this shows
1162     // up in profiling, but all of our current caches are cleared on time
1163     // change so we'd need to write a new structure.
1164     size_t numSamplesToEvaluate = std::min(maxNumSamples, numSamples);
1165     for (size_t i=0; i < numSamplesToEvaluate; ++i) {
1166         sampleTimes[i] = timeSamples[i] - time.GetValue();
1167         sampleValues[i] = UsdImaging_XfStrategy::ComputeTransform(
1168             prim,
1169             _delegate->_xformCache.GetRootPath(),
1170             timeSamples[i],
1171             _delegate->_rigidXformOverrides)
1172                 * _delegate->_rootXf;
1173     }
1174 
1175     // Early out if we can't fit the data in the arrays
1176     if (numSamples > maxNumSamples) {
1177         return numSamples;
1178     }
1179 
1180     // Optimization.
1181     // Some backends benefit if they can avoid time sample animation
1182     // for fixed transforms.  This is difficult to compute explicitly
1183     // due to the hierarchial nature of concated transforms, so we
1184     // do a post-pass sweep to detect static transforms here.
1185     for (size_t i=1; i < numSamples; ++i) {
1186         if (timeSamples[i] != timeSamples[0]) {
1187             return numSamples;
1188         }
1189     }
1190     // All samples are the same, so just return 1.
1191     return 1;
1192 }
1193 
1194 VtValue
Get(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & key,UsdTimeCode time,VtIntArray * outIndices) const1195 UsdImagingPrimAdapter::Get(
1196     UsdPrim const& prim,
1197     SdfPath const& cachePath,
1198     TfToken const &key,
1199     UsdTimeCode time,
1200     VtIntArray *outIndices) const
1201 {
1202     UsdAttribute const &attr = prim.GetAttribute(key);
1203     VtValue value;
1204     if (attr) {
1205         attr.Get(&value, time);
1206     }
1207     return value;
1208 }
1209 
1210 bool
GetVisible(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1211 UsdImagingPrimAdapter::GetVisible(
1212     UsdPrim const& prim,
1213     SdfPath const& cachePath,
1214     UsdTimeCode time) const
1215 {
1216     TRACE_FUNCTION();
1217 
1218     if (_delegate->IsInInvisedPaths(prim.GetPath())) {
1219         return false;
1220     }
1221 
1222     UsdImaging_VisCache &visCache = _delegate->_visCache;
1223     if (_IsEnabledVisCache() && visCache.GetTime() == time) {
1224         return visCache.GetValue(prim) == UsdGeomTokens->inherited;
1225     } else {
1226         return UsdImaging_VisStrategy::ComputeVisibility(prim, time)
1227                     == UsdGeomTokens->inherited;
1228     }
1229 }
1230 
1231 TfToken
GetPurpose(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & instanceInheritablePurpose) const1232 UsdImagingPrimAdapter::GetPurpose(
1233     UsdPrim const& prim,
1234     SdfPath const& cachePath,
1235     TfToken const& instanceInheritablePurpose) const
1236 {
1237     HD_TRACE_FUNCTION();
1238 
1239     UsdImaging_PurposeStrategy::value_type purposeInfo =
1240         _IsEnabledPurposeCache() ?
1241             _delegate->_purposeCache.GetValue(prim) :
1242             UsdImaging_PurposeStrategy::ComputePurposeInfo(prim);
1243 
1244     // Inherit the instance's purpose if our prim has a fallback purpose and
1245     // there's an instance that provide a purpose to inherit.
1246     if (!purposeInfo.isInheritable &&
1247         !instanceInheritablePurpose.IsEmpty()) {
1248         return instanceInheritablePurpose;
1249     }
1250 
1251     return purposeInfo.purpose.IsEmpty() ?
1252         UsdGeomTokens->default_ : purposeInfo.purpose;
1253 }
1254 
1255 TfToken
GetInheritablePurpose(UsdPrim const & prim) const1256 UsdImagingPrimAdapter::GetInheritablePurpose(UsdPrim const& prim) const
1257 {
1258     HD_TRACE_FUNCTION();
1259 
1260     UsdImaging_PurposeStrategy::value_type purposeInfo =
1261         _IsEnabledPurposeCache() ?
1262             _delegate->_purposeCache.GetValue(prim) :
1263             UsdImaging_PurposeStrategy::ComputePurposeInfo(prim);
1264 
1265     return purposeInfo.GetInheritablePurpose();
1266 }
1267 
1268 HdCullStyle
GetCullStyle(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1269 UsdImagingPrimAdapter::GetCullStyle(UsdPrim const& prim,
1270                                     SdfPath const& cachePath,
1271                                     UsdTimeCode time) const
1272 {
1273     return HdCullStyleDontCare;
1274 }
1275 
1276 SdfPath
GetMaterialUsdPath(UsdPrim const & prim) const1277 UsdImagingPrimAdapter::GetMaterialUsdPath(UsdPrim const& prim) const
1278 {
1279     HD_TRACE_FUNCTION();
1280 
1281     // No need to worry about time here, since relationships do not have time
1282     // samples.
1283     if (_IsEnabledBindingCache()) {
1284         return _delegate->_materialBindingCache.GetValue(prim);
1285     } else {
1286         return UsdImaging_MaterialStrategy::ComputeMaterialPath(prim,
1287                 &_delegate->_materialBindingImplData);
1288     }
1289 }
1290 
1291 TfToken
GetModelDrawMode(UsdPrim const & prim)1292 UsdImagingPrimAdapter::GetModelDrawMode(UsdPrim const& prim)
1293 {
1294     return _delegate->_GetModelDrawMode(prim);
1295 }
1296 
1297 /*virtual*/
1298 VtValue
GetTopology(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1299 UsdImagingPrimAdapter::GetTopology(UsdPrim const& prim,
1300                                    SdfPath const& cachePath,
1301                                    UsdTimeCode time) const
1302 {
1303     return VtValue();
1304 }
1305 
1306 /*virtual*/
1307 GfRange3d
GetExtent(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1308 UsdImagingPrimAdapter::GetExtent(UsdPrim const& prim,
1309                                  SdfPath const& cachePath,
1310                                  UsdTimeCode time) const
1311 {
1312     return GfRange3d();
1313 }
1314 
1315 /*virtual*/
1316 bool
GetDoubleSided(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1317 UsdImagingPrimAdapter::GetDoubleSided(UsdPrim const& prim,
1318                                       SdfPath const& cachePath,
1319                                       UsdTimeCode time) const
1320 {
1321     return false;
1322 }
1323 
1324 /*virtual*/
1325 SdfPath
GetMaterialId(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1326 UsdImagingPrimAdapter::GetMaterialId(UsdPrim const& prim,
1327                                      SdfPath const& cachePath,
1328                                      UsdTimeCode time) const
1329 {
1330     return SdfPath();
1331 }
1332 
1333 /*virtual*/
1334 VtValue
GetMaterialResource(UsdPrim const & prim,SdfPath const & cachePath,UsdTimeCode time) const1335 UsdImagingPrimAdapter::GetMaterialResource(UsdPrim const& prim,
1336                               SdfPath const& cachePath,
1337                               UsdTimeCode time) const
1338 {
1339     return VtValue();
1340 }
1341 
1342 /*virtual*/
1343 const TfTokenVector &
GetExtComputationSceneInputNames(SdfPath const & cachePath) const1344 UsdImagingPrimAdapter::GetExtComputationSceneInputNames(
1345     SdfPath const& cachePath) const
1346 {
1347     static TfTokenVector emptyTokenVector;
1348     return emptyTokenVector;
1349 }
1350 
1351 /*virtual*/
1352 HdExtComputationInputDescriptorVector
GetExtComputationInputs(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1353 UsdImagingPrimAdapter::GetExtComputationInputs(
1354     UsdPrim const& prim,
1355     SdfPath const& cachePath,
1356     const UsdImagingInstancerContext* instancerContext) const
1357 {
1358     return HdExtComputationInputDescriptorVector();
1359 }
1360 
1361 /*virtual*/
1362 HdExtComputationOutputDescriptorVector
GetExtComputationOutputs(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1363 UsdImagingPrimAdapter::GetExtComputationOutputs(
1364     UsdPrim const& prim,
1365     SdfPath const& cachePath,
1366     const UsdImagingInstancerContext* instancerContext) const
1367 {
1368     return HdExtComputationOutputDescriptorVector();
1369 }
1370 
1371 /*virtual*/
1372 HdExtComputationPrimvarDescriptorVector
GetExtComputationPrimvars(UsdPrim const & prim,SdfPath const & cachePath,HdInterpolation interpolation,const UsdImagingInstancerContext * instancerContext) const1373 UsdImagingPrimAdapter::GetExtComputationPrimvars(
1374     UsdPrim const& prim,
1375     SdfPath const& cachePath,
1376     HdInterpolation interpolation,
1377     const UsdImagingInstancerContext* instancerContext) const
1378 {
1379     return HdExtComputationPrimvarDescriptorVector();
1380 }
1381 
1382 /*virtual*/
1383 VtValue
GetExtComputationInput(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & name,UsdTimeCode time,const UsdImagingInstancerContext * instancerContext) const1384 UsdImagingPrimAdapter::GetExtComputationInput(
1385     UsdPrim const& prim,
1386     SdfPath const& cachePath,
1387     TfToken const& name,
1388     UsdTimeCode time,
1389     const UsdImagingInstancerContext* instancerContext) const
1390 {
1391     return VtValue();
1392 }
1393 
1394 /*virtual*/
1395 size_t
SampleExtComputationInput(UsdPrim const & prim,SdfPath const & cachePath,TfToken const & name,UsdTimeCode time,const UsdImagingInstancerContext * instancerContext,size_t maxSampleCount,float * sampleTimes,VtValue * sampleValues)1396 UsdImagingPrimAdapter::SampleExtComputationInput(
1397     UsdPrim const& prim,
1398     SdfPath const& cachePath,
1399     TfToken const& name,
1400     UsdTimeCode time,
1401     const UsdImagingInstancerContext* instancerContext,
1402     size_t maxSampleCount,
1403     float *sampleTimes,
1404     VtValue *sampleValues)
1405 {
1406     if (maxSampleCount > 0) {
1407         sampleTimes[0] = 0.0;
1408         sampleValues[0] = GetExtComputationInput(prim, cachePath, name, time,
1409                                                  instancerContext);
1410         return 1;
1411     }
1412     return 0;
1413 }
1414 
1415 /*virtual*/
1416 std::string
GetExtComputationKernel(UsdPrim const & prim,SdfPath const & cachePath,const UsdImagingInstancerContext * instancerContext) const1417 UsdImagingPrimAdapter::GetExtComputationKernel(
1418     UsdPrim const& prim,
1419     SdfPath const& cachePath,
1420     const UsdImagingInstancerContext* instancerContext) const
1421 {
1422     return std::string();
1423 }
1424 
1425 /*virtual*/
1426 VtValue
GetInstanceIndices(UsdPrim const & instancerPrim,SdfPath const & instancerCachePath,SdfPath const & prototypeCachePath,UsdTimeCode time) const1427 UsdImagingPrimAdapter::GetInstanceIndices(UsdPrim const& instancerPrim,
1428                                           SdfPath const& instancerCachePath,
1429                                           SdfPath const& prototypeCachePath,
1430                                           UsdTimeCode time) const
1431 {
1432     return VtValue();
1433 }
1434 
1435 VtArray<VtIntArray>
GetPerPrototypeIndices(UsdPrim const & prim,UsdTimeCode time) const1436 UsdImagingPrimAdapter::GetPerPrototypeIndices(UsdPrim const& prim,
1437                                               UsdTimeCode time) const
1438 {
1439     TRACE_FUNCTION();
1440 
1441     UsdImaging_PointInstancerIndicesCache &indicesCache =
1442         _delegate->_pointInstancerIndicesCache;
1443 
1444     if (_IsEnabledPointInstancerIndicesCache() &&
1445         indicesCache.GetTime() == time) {
1446         return indicesCache.GetValue(prim);
1447     } else {
1448         return UsdImaging_PointInstancerIndicesStrategy::
1449             ComputePerPrototypeIndices(prim, time);
1450     }
1451 }
1452 
1453 /*virtual*/
1454 GfMatrix4d
GetRelativeInstancerTransform(SdfPath const & instancerPath,SdfPath const & protoInstancerPath,UsdTimeCode time) const1455 UsdImagingPrimAdapter::GetRelativeInstancerTransform(
1456     SdfPath const &instancerPath,
1457     SdfPath const &protoInstancerPath, UsdTimeCode time) const
1458 {
1459     return GfMatrix4d(1);
1460 }
1461 
1462 PXR_NAMESPACE_CLOSE_SCOPE
1463 
1464