PDA

View Full Version : multithreading and multiple contexts



lobbel
07-02-2010, 01:10 AM
I've got a question about multiple contexts in multiple threads. For instance if thread 1 is working it needs to disable the context in thread 2 and make the context in thread 1 current because you cant steal the contexts from another thread.

So my questions is when thread 1 is running and is drawing some stuff and thread 2 is used to load some stuff meanwhile do I have to synchronize them ?

Let's assume the following pseudo code. The position -->x
can be a position where thread2 starts its work.

thread1


while(1)
{
context2->disable()
context1->makeCurrent()
glClear(...);
-->x
vbo->draw();
SwapBuffers(hdc)
}


thread2


{
sharecontexts()
context1->disable()
context2->makeCurrent()
load sume stuff
}


regards,
lobbel

eile
07-02-2010, 02:53 AM
The current context is per thread, that is you have to make context1 not current in thread 1 in position '-->x' instead of in thread2:

thread1:
ctx2->makeCurrent
render
makeCurrentNone
(sync)

thread2:
(sync)
ctx2->makeCurrent
render
makeCurrentNone

lobbel
07-02-2010, 03:29 AM
Hi,
thanks for the answer. But I use two contexts. Each Thread has
its own context. I want to use the second thread for loading etc.
Or did you mean ctx1 in thread1 instead of ctx2 ?

regards,
lobbel

mfort
07-02-2010, 07:11 AM
- Avoid context switches. It means each thread should have one context.

- Do not bet on better performance with 2nd thread doing background load. It only makes the app more complicated and it needs synchronization (ARB_sync).

- use asynchronous API instead (PBO, PBO, ...)

lobbel
07-02-2010, 07:29 AM
Ahoj pane,

thanks for answering and the hints. So I'm not using the
loadthread anylonger. I just have the thread for drawing
and doing the loading there before drawing. But I have big latencies. I use a stl::queue that is sync with semaphores.
So I write user inputs like mousebutton or mousemove into the
queue and the read them in the other thread and process these
commands. It works, but when I rotate just a simple cube with the
mouse the latencies are that high that I can watch how the cube
is rotating slowly while I'm not moving the mouse anymore -> some commands are still in the queue.
What would you suggest to use sending the user inputs to the opengl thread ? To summerize, it works with the queue, but with
big latencies.

cus bus bambus
lobbel

carsten neumann
07-02-2010, 07:46 AM
Are you taking only one element out of the queue each frame or do you process all available commands?
If you do the former and generate more than one command in the time it takes to render one frame your images will lag behind the input.

mfort
07-02-2010, 07:49 AM
It works, but when I rotate just a simple cube with the
mouse the latencies are that high that I can watch how the cube
is rotating slowly while I'm not moving the mouse anymore -> some commands are still in the queue.


ahoj,
this is probably not related to OpenGL at all.
be sure you process all queued events in each iteration of opengl render. This looks like you process only one event per one OpenGL render iterations.

lobbel
07-02-2010, 09:04 AM
hi,

This looks like you process only one event per one OpenGL render iterations

Well, thats exactly what I'm doing. It's the first time to me, doing the rendering in a seperate thread. So actually I have just a while loop in the thread proc and read the messages out of the queue ( so far there are any messages in the queue).
[CODE]
while(TRUE)
{
queue->read(msg);
process(msg);

render opengl here
}
[CODE]
So, it's right. It's per iteration.

How can I solve this problem? Should I read the queued messages in a seperate thread and do the drawing only every n-millisecond in another thread ?

regards,
lobbel

regards,
lobbel

carsten neumann
07-02-2010, 09:27 AM
Should I read the queued messages in a seperate thread and do the drawing only every n-millisecond in another thread ?


You can do that, of course you need to sync the threads in some way so that when you draw you don't change your data at the same time.

A perhaps simpler approach would be to put a loop around your message processing that runs up to a certain amount of time has elapsed or the queue is empty.



while(TRUE)
{
while(time_left && queue->empty() == false)
{
queue->read(msg);
process(msg);
}

// render opengl here
}

lobbel
07-06-2010, 12:54 PM
Hello,

I've got a problem with this seperate while loop.
In debug mode it works. But in release it crashes because
of access violation. I dont understand why.
The queue(read/write/empty) is synchronized with semaphores.
so, actually i dont udnerstand why it crahes only in release mode.

regards,
lobbel

lobbel
07-06-2010, 03:58 PM
Solved,

regards,
lobbel

lobbel
07-07-2010, 08:32 AM
Hi..
Before, I sent the struct to the queue's push method
by value. So my struct was allocated on the stack locally in the
OnLButtonDown method. I didnt know that this is a problem.
Because the struct is given by value and the stl::queue manages
it self.

old


OnLButtonDown(UINT nFlags, etc....)
{
Cmdstr cmd;
cmd.flag = nFlags;
etc.

queue->push(cmd);
}


new


OnLButtonDown(UINT nFlags, etc....)
{
Cmdstr* = new Cmdstr;
cmd->flag = nFlags;
etc.

queue->push(cmd);
}

while
{
....
while
...
Cmdstr* cmd = queue.pop()
processCmd(cmd);
delete cmd;
}


Maybe I missed that point, it's better to put things on the heap
for exchanging date between threads. But actually the stl::queue
put's the things also on the heap. So I dont understand it completely.

But it works.
regards,
lobbel