Page 1 of 1

Irrlicht in a seperate Thread

Posted: Tue Jun 05, 2012 2:57 pm
by Roland
Dear Forum,

I am new to Irrlicht and I dont want to make a game. Let me explain a bit.

I am working on a fairly complicated simulation and I want to use Irrlicht to visualise the internal variables. The graphics might get more complex in the future, but at moment it is simply some (~10000) circles, dots and lines running around on a 2D surface. I do not want to use software rendering, nor do I want to write the rendering engine my self. So I came to Irrlicht, even though our simulation has nothing to do with games.

The simulation I am going to develop needs to run in its own speed and can not be determaned by the rendering of Irrlicht. Irrlicht should just be used to handle the GUI to set parameters for the simulation and it should handle the graphical representation of the simulation. That basically meens I need Irrlicht to run in a seperate thread, best would be to have a fixed framerate of something like 60 fps or so.

The tutorials of Irrlicht are not very helpful for this task. They either use the rendering loop and the time between the individual loops to handle animations, or they use animated meshs. Neither works for me.

If you want to think in terms of games, I want to have a game engine with a world simulation asynchronous to the graphics output (which seems to be the case in most games anyway). I have looked for a tutorial or an example of Irrlicht, running in a seperate thread, but I have not found one yet. Is there something useful?

Best regards,
Roland

Re: Irrlicht in a seperate Thread

Posted: Tue Jun 05, 2012 7:27 pm
by hendu
While in the usual case people want to draw or load from more than one thread at once, your case would have one (or more) threads simulating and one drawing using the current state, which is completely doable.

You'd just need a good way to sync the snapshot for each frame. Perhaps a third thread taking snapshots, to avoid stalling the simulation?
With a setup like that, you could fairly easily get an initial setup where the irrlicht thread simply draws each primitive from scratch based on the snapshot. With that working, you could then work on speed if it does not reach satisfactory fps.

Though, I would recommend an accelerated 2d library instead of irrlicht; one that comes with ready primitives like circles.

Re: Irrlicht in a seperate Thread

Posted: Wed Jun 06, 2012 7:14 am
by Roland
Thnx, yeah, after sleeping it over one night, I think its much less a problem than I thought. For the data that needs to be visualized, I use a tripple-buffer. Lets say for simplicity struct Data A, B, C and a pointer pA = &A, pB = &B, pC = &C to each of them. The simulator writes into pA, when its done it flips A and B: pA <-> pB. so that pA points to B and pB points to A. When ever irrlicht wants to draw something, it first flips pB and pC and draws only using the pC pointer. That way, only the pointer flipping operation has to be mutual exclusive for the threads, which is fast. I guess, I can just use a boost::thread for the GUI and be done with it.

As for the choice of the drawing engine, the scene to be drawn is going to be in 3D later anyway. The 2D version is just for testing the simulator on a basic level. Irrlicht does not provide native circles, but it provides polygones with 100 edges, which is close enough ;-)

Cheers,
Roland

Re: Irrlicht in a seperate Thread

Posted: Wed Jun 06, 2012 9:18 am
by hendu
For those pointer writes and reads I'd use atomic operations instead of a mutex, should be a bit faster ;)

Re: Irrlicht in a seperate Thread

Posted: Wed Jun 06, 2012 12:12 pm
by Roland
Nice try, but exchanging 2 variables cant be done in one atomic operation (unless I missed some major improvements in computer technology ;-) )
a <-> b:

t = a;
a = b;
b = t;

Re: Irrlicht in a seperate Thread

Posted: Wed Jun 06, 2012 5:42 pm
by hendu
It doesn't have to be? It's quite enough for each assignment on their own to be atomic, since the other end is not in a hurry.

The compare-and-swap operation atomically writes the new value and returns the old value. So if the irr thread uses it to write to pB, the simulator has no conflict when it atomically flips pA to pB. It works because the irrlicht thread is in no rush to get the old pB value to pC, it can happen at its leisure.

Re: Irrlicht in a seperate Thread

Posted: Thu Jun 07, 2012 8:05 am
by Roland
The problem arises if both threads swap the variables simultaniously.

Lets say its like that:
pA <-> pB: t = pA; pA = pB; pB = t;
pC <-> pB: s = pC; pC = pB; pB = s;

If the operations occur in this order:

t = pA;
pA = pB;
s = pC;
pC = pB;
pB = s;
pB = t;

pA and pC point to the same object, which is not allowed.

Re: Irrlicht in a seperate Thread

Posted: Thu Jun 07, 2012 9:50 am
by hendu
Not if you use the CAS:

pA = compare-and-swap(pB == pB, then pB = pA);
pC = compare-and-swap(pB == pB, then pB = pC);

The write to pB is atomic, the writes to pA and pC are not. It's OK, since the only contention is about pB.

That is, they do the write at the same time as the read, not by using a temp variable in more than one step. (I suck at explaining this; internally it's of course using a temp variable, but with memory barriers around it. And it of course returns the old value correctly.)

--

That is the point of atomics, the second CAS cannot start before the first is completed.

Re: Irrlicht in a seperate Thread

Posted: Thu Jun 07, 2012 1:21 pm
by mongoose7
hendu wrote: pA = compare-and-swap(pB == pB, then pB = pA);
pC = compare-and-swap(pB == pB, then pB = pC);
Is there a problem with cache coherency? I know Intel tries to keep the caches coherent but other architectures don't.
What happens if the second compare-and-swap fails?

Or are we talking about a library here, like Boost, forexample. In that case, I can only say that to implement this requires a mutex so you might as well do it this way yourself.

Re: Irrlicht in a seperate Thread

Posted: Thu Jun 07, 2012 3:32 pm
by hendu
Is there a problem with cache coherency?
No, using these operations just like any other suitable parallel construct will make sure the caches are not an issue.

These are compiler (/exposed cpu) primitives, not library functions. GCC and VS both have them, but with different names.

As such they can't fail any more than any other normal instruction. Sure accessing memory that doesn't belong to you will segfault etc.
If they happen at the same time, one will block until the other is done.