PhysX: [hard crash] unassigned pointer after Sc::Scene::preallocateContactManagers initialization

I have a program which integrates PhysX for offline rigidbody simulations.

I’m getting a crash when instantiating a lot of rigidbodies in close proximity (100k+ RBs, generating millions of contacts). The crash does not occur when instantiating less rigidbodies (I’m not sure the exact number of RBs that triggers the crash…but everything runs fine when instantiating only 1000 RBs, for example)

The crash happens in PxsNphaseImplementationContext::registerContactManager because PxsContactManager* cm is not initialized (it has a value of 0xcdcdcdcdcdcdcdcc).

The only place in code where PxsContactManagers seem to be initialized is in Sc::Scene::preallocateContactManagers. The code flow seems to be as follows:

mPreallocatedContactManagers.forceSize_Unsafe is called to resize the cm array
mOverlapFilterTasks are iterated, initializing cms as required (through calls to mLLContext->getContactManagerPool().preallocate(…))

My assumption is that at the end of the call to preallocateContactManagers, each pointer in the mPreallocatedContactManagers array will point to valid memory. However, with large numbers of rigidbodies, some pointers remain unassigned, despite being referenced later in code (which causes the crash).

I’ve been trying to figure out where exactly things are going wrong, but there are a ton of different branches and dependencies within all these functions that are difficult to trace, especially when the number of contacts generated with my 100k rigidbodies is huge (multi-millions). Do any PhysX devs have an idea where to start looking first to figure out why some pointers are being skipped during the initialization process? I still don’t quite follow the logic of what’s going on in CmPool::preallocate, but it seems like that would be the best place to start looking? Or are my assumptions about how/where cms are initialized completely wrong?

For reference, when the crash occurs, the value of ‘totalCreatedPairs’ (which mPreallocatedContactManagers is being resized to) is 48467668. So a huge number, but not so huge that I’d expect it to cause the crashes I’m experiencing.

It’s also worth noting that when I compile the simulation in Debug mode, no PX assertions are triggered. So I’m not simply missing a checksomewhere.

I’ll provide updated complete instructions after Christmas break but I suspect this is hitting an arbitrary limit on the number of contact managers the pool can allocate. Please take a look at where the contact manager pool is constructed. You should see a parameter for the maximum number of slabs. Please increase this and it should fix your issue. Feel free to make this arbitrarily large. It shouldn’t have negative side-effects. We are aware of this issue and will remove this limit in a future release.

Thank you for the workaround.

I set the value of maxSlabs in the mContactManagerPool constructor (in the PxsContext constructor in PxsContext.cpp) to 8192 * 64 (default is 8192) and no longer get the crash. Should I be worried that setting this value too high will increase overall memory consumption (even in a lighter scene with less contacts)?

Does this value control the initially allocated size of the pool? Or just the maximum value it can expand to? In the PoolList constructor within CmPool.h, the value of maxSlabs seems to be used to allocate something in the mSlabs constructor, but I’m having a tough time tracing the logic of what/where.

In other words…can I just set maxSlabs to PX_MAX_U32 or will that cause problems?

The PoolList allocates an array of pointers to slabs based on the maxSlabs parameter. There was probably a valid reason for the design decisions behind this class when it was created, but it doesn’t make a lot of sense with current hardware. We’ll remove this maxElements parameter and make this class continue to grow until memory has been exhausted.

In the meantime, please set this to an arbitrarily large value, but be aware that you are paying 8 bytes for each slab so at 64*8192, it costs you about ~4MB (not a big deal). This will give you enough space for 134 million pairs, which should be sufficient for you for now hopefully.

It is probably not a good idea to use PX_MAX_U32 slabs because that would allocate a 32GB buffer of pointers and we would not be able to index all the contact managers anyway because we only have a 32-bit index, which has some bits reserved for other usage.

Thank you for the explanation! 64*8192 will be more than enough for my purposes.