Loading...
Searching...
No Matches
dependencyForwardingSceneIndex.h
1//
2// Copyright 2022 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 PXR_IMAGING_HD_DEPENDENCY_FORWARDING_SCENE_INDEX_H
25#define PXR_IMAGING_HD_DEPENDENCY_FORWARDING_SCENE_INDEX_H
26
28
29#include "pxr/imaging/hd/api.h"
30#include "pxr/imaging/hd/filteringSceneIndex.h"
31
32#include <tbb/concurrent_unordered_map.h>
33#include <tbb/concurrent_unordered_set.h>
34
35PXR_NAMESPACE_OPEN_SCOPE
36
37class HdDependencyForwardingSceneIndex;
38TF_DECLARE_REF_PTRS(HdDependencyForwardingSceneIndex);
39
40
41class HdDependencyForwardingSceneIndex
43{
44public:
45
46 static HdDependencyForwardingSceneIndexRefPtr New(
47 HdSceneIndexBaseRefPtr inputScene) {
48 return TfCreateRefPtr(
49 new HdDependencyForwardingSceneIndex(inputScene));
50 }
51
52 // satisfying HdSceneIndexBase
53 HdSceneIndexPrim GetPrim(const SdfPath &primPath) const override;
54 SdfPathVector GetChildPrimPaths(const SdfPath &primPath) const override;
55
56
57protected:
58 HD_API
59 HdDependencyForwardingSceneIndex(HdSceneIndexBaseRefPtr inputScene);
60
61 // satisfying HdSingleInputFilteringSceneIndexBase
62 void _PrimsAdded(
63 const HdSceneIndexBase &sender,
64 const HdSceneIndexObserver::AddedPrimEntries &entries) override;
65
66 void _PrimsRemoved(
67 const HdSceneIndexBase &sender,
68 const HdSceneIndexObserver::RemovedPrimEntries &entries) override;
69
70 void _PrimsDirtied(
71 const HdSceneIndexBase &sender,
72 const HdSceneIndexObserver::DirtiedPrimEntries &entries) override;
73private:
74
75 // -----------------------------------------------------------------------
76
77 struct _LocatorsEntry
78 {
79 HdDataSourceLocator dependedOnDataSourceLocator;
80 HdDataSourceLocator affectedDataSourceLocator;
81 };
82
83 // The token used as a key here corresponds to the first member of an
84 // HdDependenciesSchema::EntryPair and provides an identifier for a
85 // dependency declaration. An affected prim may depend on more than one
86 // data source of another prim. That identifier is used here for updating
87 // or removing a dependency.
88 using _LocatorsEntryMap = tbb::concurrent_unordered_map<
89 TfToken,
90 _LocatorsEntry,
92
93
94 struct _AffectedPrimDependencyEntry
95 {
96 _LocatorsEntryMap locatorsEntryMap;
97 bool flaggedForDeletion = false;
98 };
99
100 // Reverse mapping from a depended on prim to its discovered-thus-far
101 // affected prims and data source locators..
102 using _AffectedPrimsDependencyMap = tbb::concurrent_unordered_map<
103 SdfPath,
104 _AffectedPrimDependencyEntry,
105 SdfPath::Hash>;
106
107
108 // Top-level map keyed by paths of depended-on paths
109 using _DependedOnPrimsAffectedPrimsMap = tbb::concurrent_unordered_map<
110 SdfPath,
111 _AffectedPrimsDependencyMap,
112 SdfPath::Hash>;
113
114
115 // Lazily-populated mapping of depended on paths to the affected paths
116 // and data source locators used for forwarding of dirtying.
117 // NOTE: This is mutable because it can be updated during calls to
118 // GetPrim -- which is defined as const within HdSceneIndexBase.
119 // This is in service of lazy population goals.
120 mutable _DependedOnPrimsAffectedPrimsMap _dependedOnPrimToDependentsMap;
121
122
123 // -----------------------------------------------------------------------
124
125 using _PathSet = tbb::concurrent_unordered_set<SdfPath, SdfPath::Hash>;
126
127 //using _DensePathSet = TfDenseHashSet<SdfPath, SdfPath::Hash>;
128
129 struct _AffectedPrimToDependsOnPathsEntry
130 {
131 _PathSet dependsOnPaths;
132 bool flaggedForDeletion = false;
133 };
134
135
136 using _AffectedPrimToDependsOnPathsEntryMap = tbb::concurrent_unordered_map<
137 SdfPath,
138 _AffectedPrimToDependsOnPathsEntry,
139 SdfPath::Hash>;
140
141 // lazily-populated set of depended on paths for affected prims. This
142 // is used to update _dependedOnPrimToDependentsMap when a prim's
143 // __dependencies data source is dirtied (or the prim is removed)
144 // NOTE: This is mutable because it can be updated during calls to
145 // GetPrim -- which is defined as const within HdSceneIndexBase.
146 // This is in service of lazy population goals.
147 mutable _AffectedPrimToDependsOnPathsEntryMap
148 _affectedPrimToDependsOnPathsMap;
149
150 // -----------------------------------------------------------------------
151
152 void _ClearDependencies(const SdfPath &primPath);
153 void _UpdateDependencies(const SdfPath &primPath) const;
154
155 // -----------------------------------------------------------------------
156
157 // Dependencies may reasonably describe cycles given that:
158 // 1) Dependancies can exist at different levels of data source nesting
159 // 2) Dependancy declarations can be present from multiple upstream
160 // scene indices -- each of which draws its value from its input.
161 // In that case, it's not a cycle which affects a computed value but
162 // rather indicates to observers of this scene index that a value
163 // should be repulled.
164 //
165 // When following affected paths to propogate dirtiness, we need to detect
166 // cycles to avoiding hanging. This is done is by sending a "visited" set
167 // containing these node keys:
168 struct _VisitedNode
169 {
170 SdfPath primPath;
171 HdDataSourceLocator locator;
172
173 inline bool operator==(_VisitedNode const &rhs) const noexcept
174 {
175 return primPath == rhs.primPath && locator == rhs.locator;
176 }
177
178 template <class HashState>
179 friend void TfHashAppend(HashState &h, _VisitedNode const &myObj) {
180 h.Append(myObj.primPath);
181 h.Append(myObj.locator);
182 }
183
184 inline size_t Hash() const;
185 struct HashFunctor {
186 size_t operator()(_VisitedNode const &node) const {
187 return node.Hash();
188 }
189 };
190 };
191
192 using _VisitedNodeSet = TfDenseHashSet<
193 _VisitedNode,
194 _VisitedNode::HashFunctor>;
195
196 // impl for PrimDirtied which handles propogation of PrimDirtied notices
197 // for affected prims/dataSources.
198 void _PrimDirtied(
199 const SdfPath &primPath,
200 const HdDataSourceLocator &sourceLocator,
201 _VisitedNodeSet *visited,
202 HdSceneIndexObserver::DirtiedPrimEntries *moreDirtiedEntries);
203
204 // -----------------------------------------------------------------------
205
206 // accumulated depended-on prim paths whose affected prims may have been
207 // removed.
208 mutable _PathSet _potentiallyDeletedDependedOnPaths;
209
210 // Accumulated affected prim paths who may have been deleted. Normally this
211 // is needed to track affected prims which have an entry in
212 // _dependedOnPrimToDependentsMap but which is empty -- and therefore
213 // won't be handled by their dependencies inclusion in
214 // _potentiallyDeletedDependedOnPaths
215 mutable _PathSet _potentiallyDeletedAffectedPaths;
216
217 // -----------------------------------------------------------------------
218
219public:
220 // XXX does thread-unsafe deletion.
221 // NOTE FOR REVIEWERS: temporarily hiding this explosive public method
222 // down here while we discuss it. It's public because
223 // only the application knows when it's safe to call?
224 //
225 // NOTE: optional arguments are in service of unit testing to provide
226 // insight in to what was removed.
227 HD_API
228 void RemoveDeletedEntries(
229 SdfPathVector *removedAffectedPrimPaths = nullptr,
230 SdfPathVector *removedDependedOnPrimPaths = nullptr);
231
232};
233
234
235inline size_t
236HdDependencyForwardingSceneIndex::_VisitedNode::Hash() const
237{
238 return TfHash()(*this);
239}
240
241PXR_NAMESPACE_CLOSE_SCOPE
242
243#endif
Represents an object that can identify the location of a data source.
Abstract interface to scene data.
Definition: sceneIndex.h:65
virtual SdfPathVector GetChildPrimPaths(const SdfPath &primPath) const =0
Returns the paths of all scene index prims located immediately below primPath.
virtual HdSceneIndexPrim GetPrim(const SdfPath &primPath) const =0
Returns a pair of (prim type, datasource) for the object at primPath.
An abstract base class for a filtering scene index that observes a single input scene index.
A path value used to locate objects in layers or scenegraphs.
Definition: path.h:290
This is a space efficient container that mimics the TfHashSet API that uses a vector for storage when...
Definition: denseHashSet.h:56
A user-extensible hashing mechanism for use with runtime hash tables.
Definition: hash.h:477
Token for efficient comparison, assignment, and hashing of known strings.
Definition: token.h:88
#define TF_DECLARE_REF_PTRS(type)
Define standard ref pointer types.
Definition: declarePtrs.h:75
Small struct representing a 'prim' in the Hydra scene index.
Definition: sceneIndex.h:52
Functor to use for hash maps from tokens to other things.
Definition: token.h:166