So while I was debugging my random PhysX crash, I ended up wrapping all my PhysX calls in lockRead/unlockRead and lockWrite/unlockWrite. Useless you say? I thought so, especially if that was not causing the problem. BUT what happened is that I use to think you cannot have any PhysX calls within a simulate/fetchResults window.
THIS IS NOT TRUE! YOU CAN!
This is my tip: that if you wrap your calls within appropriate locks/unlocks, you can access the PhysX objects even during the simulation without it crashing. In fact, I advise you to do this because what use is having physics simulation on a different thread if there is no chance of concurrency?
Something to think about, hope this helps other people.
If you’re accessing PhysX from multiple threads, even if these accesses happen outside of the simulate/fetchResults window, you need to use lockRead(), lockWrite() etc. or some application-specific mechanism to ensure that your modifications are thread safe. The lockRead/lockWrite mechanism is there to ensure that PhysX API calls are made in a thread safe way from the application. There is a flag you can raise on the scene, PxSceneFlag::eREQUIRE_RW_LOCK, which will cause PhysX to issue warnings if you make any API calls without having first acquired the appropriate lock.
However, if you are only calling PhysX API calls from a single thread, you don’t need to enable this flag or call lockRead(), lockWrite() etc. to ensure your application is thread safe. This includes calling PhysX API methods during the simulate()/fetchResults() window. Once simulate() has returned, physx will not modify the external, user-visible state of any actors in the scene until fetchResults() is called. This means that once the call to simulate() has returned and physx is being processed on the worker threads, it is perfectly safe to access and modify body or scene properties without needing to lock the scene to protect against modifications coming from PhysX - you only need to do this to protect against non thread-safe accesses from the application. Any modifications made during the simulate()/fetchResults() window will be buffered and reflected during fetchResults() - these will overwrite the results from the scene. Not all API calls support buffering, e.g. bulk data like particles or cloth, but all of the rigid body functionality supports buffering. If an API call doesn’t support buffering and you call it during the simulate()/fetchResults() window, you should get a warning in the checked build and whatever modification you attempted will be ignored.
So, in summary, if you only have 1 thread accessing the PhysX API (i.e. it calls simulate(), fetchResults() and is the thread that reads and modifies actor and scene data), then you don’t actually need to lock the scene to ensure thread safety when calling the PhysX API. In the checked build, there are warnings issued if PhysX detects overlapping read and write or write and write operations.
Hope this helps