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
Irrlicht in a seperate Thread
Re: Irrlicht in a seperate Thread
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.
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
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
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
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
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;
a <-> b:
t = a;
a = b;
b = t;
Re: Irrlicht in a seperate Thread
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.
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
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.
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
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.
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
Is there a problem with cache coherency? I know Intel tries to keep the caches coherent but other architectures don't.hendu wrote: pA = compare-and-swap(pB == pB, then pB = pA);
pC = compare-and-swap(pB == pB, then pB = pC);
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
No, using these operations just like any other suitable parallel construct will make sure the caches are not an issue.Is there a problem with cache coherency?
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.