HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stageCache.h
Go to the documentation of this file.
1 //
2 // Copyright 2017 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 _GUSD_STAGECACHE_H_
25 #define _GUSD_STAGECACHE_H_
26 
27 #include <UT/UT_Array.h>
28 #include <UT/UT_Error.h>
29 #include <UT/UT_Set.h>
30 
31 #include "gusd/defaultArray.h"
32 #include "gusd/stageEdit.h"
33 #include "gusd/stageOpts.h"
34 #include "gusd/USD_Utils.h"
35 
36 #include "pxr/pxr.h"
37 #include "pxr/usd/sdf/layer.h"
38 #include "pxr/usd/usd/stage.h"
39 
40 class OP_Node;
41 class DEP_MicroNode;
42 class UT_Options;
43 class UT_StringHolder;
44 class UT_StringSet;
45 class UT_StringRef;
46 
48 
50 typedef void (*GusdStageCacheReaderTracker)(bool addreader);
51 
52 class GusdUSD_DataCache;
53 class UsdPrim;
54 
55 /// Cache for USD stages.
56 /// Clients interact with the cache via the GusdStageCacheReader
57 /// and GusdStageCacheWriter classes.
59 {
60 public:
62 
63  ~GusdStageCache();
64 
65  GusdStageCache(const GusdStageCache&) = delete;
66 
67  GusdStageCache& operator=(const GusdStageCache&) = delete;
68 
69  /// Get the singleton GusdStageCache object.
70  static GusdStageCache& GetInstance();
71 
72  /// Set the callback function that should be used to interpret stage
73  /// file paths that specify a LOP node.
74  static void SetLopStageResolver(GusdLopStageResolver resolver);
75 
76  /// Set a callback used to track the construction and destruction of
77  /// stage cache readers/writers. This is used by the Lop Stage Resolver
78  /// to know when it is safe to clean up after itself.
79  static void SetStageCacheReaderTracker(GusdStageCacheReaderTracker tracker);
80 
81  /// Utility function to create a LOP stage identifier from a path to a
82  /// LOP node, and the other bits of data required to generated a locked
83  /// stage from a LOP node in the HUSD library.
84  static UT_StringHolder CreateLopStageIdentifier(OP_Node *lop,
85  bool strip_layers,
86  fpreal t,
87  const UT_Options &opts);
88  /// Utility function to split a stage file path specifying a LOP node
89  /// into a part that specifies the LOP node and any additional arguments
90  /// that may appear after the LOP node path. Returns true if the path is
91  /// a LOP node path (starts with "op:"), otherwise returns false.
92  static bool SplitLopStageIdentifier(const UT_StringRef &identifier,
93  OP_Node *&lop,
94  bool &strip_layers,
95  fpreal &t,
96  UT_Options &opts);
97 
98  /// Add/remove auxiliary data caches.
99  /// Auxiliary data caches are cleared in response to changes
100  /// to stages on this cache.
101  /// @{
102  void AddDataCache(GusdUSD_DataCache& cache);
103 
104  void RemoveDataCache(GusdUSD_DataCache& cache);
105  /// @}
106 
107  /// \section GusdStageCache_Reloading Reloading
108  ///
109  /// Stages and layers may be reloaded during an active session, but it's
110  /// important to understand the full implications of doing so.
111  /// When a layer is reloaded, change notifications are sent to any stages
112  /// referencing that layer, causing those stages to recompose, if necessary.
113  /// This operation is not thread-safe, and may result in a crash if another
114  /// thread is attempting to read from an affected stage at the same time.
115  /// Further, it must be noted that simply loading stages within separate
116  /// GusdStageCache instances also does not mean that that change
117  /// propopagation will be isolated only to stages of the stage cache
118  /// instance: Although it is possible to isolate the effect of changes
119  /// on the root layers of stages to some extent, secondary layers -- such
120  /// as sublayers and reference arcs -- are shared on a global cache.
121  /// The effect of reloading layers is _global_ and _immediate_.
122  ///
123  /// Rather than attempting to solve this problem with intrusive and
124  /// expensive locking -- which would only solve the problem for stages
125  /// held internally in a GusdStageCache, not for stages referenced from
126  /// other caches -- we prefer to address the problem by requiring that
127  /// reloading only be performed at certain points of Houdini's main event
128  /// loop, where it is known to be safe.
129  /// An example of a 'safe' way to exec stage reloads is via a callback
130  /// triggered by a button in a node's GUI.
131  /// Users should never attempt to reload stages or layers during node
132  /// cook methods.
133 
134  /// Mark a set of stages for reload on the event queue.
135  static void ReloadStages(const UT_Set<UsdStagePtr>& stages);
136 
137  /// Mark a set of layers for reload on the event queue.
138  static void ReloadLayers(const UT_Set<SdfLayerHandle>& layers);
139 
140 
141 private:
142  class _MaskedStageCache;
143 
144  class _Impl;
145  _Impl* const _impl;
146 
147  friend class GusdStageCacheReader;
148  friend class GusdStageCacheWriter;
149 };
150 
151 
152 /// Helper for reading from a GusdStageCache.
153 /// Cache readers can both open existing stages on the cache,
154 /// as well as cause additional stages to be inserted into the cache.
155 /// Cache readers cannot clear out any existing stages or mutate
156 /// auxiliary data caches.
157 ///
158 /// Example usage:
159 /// @code
160 /// GusdStageCacheReader cache;
161 ///
162 /// // Pull a stage from the cache.
163 /// UsdStageRefPtr stage = cache.FindOrOpen(stagePath);
164 ///
165 /// // Access a prim on the cache.
166 /// UsdPrim prim = cache.GetPrim(stagePath, primPath).first;
167 ///
168 /// // Access a prim with a variant selection.
169 /// SdfPath primPath("/foo{variant=sel}bar");
170 /// UsdPrim prim = cache.GetPrim(stagePath, primPath);
171 /// @endcode
173 {
174 public:
175  using PrimStagePair = std::pair<UsdPrim,UsdStageRefPtr>;
176 
177  /// Construct a reader for the cache singleton.
179  : GusdStageCacheReader(cache, false) {}
180 
182 
183  GusdStageCacheReader& operator=(const GusdStageCacheReader&) = delete;
184 
186 
187  /// Find an existing stage on the cache.
188  UsdStageRefPtr
189  Find(const UT_StringRef& path,
191  const GusdStageEditPtr& edit=nullptr) const;
192 
193  /// Return a stage from the cache, if one exists.
194  /// If not, attempt to open the stage and add it to the cache.
195  /// If \p path is a non-empty path and stage opening fails, errors
196  /// are reporting to the currently scoped error manager at a severity
197  /// of \p sev.
198  UsdStageRefPtr
199  FindOrOpen(const UT_StringRef& path,
201  const GusdStageEditPtr& edit=nullptr,
203 
204  /// Insert a stage into our cache. The lifetime of this stage is not
205  /// fully controlled by this cache. The cache is just a holder for the
206  /// stage for as long as the gusd library is allowed access to it until
207  /// it is destroyed by the external owner, which must then call Clear()
208  /// with the same path.
209  void
210  InsertStage(UsdStageRefPtr &stage,
211  const UT_StringRef& path,
212  const GusdStageOpts& opts,
213  const GusdStageEditPtr& edit);
214 
215  /// Get a micro node for a stage.
216  /// Micro nodes are created on demand, and are dirtied both for
217  /// stage reloading and cache evictions.
219  GetStageMicroNode(const UsdStagePtr& stage);
220 
221  /// \section Prim Accessors
222  ///
223  /// These helpers return prims on masked stages, where only the
224  /// parts of the stage required to produce a given prim are composed.
225  /// This helps support workflows such as setting variants on packed prims,
226  /// where either many stage mutations may be made that conflict with each
227  /// other, or in isolation, such that different mutations can't be made
228  /// to share stages without intrusive locking.
229  /// In all cases, if a full stage which satisfies the stage options and
230  /// edits has already been loaded on the cache, the prim will fetched from
231  /// that stage instead.
232  ///
233  /// This use of masking may be disabled by way of the GUSD_STAGEMASK_ENABLE
234  /// environment variable, but beware that doing so may significantly degrade
235  /// performance for certain access patterns, such as if many separate prims
236  /// are being queried from the cache with different stage edits.
237  ///
238  /// \subsection Primitive Encapsulation
239  ///
240  /// Because primitives are masked to include a subset of a stage,
241  /// there is an expectation that the caller follows _encapsulation_ rules.
242  /// When we read in a prim, we consider that prim to be encapsulated,
243  /// which means that if any other primitives from the stage are required
244  /// to process an encapsulated primitive, they are expected to either
245  /// be descendants or ancestors of the encapsulated prim, or the dependency
246  /// to that external prim must be discoverable using either relationships
247  /// or attribute connections.
248  /// Following those encapsulation rules, neither _siblings_ of the prim
249  /// being requested, nor other prims in separate branches of the stage
250  /// are guaranteed to be loaded. Any attempt to reach other prims that
251  /// can't be discovered using the above rules for discovering dependencies
252  /// may either fail or introduce non-deterministic behavior.
253 
254  /// Get a prim from the cache, on a masked stage.
255  /// If \p path and \p primPath are both valid, and either a stage load
256  /// error occurs or no prim can be found, errors are reported on the
257  /// currently scoped error manager at a severity of \p sev.
258  /// If \p primPath is equal to 'defaultPrim', the stage's defaultPrim
259  /// is returned.
260  /// If \p primPath is equal to '/', the entire stage is loaded,
261  /// and the pseudo-root is returned.
262  PrimStagePair
263  GetPrim(const UT_StringRef& path,
264  const SdfPath& primPath,
265  const GusdStageEditPtr& stageEdit=GusdStageEditPtr(),
268 
269  /// Get multiple prims from the cache (in parallel).
270  /// If the configured error severity is less than UT_ERROR_ABORT,
271  /// prim loading will continue even after load errors have occurred.
272  /// If any stage load errors occur, or if any prims cannot be found, errors
273  /// are reported on the currently scoped error manager with a severity of
274  /// \p sev. If \p sev is less than UT_ERROR_ABORT, prim loading will
275  /// continue even when errors occur for some prims. Otherwise, loading
276  /// aborts upon the first error.
277  /// If a path in \p primPaths is equal to `defaultPrim`, the stage's
278  /// defaultPrim will be returned for that element.
279  /// If a path in \p primPaths is equal to `/` -- I.e., the absolute root --
280  /// then the full stage of the corresponding element is loaded, and the
281  /// pseudo-root is returned.
282  bool
283  GetPrims(const GusdDefaultArray<UT_StringHolder>& filePaths,
284  const UT_Array<SdfPath>& primPaths,
286  UsdPrim* prims,
289 
290  /// Get a prim from the cache, given a prim path that may contain
291  /// variant selections. This is a convenience method for the common case
292  /// of accessing a prim given parameters for just a file path and
293  /// prim path.
294  /// If \p primPath is equal to 'defaultPrim', the stage's defaultPrim
295  /// is returned.
296  /// If \p primPath is equal to `/`, the entire stage is loaded,
297  /// and the pseudo-root is returned.
298  /// @{
299  PrimStagePair
300  GetPrimWithVariants(const UT_StringRef& path,
301  const SdfPath& primPath,
304 
305  PrimStagePair
306  GetPrimWithVariants(const UT_StringRef& path,
307  const UT_StringRef& primPath,
310 
311  /// Different variations of the above the variants are stored separately.
312  PrimStagePair
313  GetPrimWithVariants(const UT_StringRef& path,
314  const SdfPath& primPath,
315  const SdfPath& variants,
318 
319  PrimStagePair
320  GetPrimWithVariants(const UT_StringRef& path,
321  const UT_StringRef& primPath,
322  const UT_StringRef& variants,
325  /// @}
326 
327 protected:
328  GusdStageCacheReader(GusdStageCache& cache, bool writer);
329 
330 protected:
332  const bool _writer;
333 };
334 
335 
336 /// Write accessor for a stage cache.
337 /// Write accessors have all of the capabilities of readers,
338 /// and can also remove elements from the cache and manipulate
339 /// child data caches.
340 /// Writers gain exclusive locks to the cache, and should be used sparingly.
342 {
343 public:
345 
347 
349 
350  /// Find all stages on the cache matching the given paths.
351  /// Multiple stages may be found for each path.
352  void FindStages(const UT_StringSet& paths,
354 
355  /// \section GusdStageCacheWriter_ReloadAndClear Reloading And Clearing
356  ///
357  /// During active sessions, the contents of a cache may be refreshed
358  /// by either reloading a subset of the stages that it contains, or by
359  /// removing stage entries from the cache.
360  /// In either case, if a stage is reloaded or evicted from the cache,
361  /// and if that stage has a micro node
362  /// (see: \ref GusdStageCacheReader::GetMicroNode), then that micro
363  /// node, and any OP_Node instances that reference it, are dirtied.
364  /// This means that any nodes whose cook is based on data from a cached
365  /// stage will properly update in response to Clear()/Reload() actions.
366  ///
367  /// \warn Dirty state propagation is not thread safe, and should only be
368  /// called at a safe point on the main thread, such as through a callback
369  /// triggered by a UI button. Also note that there may be side effects
370  /// from reloading stages that affect stages from *other caches*. See
371  /// \ref GusdStageCache_Reloading for more information on the caveats of
372  /// reloading.
373 
374  /// Clear out all cached items.
375  /// Note that layers are owned by a different cache, and may stay
376  /// active beyond this point.
377  void Clear();
378 
379  /// Variant of Clear() that does not remove cached stages from LOPs.
380  /// Returns the number of entries that were removed.
381  exint ClearEntriesFromDisk();
382 
383  /// Variant of Clear() that causes any stages whose root layer has
384  /// an asset path in the \p paths set to be removed from the cache.
385  void Clear(const UT_StringSet& paths);
386 
387  /// Reload all stages matching the given paths.
388  void ReloadStages(const UT_StringSet& paths);
389 };
390 
391 
393 
394 
395 #endif /*_GUSD_STAGECACHE_H_*/
PXR_NAMESPACE_OPEN_SCOPE typedef UT_StringHolder(* GusdLopStageResolver)(const UT_StringRef &path)
Definition: stageCache.h:49
Definition: UT_Set.h:58
GLbitfield stages
Definition: glcorearb.h:1931
void
Definition: png.h:1083
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
int64 exint
Definition: SYS_Types.h:125
UT_ErrorSeverity
Definition: UT_Error.h:25
void(* GusdStageCacheReaderTracker)(bool addreader)
Definition: stageCache.h:50
static GusdStageCache & GetInstance()
Get the singleton GusdStageCache object.
const bool _writer
Definition: stageCache.h:332
GusdStageCacheReader & operator=(const GusdStageCacheReader &)=delete
static GusdStageOpts LoadAll()
Return options that a configure a stage to be loaded with payloads.
Definition: stageOpts.h:52
UT_IntrusivePtr< class GusdStageEdit > GusdStageEditPtr
Definition: stageEdit.h:42
Wrapper around hboost::intrusive_ptr.
Definition: prim.h:135
Definition: path.h:291
GLdouble t
Definition: glad.h:2397
std::pair< UsdPrim, UsdStageRefPtr > PrimStagePair
Definition: stageCache.h:175
GusdStageCacheReader(GusdStageCache &cache=GusdStageCache::GetInstance())
Construct a reader for the cache singleton.
Definition: stageCache.h:178
A map of string to various well defined value types.
Definition: UT_Options.h:84
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1441
GusdStageCache & _cache
Definition: stageCache.h:331
fpreal64 fpreal
Definition: SYS_Types.h:277
friend class UT_StringHolder
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
#define GUSD_API
Definition: api.h:40