Revision control

++ // Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
++ // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
++ // SPDX-FileCopyrightText: Copyright (c) 2008-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
++ // SPDX-License-Identifier: Apache-2.0
++
++ #ifndef PXS_SIMPLE_ISLAND_GEN_H
++ #define PXS_SIMPLE_ISLAND_GEN_H
++
++ #include "foundation/PxUserAllocated.h"
++ #include "PxsIslandSim.h"
++ #include "CmTask.h"
++
++ /*
++ PT: runs first part of the island gen's second pass in parallel with the Pxg-level constraint partitioning.
++
++ mIslandGen task spawns Pxg constraint partitioning task(s).
++ mIslandGen runs processNarrowPhaseTouchEvents() in parallel with Pxg.
++
++ ///////////////////////////////////////////////////////////////////////////////
++
++ Previous design:
++
++ mPostIslandGen runs as a continuation task after mIslandGen and Pxg.
++
++ mPostIslandGen mainly runs mSetEdgesConnectedTask, which:
++ - calls mSimpleIslandManager->setEdgeConnected()
++ - calls mSimpleIslandManager-secondPassIslandGen()
++ - calls wakeObjectsUp()
++
++ ///////////////////////////////////////////////////////////////////////////////
++
++ New design:
++
++ postIslandGen is not a task anymore (mPostIslandGen does not exist).
++ postIslandGen is directly called at the end of mIslandGen.
++ So it now runs in parallel with Pxg.
++ mIslandGen and Pxg continue to mSolver task.
++
++ postIslandGen mainly runs mSetEdgesConnectedTask, which:
++ - calls mSimpleIslandManager->setEdgeConnected()
++ - calls mSimpleIslandManager->secondPassIslandGenPart1()
++
++ mSolver now first runs the parts that don't overlap with Pxg:
++ - calls mSimpleIslandManager-secondPassIslandGenPart2()
++ - calls wakeObjectsUp()
++
++ ///////////////////////////////////////////////////////////////////////////////
++
++ Before:
++ mIslandGen->processNarrowPhaseTouchEvents |mPostIslandGen |mSolver
++ =>PxgConstraintPartition |=>setEdgesConnected->secondPassIslandGen->wakeObjectsUp|
++
++ After:
++ mIslandGen->processNarrowPhaseTouchEvents->postIslandGen |secondPassIslandGenPart2->wakeObjectsUp->mSolver
++ =>PxgConstraintPartition =>setEdgesConnected->secondPassIslandGenPart1 |
++ */
++ #define USE_SPLIT_SECOND_PASS_ISLAND_GEN 1
++
++ namespace physx
++ {
++ class PxsContactManager;
++
++ // PT: TODO: fw declaring an Sc class here is not good
++ namespace Sc
++ {
++ class Interaction;
++ }
++
++ namespace Dy
++ {
++ struct Constraint;
++ }
++
++ namespace IG
++ {
++ class SimpleIslandManager;
++
++ class ThirdPassTask : public Cm::Task
++ {
++ SimpleIslandManager& mIslandManager;
++ IslandSim& mIslandSim;
++
++ public:
++
++ ThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager, IslandSim& islandSim);
++
++ virtual void runInternal() PX_OVERRIDE;
++
++ virtual const char* getName() const PX_OVERRIDE
++ {
++ return "ThirdPassIslandGenTask";
++ }
++
++ private:
++ PX_NOCOPY(ThirdPassTask)
++ };
++
++ class PostThirdPassTask : public Cm::Task
++ {
++ SimpleIslandManager& mIslandManager;
++
++ public:
++
++ PostThirdPassTask(PxU64 contextID, SimpleIslandManager& islandManager);
++
++ virtual void runInternal() PX_OVERRIDE;
++
++ virtual const char* getName() const PX_OVERRIDE
++ {
++ return "PostThirdPassTask";
++ }
++ private:
++ PX_NOCOPY(PostThirdPassTask)
++ };
++
++ class AuxCpuData
++ {
++ public:
++ PX_FORCE_INLINE PxsContactManager* getContactManager(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mConstraintOrCm[edgeId]); }
++ PX_FORCE_INLINE Dy::Constraint* getConstraint(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mConstraintOrCm[edgeId]); }
++
++ Cm::BlockArray<void*> mConstraintOrCm; //! Pointers to either the constraint or Cm for this pair
++ };
++
++ class SimpleIslandManager : public PxUserAllocated
++ {
++ HandleManager<PxU32> mNodeHandles; //! Handle manager for nodes
++ HandleManager<EdgeIndex> mEdgeHandles; //! Handle manager for edges
++
++ //An array of destroyed nodes
++ PxArray<PxNodeIndex> mDestroyedNodes;
++ Cm::BlockArray<Sc::Interaction*> mInteractions;
++
++ //Edges destroyed this frame
++ PxArray<EdgeIndex> mDestroyedEdges;
++ GPUExternalData mGpuData;
++
++ CPUExternalData mCpuData;
++ AuxCpuData mAuxCpuData;
++
++ PxBitMap mConnectedMap;
++
++ // PT: TODO: figure out why we still need both
++ IslandSim mAccurateIslandManager;
++ IslandSim mSpeculativeIslandManager;
++
++ ThirdPassTask mSpeculativeThirdPassTask;
++ ThirdPassTask mAccurateThirdPassTask;
++
++ PostThirdPassTask mPostThirdPassTask;
++ PxU32 mMaxDirtyNodesPerFrame;
++
++ const PxU64 mContextID;
++ const bool mGPU;
++ public:
++
++ SimpleIslandManager(bool useEnhancedDeterminism, bool gpu, PxU64 contextID);
++ ~SimpleIslandManager();
++
++ PxNodeIndex addNode(bool isActive, bool isKinematic, Node::NodeType type, void* object);
++ void removeNode(const PxNodeIndex index);
++
++ // PT: these two functions added for multithreaded implementation of Sc::Scene::islandInsertion
++ void preallocateContactManagers(PxU32 nb, EdgeIndex* handles);
++ bool addPreallocatedContactManager(EdgeIndex handle, PxsContactManager* manager, PxNodeIndex nodeHandle1, PxNodeIndex nodeHandle2, Sc::Interaction* interaction, Edge::EdgeType edgeType);
++
++ EdgeIndex addContactManager(PxsContactManager* manager, PxNodeIndex nodeHandle1, PxNodeIndex nodeHandle2, Sc::Interaction* interaction, Edge::EdgeType edgeType);
++ EdgeIndex addConstraint(Dy::Constraint* constraint, PxNodeIndex nodeHandle1, PxNodeIndex nodeHandle2, Sc::Interaction* interaction);
++
++ PX_FORCE_INLINE PxIntBool isEdgeConnected(EdgeIndex edgeIndex) const { return mConnectedMap.test(edgeIndex); }
++
++ void activateNode(PxNodeIndex index);
++ void deactivateNode(PxNodeIndex index);
++ void putNodeToSleep(PxNodeIndex index);
++
++ void removeConnection(EdgeIndex edgeIndex);
++
++ void firstPassIslandGen();
++ void additionalSpeculativeActivation();
++ void secondPassIslandGen();
++ void secondPassIslandGenPart1();
++ void secondPassIslandGenPart2();
++ void thirdPassIslandGen(PxBaseTask* continuation);
++
++ PX_INLINE void clearDestroyedPartitionEdges()
++ {
++ mGpuData.mDestroyedPartitionEdges.forceSize_Unsafe(0);
++ }
++
++ void setEdgeConnected(EdgeIndex edgeIndex, Edge::EdgeType edgeType);
++ void setEdgeDisconnected(EdgeIndex edgeIndex);
++
++ void setEdgeRigidCM(const EdgeIndex edgeIndex, PxsContactManager* cm);
++
++ void clearEdgeRigidCM(const EdgeIndex edgeIndex);
++
++ void setKinematic(PxNodeIndex nodeIndex);
++
++ void setDynamic(PxNodeIndex nodeIndex);
++
++ PX_FORCE_INLINE IslandSim& getSpeculativeIslandSim() { return mSpeculativeIslandManager; }
++ PX_FORCE_INLINE const IslandSim& getSpeculativeIslandSim() const { return mSpeculativeIslandManager; }
++
++ PX_FORCE_INLINE IslandSim& getAccurateIslandSim() { return mAccurateIslandManager; }
++ PX_FORCE_INLINE const IslandSim& getAccurateIslandSim() const { return mAccurateIslandManager; }
++
++ PX_FORCE_INLINE const AuxCpuData& getAuxCpuData() const { return mAuxCpuData; }
++
++ PX_FORCE_INLINE PxU32 getNbEdgeHandles() const { return mEdgeHandles.getTotalHandles(); }
++
++ PX_FORCE_INLINE PxU32 getNbNodeHandles() const { return mNodeHandles.getTotalHandles(); }
++
++ void deactivateEdge(const EdgeIndex edge);
++
++ PX_FORCE_INLINE PxsContactManager* getContactManager(IG::EdgeIndex edgeId) const { return reinterpret_cast<PxsContactManager*>(mAuxCpuData.mConstraintOrCm[edgeId]); }
++ PX_FORCE_INLINE Dy::Constraint* getConstraint(IG::EdgeIndex edgeId) const { return reinterpret_cast<Dy::Constraint*>(mAuxCpuData.mConstraintOrCm[edgeId]); }
++
++ PX_FORCE_INLINE Sc::Interaction* getInteractionFromEdgeIndex(IG::EdgeIndex edgeId) const { return mInteractions[edgeId]; }
++
++ PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
++
++ bool checkInternalConsistency();
++
++ private:
++
++ friend class ThirdPassTask;
++ friend class PostThirdPassTask;
++
++ bool validateDeactivations() const;
++ EdgeIndex addEdge(void* edge, PxNodeIndex nodeHandle1, PxNodeIndex nodeHandle2, Sc::Interaction* interaction);
++ EdgeIndex resizeEdgeArrays(EdgeIndex handle, bool flag);
++
++ PX_NOCOPY(SimpleIslandManager)
++ };
++
++ }
++ }
++
++ #endif