HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stageData.h
Go to the documentation of this file.
1 //
2 // Copyright 2026 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_ESF_USD_STAGE_DATA_H
8 #define PXR_EXEC_ESF_USD_STAGE_DATA_H
9 
10 /// \file
11 
12 #include "pxr/pxr.h"
13 
14 #include "pxr/exec/esfUsd/api.h"
15 
17 #include "pxr/base/tf/hash.h"
18 #include "pxr/usd/sdf/path.h"
19 #include "pxr/usd/usd/notice.h"
20 
21 #ifdef TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS
22 #include <tbb/concurrent_map.h>
23 #else
24 #define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1
25 #include <tbb/concurrent_map.h>
26 #undef TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS
27 #endif
28 
29 #include <tbb/concurrent_unordered_map.h>
30 #include <tbb/concurrent_unordered_set.h>
31 #include <tbb/concurrent_vector.h>
32 
33 #include <memory>
34 #include <mutex>
35 #include <vector>
36 
38 
39 class UsdAttribute;
40 class UsdPrim;
41 
43 
44 /// Class that holds data that is cached per-stage.
45 ///
46 /// \note
47 /// It's unfortunate that clients that access outgoing and incoming connections
48 /// using this class have to provide a stage pointer, making the implementation
49 /// of this class less performant and more complicated. Ideally, EsfUsd objects
50 /// would have a way to get directly to the stage data for their stage, but
51 /// given the fact that those objects are all short-lived, it's not clear how to
52 /// do that, at least without growing the sizes of all Esf objects.
53 ///
55 {
56  EsfUsdStageData(const UsdStageConstPtr &stage);
57 
58 public:
59 
60  /// A concurrent set of paths, used to indicate the set of targets for which
61  /// incoming connections have changed.
62  ///
63  using ChangedPathSet = tbb::concurrent_unordered_set<SdfPath, TfHash>;
64 
65  /// The base class for listeners defined by clients in order to be notified
66  /// of scene changes.
67  ///
69  public:
71  virtual ~ListenerBase();
72 
73  private:
74  friend EsfUsdStageData;
75 
76  /// Called to communicate scene changes to a client liseter.
77  ///
78  virtual void _DidObjectsChanged(
79  const UsdNotice::ObjectsChanged &objectsChanged,
80  const ChangedPathSet &changedTargetPaths) const = 0;
81  };
82 
83 
86 
87  /// Registers \p stage as a stage for which cached data should be held,
88  /// returning a strong reference the client must hold until the cached data
89  /// is no longer needed.
90  ///
91  /// \p listener will be notified of scene changes.
92  ///
94  static std::shared_ptr<EsfUsdStageData> RegisterStage(
95  const UsdStageConstPtr &stage,
96  const ListenerBase *listener);
97 
98  /// Notifies that \p listener no longer needs to be informed of changes.
99  ///
100  ESFUSD_API
101  void Unregister(
102  const ListenerBase *listener);
103 
104  /// Get the cached stage data for \p stage.
105  ///
106  /// \note
107  /// The client calling this method must first have registered \p stage by
108  /// calling RegisterStage and must still be holding the strong reference to
109  /// the stage data while calling this method and using the returned
110  /// reference.
111  ///
112  ESFUSD_API
114  const UsdStageConstPtr &stage);
115 
116  /// Returns the paths of all objects that are targets of connections owned
117  /// by the attribute at \p attrPath.
118  ///
119  ESFUSD_API
121  const UsdStageConstPtr &stage,
122  const SdfPath &attrPath);
123 
124  /// Returns the paths of all attributes that own connections that target
125  /// the object at \p targetPath.
126  ///
127  ESFUSD_API
129  const UsdStageConstPtr &stage,
130  const SdfPath &targetPath);
131 
132 private:
133  const UsdStageConstPtr &_GetStage() const { return _stage; }
134 
135  const SdfPathVector &_GetOutgoingConnections(
136  const SdfPath &targetPath);
137 
138  SdfPathVector _GetIncomingConnections(
139  const SdfPath &targetPath);
140 
141  void _PopulateConnectionTables();
142 
143  // Define a type and a corresponding transparent comparator so that we can
144  // use lower_bound to find the end of a map range with keys that are paths
145  // with a given prefix.
146 
147  struct _PathPrefix
148  {
149  SdfPath prefix;
150  };
151 
152  struct _PathRangeLessThan
153  {
154  using is_transparent = void;
155 
156  bool operator()(const SdfPath &lhs, const SdfPath &rhs) const {
157  return lhs < rhs;
158  }
159 
160  bool operator()(const SdfPath &lhs, const _PathPrefix& rhs) const {
161  return lhs < rhs.prefix || lhs.HasPrefix(rhs.prefix);
162  }
163  };
164 
165  // A concurrent map from owning attribute paths to target object paths.
166  using _OutgoingPathTable =
167  tbb::concurrent_map<SdfPath, SdfPathVector, _PathRangeLessThan>;
168 
169  // A concurent map from target object paths to owning attribute paths.
170  using _IncomingPathTable =
171  tbb::concurrent_unordered_map<
172  SdfPath, tbb::concurrent_vector<SdfPath>, TfHash>;
173 
174  // Gets the new (i.e., current) connections for the given attribute and
175  // computes the added and removed target paths, relative to what was
176  // previously stored in the outgoing connection paths table.
177  //
178  void _GetChangedConnectionTargets(
179  const SdfPath &attrPath,
180  const UsdAttribute &attribute,
181  SdfPathVector *newConnections,
182  SdfPathVector *addedTargetPaths,
183  SdfPathVector *removedTargetPaths) const;
184 
185  // Updates attribute connection caches for connections owned by the
186  // attribute at \p attrPath.
187  //
188  // Populates \p incomingConnectionsChanged with the paths of objects whose
189  // incoming connection paths have changed.
190  //
191  void _UpdateForChangedAttributeConnections(
192  const SdfPath &attrPath,
193  ChangedPathSet *incomingConnectionsChanged);
194 
195  // Updates attribute connection caches for connections owned by attribute
196  // at or under \p resyncedPath.
197  //
198  void _UpdateForResync(
199  const SdfPath &resyncedPath,
200  ChangedPathSet *incomingConnectionsChanged);
201 
202  // Updates outgoing and incoming connection tables for any changes to the
203  // given prim.
204  //
205  // New incoming connections are added immediately; new outgoing connections
206  // and removed incoming connections are queued up for deferred processing,
207  // to allow this method to be called in parallel.
208  //
209  void _UpdateForChangedPrim(
210  const UsdPrim &prim,
211  _IncomingPathTable *incomingToRemove,
212  ChangedPathSet *incomingConnectionsChanged);
213 
214  // Find entries in the outgoing connections map for attributes on the
215  // resynced prim and its descendants that no longer exist in the scene,
216  // populating \p ownerAttrsToRemove and \p incomingToRemove.
217  //
218  void _UpdateForRemovedAttributes(
219  const SdfPath &resyncedPath,
220  _IncomingPathTable *incomingToRemove,
221  tbb::concurrent_vector<SdfPath> *ownerAttrsToRemove) const;
222 
223  // Removes the entries indicated by \p incomingToRemove from _incoming.
224  void _RemoveIncomingTableEntries(
225  const _IncomingPathTable &incomingToRemove);
226 
227  // Notifies all listeners of changes.
228  void _Notify(
229  const UsdNotice::ObjectsChanged &objectsChanged,
230  const ChangedPathSet &changedTargetPaths) const;
231 
232 private:
233  const UsdStageConstPtr _stage;
234 
235  // Used to listen for change notification from the stage.
236  class _NoticeListener;
237  const std::unique_ptr<_NoticeListener> _noticeListener;
238 
239  // Registered listeners, used to communicate change notfication to clients.
240  std::vector<const ListenerBase *> _listeners;
241  mutable std::mutex _listenersMutex;
242 
243  _OutgoingPathTable _outgoing;
244 
245  _IncomingPathTable _incoming;
246 };
247 
249 
250 #endif
static ESFUSD_API std::shared_ptr< EsfUsdStageData > RegisterStage(const UsdStageConstPtr &stage, const ListenerBase *listener)
static ESFUSD_API const SdfPathVector & GetOutgoingConnections(const UsdStageConstPtr &stage, const SdfPath &attrPath)
TF_DECLARE_WEAK_PTRS(UsdStage)
void
Definition: png.h:1083
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
#define ESFUSD_API_TYPE
Definition: api.h:26
ESFUSD_API void Unregister(const ListenerBase *listener)
Definition: hash.h:472
std::vector< class SdfPath > SdfPathVector
static ESFUSD_API EsfUsdStageData & GetStageData(const UsdStageConstPtr &stage)
ESFUSD_API ~EsfUsdStageData()
static ESFUSD_API SdfPathVector GetIncomingConnections(const UsdStageConstPtr &stage, const SdfPath &targetPath)
Definition: prim.h:116
#define ESFUSD_API
Definition: api.h:25
Definition: path.h:280
tbb::concurrent_unordered_set< SdfPath, TfHash > ChangedPathSet
Definition: stageData.h:63
SDF_API bool HasPrefix(const SdfPath &prefix) const
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)