RavEngine
Loading...
Searching...
No Matches
GuAABBPruner.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef GU_AABB_PRUNER_H
30#define GU_AABB_PRUNER_H
31
32#include "common/PxPhysXCommonConfig.h"
33#include "GuExtendedBucketPruner.h"
34#include "GuSqInternal.h"
35#include "GuPruningPool.h"
36#include "GuAABBTree.h"
37#include "GuAABBTreeUpdateMap.h"
38#include "GuAABBTreeBuildStats.h"
39
40namespace physx
41{
42namespace Gu
43{
44 // PT: we build the new tree over a number of frames/states, in order to limit perf spikes in 'updatePruningTrees'.
45 // The states are as follows:
46 //
47 // BUILD_NOT_STARTED (1 frame, AABBPruner):
48 //
49 // This is the initial state, before the new (AABBTree) build even starts. In this frame/state, we perform the AABBPruner-related
50 // memory allocations:
51 // - the new AABB tree is allocated
52 // - the array of cached bounding boxes is allocated and filled
53 //
54 // BUILD_INIT (1 frame, AABBTree):
55 //
56 // This is the first frame in which the new tree gets built. It deserves its own special state since various things happen in the
57 // first frame, that do no happen in subsequent frames. Basically most initial AABBTree-related allocations happen here (but no
58 // build step per se).
59 //
60 // BUILD_IN_PROGRESS (N frames, AABBTree):
61 //
62 // This is the core build function, actually building the tree. This should be mostly allocation-free, except here and there when
63 // building non-complete trees, and during the last call when the tree is finally built.
64 //
65 // BUILD_NEW_MAPPING (1 frame, AABBPruner):
66 //
67 // After the new AABBTree is built, we recreate an AABBTreeUpdateMap for the new tree, and use it to invalidate nodes whose objects
68 // have been removed during the build.
69 //
70 // We need to do that before doing a full refit in the next stage/frame. If we don't do that, the refit code will fetch a wrong box,
71 // that may very well belong to an entirely new object.
72 //
73 // Note that this mapping/update map (mNewTreeMap) is temporary, and only needed for the next stage.
74 //
75 // BUILD_FULL_REFIT (1 frame, AABBPruner):
76 //
77 // Once the new update map is available, we fully refit the new tree. AABBs of moved objects get updated. AABBs of removed objects
78 // become empty.
79 //
80 // BUILD_LAST_FRAME (1 frame, AABBPruner):
81 //
82 // This is an artificial frame used to delay the tree switching code. The switch happens as soon as we reach the BUILD_FINISHED
83 // state, but we don't want to execute BUILD_FULL_REFIT and the switch in the same frame. This extra BUILD_LAST_FRAME stage buys
84 // us one frame, i.e. we have one frame in which we do BUILD_FULL_REFIT, and in the next frame we'll do both BUILD_LAST_FRAME /
85 // BUILD_FINISHED / the switch.
86 //
87 // BUILD_FINISHED (1 frame, AABBPruner):
88 //
89 // Several things happen in this 'finalization' frame/stage:
90 // - We switch the trees (old one is deleted, cached boxes are deleted, new tree pointer is setup)
91 // - A new (final) update map is created (mTreeMap). The map is used to invalidate objects that may have been removed during
92 // the BUILD_NEW_MAPPING and BUILD_FULL_REFIT frames. The nodes containing these removed objects are marked for refit.
93 // - Nodes containing objects that have moved during the BUILD_NEW_MAPPING and BUILD_FULL_REFIT frames are marked for refit.
94 // - We do a partial refit on the new tree, to take these final changes into account. This small partial refit is usually much
95 // cheaper than the full refit we previously performed here.
96 // - We remove old objects from the bucket pruner
97 //
98 enum BuildStatus
99 {
100 BUILD_NOT_STARTED,
101 BUILD_INIT,
102 BUILD_IN_PROGRESS,
103 BUILD_NEW_MAPPING,
104 BUILD_FULL_REFIT,
105 BUILD_LAST_FRAME,
106 BUILD_FINISHED,
107
108 BUILD_FORCE_DWORD = 0xffffffff
109 };
110
111 // This class implements the Pruner interface for internal SQ use with some additional specialized functions
112 // The underlying data structure is a binary AABB tree
113 // AABBPruner supports insertions, removals and updates for dynamic objects
114 // The tree is either entirely rebuilt in a single frame (static pruner) or progressively rebuilt over multiple frames (dynamic pruner)
115 // The rebuild happens on a copy of the tree
116 // the copy is then swapped with current tree at the time commit() is called (only if mBuildState is BUILD_FINISHED),
117 // otherwise commit() will perform a refit operation applying any pending changes to the current tree
118 // While the tree is being rebuilt a temporary data structure (BucketPruner) is also kept in sync and used to speed up
119 // queries on updated objects that are not yet in either old or new tree.
120 // The requirements on the order of calls:
121 // commit() is required to be called before any queries to apply modifications
122 // queries can be issued on multiple threads after commit is called
123 // commit, buildStep, add/remove/update have to be called from the same thread or otherwise strictly serialized by external code
124 // and cannot be issued while a query is running
126 {
127 PX_NOCOPY(AABBPruner)
128 public:
129 PX_PHYSX_COMMON_API AABBPruner(bool incrementalRebuild, PxU64 contextID, CompanionPrunerType cpType, BVHBuildStrategy buildStrategy=BVH_SPLATTER_POINTS, PxU32 nbObjectsPerNode=4); // true is equivalent to former dynamic pruner
130 virtual ~AABBPruner();
131
132 // BasePruner
133 DECLARE_BASE_PRUNER_API
134 //~BasePruner
135
136 // Pruner
137 DECLARE_PRUNER_API_COMMON
138 virtual bool isDynamic() const { return mIncrementalRebuild; }
139 //~Pruner
140
141 // DynamicPruner
142 virtual void setRebuildRateHint(PxU32 nbStepsForRebuild); // Besides the actual rebuild steps, 3 additional steps are needed.
143 virtual bool buildStep(bool synchronousCall = true); // returns true if finished
144 virtual bool prepareBuild(); // returns true if new tree is needed
145 //~DynamicPruner
146
147 // direct access for test code
148
149 PX_FORCE_INLINE PxU32 getNbAddedObjects() const { return mBucketPruner.getNbObjects(); }
150 PX_FORCE_INLINE const AABBTree* getAABBTree() const { PX_ASSERT(!mUncommittedChanges); return mAABBTree; }
151 PX_FORCE_INLINE AABBTree* getAABBTree() { PX_ASSERT(!mUncommittedChanges); return mAABBTree; }
152 PX_FORCE_INLINE void setAABBTree(AABBTree* tree) { mAABBTree = tree; }
153 PX_FORCE_INLINE const AABBTree* hasAABBTree() const { return mAABBTree; }
154 PX_FORCE_INLINE BuildStatus getBuildStatus() const { return mProgress; }
155
156 // local functions
157// private:
158 NodeAllocator mNodeAllocator;
159
160 AABBTree* mAABBTree; // current active tree
161 AABBTreeBuildParams mBuilder; // this class deals with the details of the actual tree building
162 BuildStats mBuildStats;
163
164 // tree with build in progress, assigned to mAABBTree in commit, when mProgress is BUILD_FINISHED
165 // created in buildStep(), BUILD_NOT_STARTED
166 // This is non-null when there is a tree rebuild going on in progress
167 // and thus also indicates that we have to start saving the fixups
168 AABBTree* mNewTree;
169
170 // during rebuild the pool might change so we need a copy of boxes for the tree build
171 AABBTreeBounds mCachedBoxes;
172 PxU32 mNbCachedBoxes;
173
174 // incremented in commit(), serves as a progress counter for rebuild
175 PxU32 mNbCalls;
176
177 // PT: incremented each time we start building a new tree (i.e. effectively identifies a given tree)
178 // Timestamp is passed to bucket pruner to mark objects added there, linking them to a specific tree.
179 // When switching to the new tree, timestamp is used to remove old objects (now in the new tree) from
180 // the bucket pruner.
181 PxU32 mTimeStamp;
182
183 // this pruner is used for queries on objects that are not in the current tree yet
184 // includes both the objects in the tree being rebuilt and all the objects added later
185 ExtendedBucketPruner mBucketPruner;
186
187 BuildStatus mProgress; // current state of second tree build progress
188
189 // Fraction (as in 1/Nth) of the total number of primitives
190 // that should be processed per step by the AABB builder
191 // so if this value is 1, all primitives will be rebuilt, 2 => 1/2 of primitives per step etc.
192 // see also mNbCalls, mNbCalls varies from 0 to mRebuildRateHint-1
193 PxU32 mRebuildRateHint;
194
195 // Estimate for how much work has to be done to rebuild the tree.
196 PxU32 mTotalWorkUnits;
197
198 // Term to correct the work unit estimate if the rebuild rate is not matched
199 PxI32 mAdaptiveRebuildTerm;
200
201 const PxU32 mNbObjectsPerNode;
202 const BVHBuildStrategy mBuildStrategy;
203
204 PruningPool mPool; // Pool of AABBs
205
206 // maps pruning pool indices to aabb tree indices
207 // maps to INVALID_NODE_ID if the pool entry was removed or "pool index is outside input domain"
208 // The map is the inverse of the tree mapping: (node[map[poolID]].primitive == poolID)
209 // So:
210 // treeNodeIndex = mTreeMap.operator[](poolIndex)
211 // aabbTree->treeNodes[treeNodeIndex].primitives[0] == poolIndex
212 AABBTreeUpdateMap mTreeMap;
213 // Temporary update map, see BuildStatus notes above for details
214 AABBTreeUpdateMap mNewTreeMap;
215
216 // This is only set once in the constructor and is equivalent to isDynamicTree
217 // if it set to false then a 1-shot rebuild is performed in commit()
218 // bucket pruner is only used with incremental rebuild
219 const bool mIncrementalRebuild;
220
221 // A rebuild can be triggered even when the Pruner is not dirty
222 // mUncommittedChanges is set to true in add, remove, update and buildStep
223 // mUncommittedChanges is set to false in commit
224 // mUncommittedChanges has to be false (commit() has to be called) in order to run a query as defined by the
225 // mUncommittedChanges is not set to true in add, when pruning structure is provided. Scene query shapes
226 // are merged to current AABB tree directly
227 // Pruner higher level API
228 bool mUncommittedChanges;
229
230 // A new AABB tree is built if an object was added, removed or updated
231 // Changing objects during a build will trigger another rebuild right afterwards
232 // this is set to true if a new tree has to be created again after the current rebuild is done
233 bool mNeedsNewTree;
234
235 // This struct is used to record modifications made to the pruner state
236 // while a tree is building in the background
237 // this is so we can apply the modifications to the tree at the time of completion
238 // the recorded fixup information is: removedIndex (in ::remove()) and
239 // lastIndexMoved which is the last index in the pruner array
240 // (since the way we remove from PruningPool is by swapping last into removed slot,
241 // we need to apply a fixup so that it syncs up that operation in the new tree)
243 {
244 PX_FORCE_INLINE NewTreeFixup(PxU32 removedIndex_, PxU32 relocatedLastIndex_)
245 : removedIndex(removedIndex_), relocatedLastIndex(relocatedLastIndex_) {}
246 PxU32 removedIndex;
247 PxU32 relocatedLastIndex;
248 };
249 PxArray<NewTreeFixup> mNewTreeFixups;
250
251 PxArray<PoolIndex> mToRefit;
252
253 // Internal methods
254 bool fullRebuildAABBTree(); // full rebuild function, used with static pruner mode
255 void release();
256 void refitUpdatedAndRemoved();
257 void updateBucketPruner();
258 };
259
260}
261
262}
263
264#endif
Definition GuAABBPruner.h:126
bool fullRebuildAABBTree()
Definition GuAABBPruner.cpp:649
virtual bool prepareBuild()
Definition GuAABBPruner.cpp:594
virtual bool buildStep(bool synchronousCall=true)
Definition GuAABBPruner.cpp:478
virtual void setRebuildRateHint(PxU32 nbStepsForRebuild)
Definition GuAABBPruner.cpp:317
Definition GuAABBTreeBounds.h:39
Contains AABB-tree build parameters.
Definition GuAABBTree.h:57
Definition GuAABBTreeUpdateMap.h:53
AABB-tree, N primitives/leaf.
Definition GuAABBTree.h:290
Definition GuPruner.h:203
Definition GuExtendedBucketPruner.h:95
Definition GuAABBTree.h:125
Definition GuPruningPool.h:55
Definition PxArray.h:53
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
Definition GuAABBPruner.h:243
Contains AABB-tree build statistics.
Definition GuAABBTreeBuildStats.h:40