Revision control
Copy as Markdown
// 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 DY_CONTEXT_H
#define DY_CONTEXT_H
#include "PxSceneDesc.h"
#include "DyThresholdTable.h"
#include "PxcNpThreadContext.h"
#include "PxsSimulationController.h"
#include "PxsHeapStats.h"
#include "DyConstraintWriteBack.h"
#include "foundation/PxAllocator.h"
#include "foundation/PxUserAllocated.h"
#include "CmPinnableArray.h"
#include "CmPinnableBitMap.h"
#include "PxsRigidBody.h"
namespace physx
{
class PxcNpMemBlockPool;
namespace Cm
{
class FlushPool;
}
namespace IG
{
class SimpleIslandManager;
}
struct PxvSimStats;
class PxsContactManager;
struct PxsContactManagerOutputCounts;
class PxvNphaseImplementationContext;
namespace Dy
{
/**
Defining class, so it can be forward declared without pulling in DyThreasholdTable.h.
*/
class ThresholdStream : public PxArray<ThresholdStreamElement>{};
/**
Threshold stream that may be backed by device mapped host memory for the GPU pipeline,
hence the pageable fallback is disabled.
For the CPU pipeline, the stream is backed by pageable memory anyways, so no fallback
required either.
*/
class ThresholdStreamMapped : public Cm::PinnableArray<ThresholdStreamElement>
{
public:
ThresholdStreamMapped(Cm::VirtualAllocatorCallback& allocator) :
Cm::PinnableArray<ThresholdStreamElement>(allocator, PxsHeapStats::eSOLVER, Cm::PinnableAllocatorFallback::eDISABLED)
{}
};
class Context : public PxUserAllocated
{
PX_NOCOPY(Context)
public:
// PT: TODO: consider making all of these public at this point
// PT: please avoid useless comments like "returns Blah" for a function called "getBlah".
PX_FORCE_INLINE PxReal getMaxBiasCoefficient() const { return mMaxBiasCoefficient; }
PX_FORCE_INLINE void setMaxBiasCoefficient(PxReal coeff) { mMaxBiasCoefficient = coeff; }
PX_FORCE_INLINE PxReal getCorrelationDistance() const { return mCorrelationDistance; }
PX_FORCE_INLINE void setCorrelationDistance(PxReal f) { mCorrelationDistance = f; }
PX_FORCE_INLINE PxReal getBounceThreshold() const { return mBounceThreshold; }
PX_FORCE_INLINE void setBounceThreshold(PxReal f) { mBounceThreshold = f; }
PX_FORCE_INLINE PxReal getFrictionOffsetThreshold() const { return mFrictionOffsetThreshold; }
PX_FORCE_INLINE void setFrictionOffsetThreshold(PxReal offset) { mFrictionOffsetThreshold = offset; }
PX_FORCE_INLINE PxReal getCCDSeparationThreshold() const { return mCCDSeparationThreshold; }
PX_FORCE_INLINE void setCCDSeparationThreshold(PxReal offset) { mCCDSeparationThreshold = offset; }
PX_FORCE_INLINE PxU32 getSolverBatchSize() const { return mSolverBatchSize; }
PX_FORCE_INLINE void setSolverBatchSize(PxU32 f) { mSolverBatchSize = f; }
PX_FORCE_INLINE PxU32 getSolverArticBatchSize() const { return mSolverArticBatchSize; }
PX_FORCE_INLINE void setSolverArticBatchSize(PxU32 f) { mSolverArticBatchSize = f; }
PX_FORCE_INLINE PxReal getDt() const { return mDt; }
PX_FORCE_INLINE void setDt(const PxReal dt) { mDt = dt; }
// PT: TODO: we have a setDt function but it doesn't set the inverse dt, what's the story here?
PX_FORCE_INLINE PxReal getInvDt() const { return mInvDt; }
//Forces any cached body state to be updated!
PX_FORCE_INLINE void setStateDirty(bool dirty) { mBodyStateDirty = dirty; }
PX_FORCE_INLINE bool isStateDirty() const { return mBodyStateDirty; }
// Returns the maximum solver constraint size in this island in bytes.
PX_FORCE_INLINE PxU32 getMaxSolverConstraintSize() const { return mMaxSolverConstraintSize; }
PX_FORCE_INLINE PxReal getLengthScale() const { return mLengthScale; }
PX_FORCE_INLINE const PxVec3& getGravity() const { return mGravity; }
PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
PX_FORCE_INLINE ThresholdStream& getThresholdStream() { return mThresholdStream; }
PX_FORCE_INLINE ThresholdStreamMapped& getForceChangedThresholdStream() { return mForceChangedThresholdStream; }
PX_FORCE_INLINE ThresholdTable& getThresholdTable() { return mThresholdTable; }
PX_FORCE_INLINE PxcDataStreamPool& getContactStreamPool() { return mContactStreamPool; }
PX_FORCE_INLINE PxcDataStreamPool& getPatchStreamPool() { return mPatchStreamPool; }
PX_FORCE_INLINE PxcDataStreamPool& getForceStreamPool() { return mForceStreamPool; }
PX_FORCE_INLINE Cm::PinnableArray<Dy::ConstraintWriteback>& getConstraintWriteBackPool() { return mConstraintWriteBackPool; }
PX_FORCE_INLINE PxcDataStreamPool& getFrictionPatchStreamPool() { return mFrictionPatchStreamPool; }
/**
\brief Returns whether sleeping is disabled in the scene
\return True if sleeping is disabled (PxSceneFlag::eDISABLE_SLEEPING is set)
*/
PX_FORCE_INLINE bool isSleepingDisabled() const { return mIsSleepingDisabled; }
PX_FORCE_INLINE bool isEnhancedDeterminismEnabled() const { return mUseEnhancedDeterminism; }
/**
\brief Destroys this dynamics context
*/
virtual void destroy() = 0;
/**
\brief The entry point for the constraint solver.
\param[in] dt The simulation time-step
\param[in] continuation The continuation task for the solver
\param[in] processLostTouchTask The task that processes lost touches
This method is called after the island generation has completed. Its main responsibilities are:
(1) Reserving the solver body pools
(2) Initializing the static and kinematic solver bodies, which are shared resources between islands.
(3) Construct the solver task chains for each island
Each island is solved as an independent solver task chain. In addition, large islands may be solved using multiple parallel tasks.
Island solving is asynchronous. Once all islands have been solved, the continuation task will be called.
*/
virtual void update( Cm::FlushPool& flushPool, PxBaseTask* continuation, PxBaseTask* postPartitioningTask, PxBaseTask* processLostTouchTask,
PxvNphaseImplementationContext* nPhaseContext, PxU32 maxPatchesPerCM, PxU32 maxArticulationLinks,
PxReal dt, const PxVec3& gravity, Cm::PinnableBitMap& changedHandleMap) = 0;
virtual void updatePostPartitioning(PxBaseTask* /*processLostTouchTask*/,
PxvNphaseImplementationContext* /*nPhaseContext*/, PxU32 /*maxPatchesPerCM*/, PxU32 /*maxArticulationLinks*/,
PxReal /*dt*/, const PxVec3& /*gravity*/, Cm::PinnableBitMap& /*changedHandleMap*/) {}
virtual void processPatches( Cm::FlushPool& /*flushPool*/, PxBaseTask* /*continuation*/,
PxsContactManager** /*lostFoundPatchManagers*/, PxU32 /*nbLostFoundPatchManagers*/, PxsContactManagerOutputCounts* /*outCounts*/) {}
/**
\brief This method copy gpu solver body data to cpu body core
*/
virtual void updateBodyCore(PxBaseTask* /*continuation*/) {}
/**
\brief Called after update's task chain has completed. This collects the results of the solver together.
This method combines the results of several islands, e.g. constructing scene-level simulation statistics and merging together threshold streams for contact notification.
*/
virtual void mergeResults() = 0;
virtual void setSimulationController(PxsSimulationController* simulationController) = 0;
virtual void getDataStreamBase(void*& /*contactStreamBase*/, void*& /*patchStreamBase*/, void*& /*forceAndIndicesStreamBase*/) {}
virtual PxSolverType::Enum getSolverType() const = 0;
virtual PxsExternalAccelerationProvider& getExternalRigidAccelerations() { return mRigidExternalAccelerations; }
// Only used for Direct GPU API pipeline at the moment.
virtual void setActiveBreakableConstraintCount(PxU32 activeBreakableConstraintCount) { PX_UNUSED(activeBreakableConstraintCount); }
protected:
Context(IG::SimpleIslandManager& islandManager, Cm::VirtualAllocatorCallback& allocator, Cm::VirtualAllocatorCallback& mappedAllocator,
PxvSimStats& simStats, PxReal maxBiasCoefficient, PxReal lengthScale, PxU64 contextID, PxSceneFlags sceneFlags) :
mForceChangedThresholdStream(mappedAllocator),
mIslandManager (islandManager),
mDt (1.0f),
mInvDt (1.0f),
mMaxBiasCoefficient (maxBiasCoefficient),
mEnableStabilization (sceneFlags & PxSceneFlag::eENABLE_STABILIZATION),
mUseEnhancedDeterminism (sceneFlags & PxSceneFlag::eENABLE_ENHANCED_DETERMINISM),
mSolveArticulationContactLast(sceneFlags & PxSceneFlag::eSOLVE_ARTICULATION_CONTACT_LAST),
mIsSleepingDisabled (sceneFlags & PxSceneFlag::eDISABLE_SLEEPING),
mBounceThreshold (-2.0f),
mLengthScale (lengthScale),
mSolverBatchSize (32),
mConstraintWriteBackPool (allocator),
mSimStats (simStats),
mContextID (contextID),
mBodyStateDirty (false)
{
}
virtual ~Context() {}
ThresholdStream mThresholdStream;
ThresholdStreamMapped mForceChangedThresholdStream;
ThresholdTable mThresholdTable;
IG::SimpleIslandManager& mIslandManager;
PxsSimulationController* mSimulationController;
/**
\brief Time-step.
*/
PxReal mDt;
/**
\brief 1/time-step.
*/
PxReal mInvDt;
PxReal mMaxBiasCoefficient;
const bool mEnableStabilization;
const bool mUseEnhancedDeterminism;
const bool mSolveArticulationContactLast;
const bool mIsSleepingDisabled;
PxVec3 mGravity;
/**
\brief max solver constraint size
*/
PxU32 mMaxSolverConstraintSize;
/**
\brief Threshold controlling the relative velocity at which the solver transitions between restitution and bias for solving normal contact constraint.
*/
PxReal mBounceThreshold;
/**
\brief Threshold controlling whether friction anchors are constructed or not. If the separation is above mFrictionOffsetThreshold, the contact will not be considered to become a friction anchor
*/
PxReal mFrictionOffsetThreshold;
/**
\brief Threshold controlling whether distant contacts are processed using bias, restitution or a combination of the two. This only has effect on pairs involving bodies that have enabled speculative CCD simulation mode.
*/
PxReal mCCDSeparationThreshold;
/**
\brief Threshold for controlling friction correlation
*/
PxReal mCorrelationDistance;
/**
\brief The length scale from PxTolerancesScale::length.
*/
PxReal mLengthScale;
/**
\brief The minimum size of an island to generate a solver task chain.
*/
PxU32 mSolverBatchSize;
/**
\brief The minimum number of articulations required to generate a solver task chain.
*/
PxU32 mSolverArticBatchSize;
/**
\brief Structure to encapsulate contact stream allocations. Used by GPU solver to reference pre-allocated pinned host memory
*/
PxcDataStreamPool mContactStreamPool;
/**
\brief Struct to encapsulate the contact patch stream allocations. Used by GPU solver to reference pre-allocated pinned host memory
*/
PxcDataStreamPool mPatchStreamPool;
/**
\brief Structure to encapsulate force stream allocations. Used by GPU solver to reference pre-allocated pinned host memory for force reports.
*/
PxcDataStreamPool mForceStreamPool;
/**
\brief Struct to encapsulate the friction patch stream allocations. Used by GPU solver to reference pre-allocated pinned host memory
*/
PxcDataStreamPool mFrictionPatchStreamPool;
/**
\brief Structure to encapsulate constraint write back allocations. Used by GPU/CPU solver to reference pre-allocated pinned host memory for breakable joint reports.
*/
Cm::PinnableArray<Dy::ConstraintWriteback> mConstraintWriteBackPool;
PxvSimStats& mSimStats;
const PxU64 mContextID;
PxsExternalAccelerationProvider mRigidExternalAccelerations;
bool mBodyStateDirty;
};
Context* createDynamicsContext( PxcNpMemBlockPool* memBlockPool, Cm::FlushPool& taskPool, PxvSimStats& simStats,
Cm::VirtualAllocatorCallback& allocator, PxsMaterialManager* materialManager,
IG::SimpleIslandManager& islandManager, PxU64 contextID, PxReal maxBiasCoefficient,
PxReal lengthScale, PxSceneFlags sceneFlags);
Context* createTGSDynamicsContext( PxcNpMemBlockPool* memBlockPool, Cm::FlushPool& taskPool, PxvSimStats& simStats,
Cm::VirtualAllocatorCallback& allocator, PxsMaterialManager* materialManager,
IG::SimpleIslandManager& islandManager, PxU64 contextID,
PxReal lengthScale, PxSceneFlags sceneFlags);
}
}
#endif