Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash inside NpConstraint::updateConstants #216

Open
Elercia opened this issue Nov 27, 2023 · 1 comment
Open

Crash inside NpConstraint::updateConstants #216

Elercia opened this issue Nov 27, 2023 · 1 comment
Assignees

Comments

@Elercia
Copy link

Elercia commented Nov 27, 2023

Library and Version

PhysX v5.3.0 (last commit on trunk)

Operating System

Windows 10

Steps to Trigger Behavior

  1. Create a RigidBody & a constraint (like a joint)
  2. Call immediate::PxCreateJointConstraintsWithShaders
  3. Release the constraint
  4. Simulate

A new constraint will be marked dirty (flag ConstraintCore::mIsDirty ) and will be registered inside NpScene::mDirtyConstraints.
Both array and flag are cleaned inside a simulation (NpScene::updateDirtyShaders).

The call to immediate::PxCreateJointConstraintsWithShaders will trigger a call to PxConstraintAdapter::getData causing the constraint to be marked as clean but not removed from the dirty array of the scene.

Code Snippet to Reproduce Behavior

There might be some useless code here. But from HelloWorldSnippet inside InitPhysics:

// Step 1 
PxRigidDynamic* spherePhysic = PxCreateDynamic( *gPhysics, PxTransform( 0.f, 0.f, 0.f ), PxSphereGeometry( 3.0f ), *gMaterial, 1.f );
gScene->addActor( *spherePhysic );

PxFixedJoint* joint = PxFixedJointCreate( *gPhysics, spherePhysic, PxTransform( PxIDENTITY::PxIdentity ), NULL, PxTransform( PxIDENTITY::PxIdentity ) );

// Step 2
{
	immediate::PxRigidBodyData rigidBodyData;
	rigidBodyData.invMass = spherePhysic->getInvMass();
	rigidBodyData.invInertia = spherePhysic->getMassSpaceInvInertiaTensor();
	rigidBodyData.maxDepenetrationVelocity = spherePhysic->getMaxDepenetrationVelocity();
	rigidBodyData.maxContactImpulse = spherePhysic->getMaxContactImpulse();
	rigidBodyData.linearDamping = spherePhysic->getLinearDamping();
	rigidBodyData.angularDamping = spherePhysic->getAngularDamping();
	rigidBodyData.maxLinearVelocitySq = 100.f * 100.f;
	rigidBodyData.maxAngularVelocitySq = spherePhysic->getMaxAngularVelocity() * spherePhysic->getMaxAngularVelocity();

	PX_ALIGN_PREFIX(16) PxSolverBody	 oSolverBody;
	PxSolverBodyData solverBodyData;

	PxSolverBodyData solverStaticData;
	physx::immediate::PxConstructStaticSolverBody( PxTransform( PxIdentity ), solverStaticData );

	PX_ALIGN_PREFIX( 16 ) PxSolverBody solverStatic;
	memset( &solverStatic, 0, sizeof( PxSolverBody ) );

	PxConstraintBatchHeader constraintBatchHeader;
	constraintBatchHeader.startIndex = 0;
	constraintBatchHeader.stride = 1;
	constraintBatchHeader.constraintType = PxSolverConstraintDesc::eJOINT_CONSTRAINT; // Not used, will be overwritten in PxCreateJointConstraints as our constraint is not batchable

	PxConstraint* constraint = joint->getConstraint();
	PxSolverConstraintDesc solverConstraintDesc;
	memset( &solverConstraintDesc,0, sizeof( PxSolverConstraintDesc ) );
	solverConstraintDesc.bodyA = &oSolverBody;
	solverConstraintDesc.bodyB = &solverStatic;
	solverConstraintDesc.bodyADataIndex = 0;
	solverConstraintDesc.bodyBDataIndex = 1; // Won't be used
	solverConstraintDesc.linkIndexA = PxSolverConstraintDesc::RIGID_BODY;
	solverConstraintDesc.linkIndexB = PxSolverConstraintDesc::RIGID_BODY;
	solverConstraintDesc.constraint = reinterpret_cast<PxU8*>( constraint );

	PxSolverConstraintPrepDesc solverConstraintPrepDesc;
	memset( &solverConstraintPrepDesc,0, sizeof( PxSolverConstraintPrepDesc ) );
	solverConstraintPrepDesc.body0 = solverConstraintDesc.bodyA;
	solverConstraintPrepDesc.body1 = solverConstraintDesc.bodyB;
	solverConstraintPrepDesc.data0 = &solverBodyData;
	solverConstraintPrepDesc.data1 = &solverStaticData;
	solverConstraintPrepDesc.bodyFrame1 = solverStaticData.body2World;
	solverConstraintPrepDesc.bodyState0 = PxSolverConstraintPrepDescBase::eDYNAMIC_BODY;
	solverConstraintPrepDesc.bodyState1 = PxSolverConstraintPrepDescBase::eSTATIC_BODY;
	solverConstraintPrepDesc.desc = &solverConstraintDesc;
	solverConstraintPrepDesc.invMassScales.angular0 = solverConstraintPrepDesc.invMassScales.angular1 = solverConstraintPrepDesc.invMassScales.linear0 =
		solverConstraintPrepDesc.invMassScales.linear1 = 1.f;
	solverConstraintPrepDesc.writeback = NULL;
	constraint->getBreakForce( solverConstraintPrepDesc.linBreakForce, solverConstraintPrepDesc.angBreakForce );
	solverConstraintPrepDesc.minResponseThreshold = constraint->getMinResponseThreshold();
	solverConstraintPrepDesc.disablePreprocessing = !!( constraint->getFlags() & PxConstraintFlag::eDISABLE_PREPROCESSING );
	solverConstraintPrepDesc.improvedSlerp = !!( constraint->getFlags() & PxConstraintFlag::eIMPROVED_SLERP );
	solverConstraintPrepDesc.driveLimitsAreForces = !!( constraint->getFlags() & PxConstraintFlag::eDRIVE_LIMITS_ARE_FORCES );

	physx::SnippetImmUtils::TestConstraintAllocator allocator;

	rigidBodyData.linearVelocity = spherePhysic->getLinearVelocity();
	rigidBodyData.angularVelocity = spherePhysic->getAngularVelocity();
	rigidBodyData.body2World = spherePhysic->getGlobalPose();
	immediate::PxConstructSolverBodies( &rigidBodyData, &solverBodyData, 1, PxVec3( 0.f, 0.f, 0.f ), 0.16f );

	solverConstraintPrepDesc.bodyFrame0 = solverBodyData.body2World;
	PxConstraint* oConstraintArray[1] = { constraint };
	immediate::PxCreateJointConstraintsWithShaders( &constraintBatchHeader, 1, oConstraintArray, &solverConstraintPrepDesc, allocator, 0.16f,
		1.f / 0.16f );
}

// Step 3
joint->release();
spherePhysic->release();

// Step 4
gScene->simulate( 1.0f / 60.0f );
gScene->fetchResults( true );

Expected Behavior

There is 2 options here.

  • Remove the NpConstraint::markClean inside PxConstraintAdapter::getData. This will probably cause a 2nd call to prepareData in the simulation.
  • Remove from NpScene::mDirtyConstraints as we lower the dirty flag. Doing this will result in a different "cleaning" code. This will not make all the calls that are inside NpConstraint::updateConstants (PVD update, and PxsSimulationController::updateJoint).

We are not actually sure of what option is the best. Is our usage of PxCreateJointConstraintsWithShaders right (in term of API calls)?

Actual Behavior

Dirty bool and array are not in sync

@preist-nvidia
Copy link
Collaborator

Thank you for the great report!

Internal tracking: PX-4630

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants