Files
XCEngine/engine/third_party/physx/source/gpubroadphase/include/PxgAABBManager.h

328 lines
12 KiB
C++

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#ifndef PXG_AABBMANAGER_H
#define PXG_AABBMANAGER_H
#include "BpAABBManagerBase.h"
#include "PxgCudaBuffer.h"
#include "PxgAggregate.h"
#include "CmIDPool.h"
#include "PxgBroadPhasePairReport.h"
#include "PxgAggregateDesc.h"
#include "CmTask.h"
#include "foundation/PxPinnedArray.h"
namespace physx
{
class PxgCudaKernelWranglerManager;
class PxCudaContextManager;
class PxgCudaBroadPhaseSap;
struct PxGpuDynamicsMemoryConfig;
class PxgAABBManager;
class PxSceneDesc;
struct PxBoundTransformUpdate
{
PxU32 indexTo;
PxU32 indexFrom; //MSB stores info if the bound is new. New is copied from cpu array, not new - from gpu array
};
class PxgProcessFoundPairTask : public Cm::Task
{
PxgAABBManager* mManager;
public:
PxgProcessFoundPairTask(PxgAABBManager* manager) : Cm::Task(0), mManager(manager)
{
}
virtual void runInternal();
virtual const char* getName() const { return "PxgProcessFoundPairTask"; }
};
class PxgProcessLostPairTask : public Cm::Task
{
PxgAABBManager* mManager;
public:
PxgProcessLostPairTask(PxgAABBManager* manager) : Cm::Task(0), mManager(manager)
{
}
virtual void runInternal();
virtual const char* getName() const { return "PxgProcessLostPairTask"; }
};
class PxgAABBManager : public Bp::AABBManagerBase
{
public:
PxgAABBManager(PxgCudaKernelWranglerManager* gpuKernelWrangler,
PxCudaContextManager* cudaContextManager,
PxgHeapMemoryAllocatorManager* heapMemoryManager,
const PxGpuDynamicsMemoryConfig& config,
Bp::BroadPhase& bp, Bp::BoundsArray& boundsArray, PxFloatArrayPinned& contactDistance,
PxU32 maxNbAggregates, PxU32 maxNbShapes, PxVirtualAllocator& allocator, PxU64 contextID,
PxPairFilteringMode::Enum kineKineFilteringMode, PxPairFilteringMode::Enum staticKineFilteringMode);
virtual ~PxgAABBManager() {}
// AABBManagerBase
virtual void destroy() PX_OVERRIDE;
virtual Bp::AggregateHandle createAggregate(Bp::BoundsIndex index, Bp::FilterGroup::Enum group, void* userData, PxU32 maxNumShapes, PxAggregateFilterHint filterHint, PxU32 envID) PX_OVERRIDE;
virtual bool destroyAggregate(Bp::BoundsIndex& index, Bp::FilterGroup::Enum& group, Bp::AggregateHandle aggregateHandle) PX_OVERRIDE;
virtual bool addBounds(Bp::BoundsIndex index, PxReal contactDistance, Bp::FilterGroup::Enum group, void* userData, Bp::AggregateHandle aggregateHandle, Bp::ElementType::Enum volumeType, PxU32 envID) PX_OVERRIDE;
virtual bool removeBounds(Bp::BoundsIndex index) PX_OVERRIDE;
virtual void updateBPFirstPass(PxU32 numCpuTasks, Cm::FlushPool& flushPool, bool hasContactDistanceUpdated, PxBaseTask* continuation) PX_OVERRIDE;
virtual void updateBPSecondPass(PxcScratchAllocator* scratchAllocator, PxBaseTask* continuation) PX_OVERRIDE;
virtual void postBroadPhase(PxBaseTask*, Cm::FlushPool& flushPool) PX_OVERRIDE;
virtual void reallocateChangedAABBMgActorHandleMap(const PxU32 size) PX_OVERRIDE;
virtual void visualize(PxRenderOutput& out) PX_OVERRIDE;
virtual void releaseDeferredAggregateIds() PX_OVERRIDE;
virtual void setGPUStateChanged() PX_OVERRIDE { mGPUStateChanged = true; }
virtual void setPersistentStateChanged() PX_OVERRIDE { mPersistentStateChanged = true; }
//~AABBManagerBase
PxgCudaBuffer mVolumDataBuf;
void markAggregateBoundsBitmap();
void processFoundPairs();
void processLostPairs();
// PX_FORCE_INLINE PxBitMapPinned& getAggregatedBoundMap() { return mAggregatedBoundMap; }
PX_FORCE_INLINE CUdeviceptr getAggregatedBounds() { return mAggregatedBoundsBuf.getDevicePtr(); }
PX_FORCE_INLINE CUdeviceptr getAddedHandles() { return mAddedHandleBuf.getDevicePtr(); }
PX_FORCE_INLINE CUdeviceptr getRemovedHandles() { return mRemovedHandleBuf.getDevicePtr(); }
PX_FORCE_INLINE CUdeviceptr getChangedAABBMgrHandles() { return mChangedAABBMgrHandlesBuf.getDevicePtr(); }
PX_FORCE_INLINE PxU32 getChangedAABBMgrHandlesWordCount() { return mChangedHandleMap.getWordCount(); }
private:
void preBpUpdate_GPU();
void gpuDmaDataUp();
void clearDirtyAggs();
void resizeFoundAndLostPairs();
void computeAggregateBounds();
void updateDescriptor(CUstream bpStream);
PxgCudaKernelWranglerManager* mGpuKernelWranglerManager;
PxCudaContextManager* mCudaContextManager;
PxCudaContext* mCudaContext;
PxgHeapMemoryAllocatorManager* mHeapMemoryManager;
PxArray<PxgAggregate> mAggregates; //cpu mirror
PxPinnedArray<PxgAggregatePair> mAggregatePairs;
PxPinnedArray<Bp::AggregateHandle> mDirtyAggregateIndices;
PxPinnedArray<PxgAggregate> mDirtyAggregates;
//found and lost pairs for agg vs agg and agg vs actor
PxPinnedArray<PxgBroadPhasePair> mFoundPairs;
PxPinnedArray<PxgBroadPhasePair> mLostPairs;
PxInt32ArrayPinned mDirtyBoundIndices;
PxInt32ArrayPinned mDirtyBoundStartIndices; //start index of each aggregate in the dirty bound indices list
PxInt32ArrayPinned mRemovedAggregatedBounds;
PxInt32ArrayPinned mAddedAggregatedBounds;
Cm::DeferredIDPool mAggregatesIdPool; //generate the remap id between pxgbodysim and pxgaggregate
PxBitMap mDirtyAggregateBitMap;
PxBitMapPinned mAggregatedBoundMap;
PxArray<PxgAggregateBuffer*> mAggregateBufferArray;
PxgAggregateDesc* mAggregateDesc;
PxgCudaBuffer mAggregateBuf;
PxgCudaBuffer mAggregatePairsBuf;
PxgCudaBuffer mDirtyAggregateIndiceBuf;
PxgCudaBuffer mDirtyAggregateBuf;
PxgCudaBuffer mDirtyBoundIndicesBuf;
PxgCudaBuffer mDirtyBoundStartIndicesBuf;
PxgCudaBuffer mRemovedAggregatedBoundsBuf;
PxgCudaBuffer mAddedAggregatedBoundsBuf;
PxgCudaBuffer mAggPairBuf; //persistent pairs
PxgCudaBuffer mNumAggPairBuf; // number of app pairs
PxgCudaBuffer mAggregateDescBuf;
PxgCudaBuffer mFoundPairsBuf;
PxgCudaBuffer mLostPairsBuf;
PxgCudaBuffer mFreeIDPool;
PxgCudaBuffer mFreeIDs;
PxgCudaBuffer mRemoveBitmap;
PxgCudaBuffer mRemoveHistogram;
PxgCudaBuffer mAggregatedBoundsBuf;
PxgCudaBuffer mAddedHandleBuf;
PxgCudaBuffer mRemovedHandleBuf;
PxgCudaBuffer mChangedAABBMgrHandlesBuf;
PxU32 mNumAggregatesSlots;
PxU32 mMaxFoundLostPairs;
PxU32 mMaxAggPairs;
PxgProcessFoundPairTask mFoundPairTask;
PxgProcessLostPairTask mLostPairTask;
// PT: this flag is set:
// - via setGPUStateChanged():
// - in PxgSimulationCore::applyActorData() when body data is changed
// - in FEMClothShapeSim::updateBoundsInAABBMgr()
// - in ParticleSystemShapeSim::updateBoundsInAABBMgr
// - in SoftBodyShapeSim::updateBoundsInAABBMgr()
// - when mOriginShifted is false and hasActive is true in PxgAABBManager::updateBPFirstPass
//
// It is unclear whether we need to set the flag in all of these cases.
//
// The flag is used:
// - in PxgAABBManager::preBpUpdate_GPU
// - to skip DMA of mChangedHandleMap
// - in PxgAABBManager::updateBPSecondPass
// - in the GPU broadphase (passed there as part of the updateData structure)
// - TODO: investigate what happens there
// - to skip kernel launches of AGG_ADD_AGGPAIRS_STAGE_1/AGG_ADD_AGGPAIRS_STAGE_2
bool mGPUStateChanged; //non-rigid body, direct API calls
// PT: this flag is set:
// - via setPersistentStateChanged():
// - when a contact distance changes
// - when an aggregate is removed (PxgAABBManager::destroyAggregate)
// - when an object is added (PxgAABBManager::addBounds)
// - when an aggregated is added (PxgAABBManager::addBounds)
// - when an object is removed (PxgAABBManager::removeBounds)
// - when an aggregated is removed (PxgAABBManager::removeBounds)
// - in PxgAABBManager::updateBPFirstPass if hasContactDistanceUpdated is true
// - when mOriginShifted is true, during PxgAABBManager::updateBPFirstPass
//
// It is unclear whether we need to set the flag in all of these cases.
//
// The flag is used:
// - in PxgAABBManager::preBpUpdate_GPU
// - to skip DMAs of mAddedHandleMap/mRemovedHandleMap
// - to skip DMA of mAggregatedBoundMap / mVolumeData
// - to skip the preBroadphase call
// - to skip DMA of mChangedHandleMap
// - in PxgAABBManager::updateBPSecondPass
// - in the GPU broadphase (passed there as part of the updateData structure)
// - TODO: investigate what happens there
// - to skip kernel launches of AGG_ADD_AGGPAIRS_STAGE_1/AGG_ADD_AGGPAIRS_STAGE_2
bool mPersistentStateChanged;
};
class PxgBoundsArray : public Bp::BoundsArray
{
PX_NOCOPY(PxgBoundsArray)
public:
PxgBoundsArray(PxVirtualAllocator& allocator)
: BoundsArray(allocator)
, mIsFirstCopy(true)
, mChanges(allocator)
{
}
virtual ~PxgBoundsArray() PX_OVERRIDE
{
mChanges.clear();
}
void updateBounds(const PxTransform& transform, const PxGeometry& geom, PxU32 index,
PxU32 indexFrom) PX_OVERRIDE PX_FINAL
{
if(indexFrom == index) // new, needs to be copied from CPU
{
Gu::computeBounds(mBounds[index], geom, transform, 0.0f, 1.0f);
updateChanges(index, indexFrom, true);
}
else
{
updateChanges(index, indexFrom, false);
}
}
void setBounds(const PxBounds3& bounds, PxU32 index) PX_OVERRIDE PX_FINAL
{
mBounds[index] = bounds;
updateChanges(index, index, true);
}
PX_FORCE_INLINE PxU32 getNumberOfChanges()
{
return mChanges.size();
}
PX_FORCE_INLINE PxArray<PxBoundTransformUpdate, PxVirtualAllocator>& getStagingBuffer()
{
return mChanges;
}
PX_FORCE_INLINE void resetChanges()
{
mChanges.reset();
}
PX_FORCE_INLINE bool isFirstCopy()
{
return mIsFirstCopy;
}
PX_FORCE_INLINE void setCopied()
{
mIsFirstCopy = false;
}
private:
PX_FORCE_INLINE void updateChanges(PxU32 indexTo, PxU32 indexFrom, bool isNew)
{
if(!mIsFirstCopy)
{
PxBoundTransformUpdate update;
update.indexTo = indexTo;
update.indexFrom = indexFrom & 0x7FFFFFFF;
if(isNew)
{
update.indexFrom |= (1U << 31);
}
mChanges.pushBack(update);
}
}
bool mIsFirstCopy;
PxArray<PxBoundTransformUpdate, PxVirtualAllocator> mChanges;
};
}
#endif