Vertex Clouds behave differently in Debug and Release

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

Re: Vertex Clouds behave differently in Debug and Release

Postby Julio Jerez » Sun Jan 06, 2019 12:53 pm

Ok I pasted the code, and the first thing I see is that you are deleting teh joint from a callback.
that's always a bad idea.

you need to make a global vector and push any object that you want to destroy in a callback.
them after the newton update returns, you iterate over the vector and delete any object that was collected during the update.
care must be taken that you do not push teh same object more than once.

however if you want to do it like the way you are doing it now,
I fixed the function that does the deletion like this.
Code: Select all
static void BreakHinge(const NewtonBody* body, dFloat timestep, int threadIndex)
{
   NewtonWorld* const world = NewtonBodyGetWorld(body);
   DemoEntityManager* const scene = (DemoEntityManager*)NewtonWorldGetUserData(world);

   static unsigned atomicLock = 0;
   if (scene->GetKeyState('1')) {
      dCustomScopeLock lock(&atomicLock);
      if (pHinge1) {
         delete pHinge1;
         pHinge1 = NULL;
      }
   }
   if (scene->GetKeyState('2')) {
      dCustomScopeLock lock(&atomicLock);
      if (pHinge[0]) {
         delete pHinge[0];
         pHinge[0] = NULL;
         delete pHinge[1];
         pHinge[1] = NULL;
         delete pHinge[2];
         pHinge[2] = NULL;
      }
   }
}

basically you need to add an atomic spinlock so that onle one thread hit the same spot at a time.
That fixes the crash with multicore.

The problem with the zero dof, is related to the what I mentioned first. by deleting the the joint in the middle of an update, you are altering the joint topology.
the toplogy is only checked on the beginning of each update, if you delete a joint the unpredictable thing happens.

that said for this test case I made this change from this
Code: Select all
   DG_TRACKTIME(__FUNCTION__);
   UpdateSkeletons();
   UpdateBroadphase(timestep);

   UpdateDynamics (timestep);


to this
Code: Select all
   DG_TRACKTIME(__FUNCTION__);
   UpdateBroadphase(timestep);
   UpdateSkeletons();

   UpdateDynamics (timestep);


and is solve this particular case, but all it takes is some one deleting an object from a different callback and will break again, the proper fix in on the client side by garbage collect objects to be destroyed and actually delete them after the newton update returns.

sync to get the fix, but I will revert the change in the engine later, this is the kind of change that can cause bad side effects that can break other person code.
Julio Jerez
Moderator
Moderator
 
Posts: 11046
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Vertex Clouds behave differently in Debug and Release

Postby Julio Jerez » Sun Jan 06, 2019 1:11 pm

there is still another bug, I am looking at it.
Julio Jerez
Moderator
Moderator
 
Posts: 11046
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Vertex Clouds behave differently in Debug and Release

Postby Julio Jerez » Sun Jan 06, 2019 2:18 pm

As I suspected that little trick caused big problems, so I added the proper fix.
look at the function
Code: Select all
static void BreakHinge(const NewtonBody* body, dFloat timestep, int threadIndex)


also check out hwo the post update call back is set so that the app get the proper call whe is safe to delete stuff. look this code in teh demo
Code: Select all
   // chain the call back so that we cal delete object after the newton update
   gParentCallback = NewtonGetPostUpdateCallback(world);
   NewtonSetPostUpdateCallback(world, GarbageCollectJoints);


basically it use a map to collect joint selected for deletion and in the post update it simply iterate over the map deleting every joint.
if you need to do bodies is the same thing with a body map.

now wit this is work every time without problems.

BTW: I know is a simple thing, but it is really cool seeing how the stage get detached, few year ago Hollywood paid big buck for that kind of effects and now is so simple.
Julio Jerez
Moderator
Moderator
 
Posts: 11046
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Vertex Clouds behave differently in Debug and Release

Postby misho » Sun Jan 06, 2019 5:00 pm

Julio Jerez wrote:BTW: I know is a simple thing, but it is really cool seeing how the stage get detached, few year ago Hollywood paid big buck for that kind of effects and now is so simple.


My stuff is starting to look pretty "Hollywood-ish" :mrgreen:

Here is a rocket escape system in action, all under the watchful eye of Newton Dynamics: NASA SLS Launch Abort System Test
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 553
Joined: Tue May 04, 2010 10:13 am

Re: Vertex Clouds behave differently in Debug and Release

Postby misho » Mon Jan 07, 2019 8:11 pm

OK, I implemented the correct method for destroying hinges. I had to fiddle about with it because my code is structured a bit differently. Namely, my hinge is a member of the "attachpoint" struct. I have a method that calls for de-coupling on command (just like the keypress in the demo code) but since it is outside of callback, I had to label the hinge as discardable, and then process it inside callback:

(in ApplyForceAndTorqueCallback() callback)
Code: Select all
   for (int i = 0; i < ent->GetAttachPointCount(); i++)
   {
      structAttachPoint* AP = ent->GetAttachPoint(i);
      if (AP->bDiscardHinge)
      {
         AP->bDiscardHinge = false;
         bOKToApplyImpulse = true;
         dCustomScopeLock lock(&atomicLock);
         if (!garbageCollectedJoints.Find(AP->pHinge)) {
            garbageCollectedJoints.Insert(AP->pHinge, AP->pHinge);
            AP->pHinge = NULL;
         }
      }
   }


I also had to change from
Code: Select all
dMap<dCustomJoint*, dCustomJoint*> garbageCollectedJoints;

to
Code: Select all
dMap<dCustomHinge*, dCustomHinge*> garbageCollectedJoints;

because garbageCollectedJoints.Insert(); wouldn't go for it (not sure why it does in the demo code)

This works in Release, however, in Debug, I get access violation crash in:
Code: Select all
delete garbageCollectedJoints.GetRoot()->GetInfo();

Also - it works for joint count of 1, but this crash happens on joint count of 5...
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 553
Joined: Tue May 04, 2010 10:13 am

Re: Vertex Clouds behave differently in Debug and Release

Postby Julio Jerez » Mon Jan 07, 2019 8:22 pm

some how a NULL is been added to the Map. put an assert here

 if (!garbageCollectedJoints.Find(AP->pHinge)) {
dAssert (AP->pHinge);
            garbageCollectedJoints.Insert(AP->pHinge, AP->pHinge);
            AP->pHinge = NULL;
         }

and also see which one is NULL, garbageCollectedJoints.GetRoot()->
or garbageCollectedJoints.GetRoot()->()->GetInfo();
Julio Jerez
Moderator
Moderator
 
Posts: 11046
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Vertex Clouds behave differently in Debug and Release

Postby misho » Mon Jan 07, 2019 10:27 pm

Julio Jerez wrote:some how a NULL is been added to the Map.


Ah - that was me :roll: . When 2 objects share a hinge through their own attachpoints, the attachpoint hinge members both point to the same hinge. So, I was telling both attachpoints to erase the same hinge! Not sure why it passed on deleting only one hinge, but it is fixed now!
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 553
Joined: Tue May 04, 2010 10:13 am

Re: Vertex Clouds behave differently in Debug and Release

Postby Julio Jerez » Mon Jan 07, 2019 11:32 pm

Smart pointers :D
Julio Jerez
Moderator
Moderator
 
Posts: 11046
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Vertex Clouds behave differently in Debug and Release

Postby misho » Tue Jan 08, 2019 3:58 am

Ok, after restructuring some of the sample code you posted, I got it going the way I need it (I think, correct me if I'm wrong). I had to expand on the Map a bit, because I need to set off the "spring" just after the hinge is destroyed (by adding impulse), and for that I need access to hinge owner:

Code: Select all
dMap<TBEntity*, structAttachPoint*> garbageCollectedJoints
...
static unsigned atomicLock = 0;
for (int i = 0; i < ent->GetAttachPointCount(); i++)
{
   structAttachPoint* AP = ent->GetAttachPoint(i);
   if (AP->bDiscardHinge)
   {
      AP->bDiscardHinge = false;
      dCustomScopeLock lock(&atomicLock);
      if (!garbageCollectedJoints.Find(AP))
         garbageCollectedJoints.Insert(ent, AP);
   }
}
...
static void GarbageCollectJoints(const NewtonWorld* const world, dFloat timestep)
{
   if (gParentCallback) {
      gParentCallback(world, timestep);
   }
   while (garbageCollectedJoints.GetCount())
   {
      TBEntity *ent = garbageCollectedJoints.GetRoot()->GetInfo();
      structAttachPoint *AP = garbageCollectedJoints.GetRoot()->GetKey();
      ent->ApplyHingeImpulse(AP);
      if(AP->pHinge != NULL)
         delete AP->pHinge;
      AP->pHinge = NULL;
      garbageCollectedJoints.Remove(garbageCollectedJoints.GetRoot());
   }
}


So far, this works - I haven't seen any crashes. Let me know if you see any potential problems, otherwise, good to go!
Misho Katulic
CTO, FSX SpacePort
TerraBuilder
www.terrabuilder.com
misho
 
Posts: 553
Joined: Tue May 04, 2010 10:13 am

Previous

Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 1 guest