It will block in OpenGL function when using mutlithread

I create two thread and two HGLRC,Them can share list and texture(because I use wglShareLists.

Thread1 for draw the created model and have priority THREAD_PRIORITY_NORMAL

Thread2 for create the next model and have priority THREAD_PRIORITY_BELOW_NORMAL

When Thread2 finish a creating model job,Thread2 will change the model that thread1 draw,so thread1 will draw the new model

The problem is:
Sometimes,when thread2 put texture data to graphic card or get texture data from graphic card or remove some texture data,thead1 will block in some gl function for a moment,like glClear ,glViewport and so on…
I think maybe the GPU or pipeline are too busy,so

The first method I try is:
I use CCriticalSection to synchronization the two thread in order to prevent the two thread send command at the same time.
However It does not work,thread1 also block in some gl funtion sometimes.

The second method I try is:
I think that maybe there are many command reside in the command queue,When queue is full,the next command will waiting for a moment to let graphic card run these command.
So besides the first method,I add glFinish everywhere to make sure the command before call glFinish will send to graphic card then the next command will be sent after calling glFinish.
However It does not work,thread1 also block in some gl funtion sometimes.

The second method I try is:
I doubt glFinish do nothing,so I replace glFinish by the code below:

glFlush();
GLuint querie;
glGenQueriesARB(1,&querie);
glBeginQueryARB(GL_SAMPLES_PASSED_ARB,querie);
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
GLint available=1;
glGetQueryObjectivARB(querie,GL_QUERY_RESULT_AVAILABLE_ARB,&available);
while (!available)
{
Sleep(1);
glGetQueryObjectivARB(querie,GL_QUERY_RESULT_AVAILABLE_ARB,&available);
}

However It does not work,thread1 also block in some gl funtion sometimes.But it is better than before,the times of block are fewer and the time of block is shorter.

Another situation is that ATI chip is more seriously than nVidia chip.
The situation of block always happen in ATI chip no matter the level of chip
The situation of block seldom happen in high level nVidia chip,even if it happened,the time of block is very short.It usually happened in low level nVidia chip.

The problem have confused me for three month.
I have tried many mothods,but …

Can anyone help me ?

Don’t use glFinish as this would block until all GL complete.
Are you doing the rendering in a infinite loop?

Yes,I doing the rendering in a infinite loop.

I mean that It will block in some OpenGL function,the function is not glFinish.

I know that glFinish will block until all GL complete.

If you have 2 windows, each running GL in an infinite loop, then you need a card that can support this. Gaming cards are not good. 3DLabs cards are probably best.

What happens when both threads are runing under THREAD_PRIORITY_NORMAL?

I only have one window and only the first thread running GL in an infinite loop,the second thread create model.when the model creating finished,I’ll change the model ,then the first thread use the newer model to render.
When the second thread put texture data to graphic card,the first thread will block in some gl function,like glClear,and so on…
I also use CCriticalSection to synchronization the two thread in order to prevent the two thread send command at the same time,but it does not work.

If I run both threads under THREAD_PRIORITY_NORMAL,The first thread will not smoth,when thread2 are running,the frames per second will from 25 Frames/Sec down to 10 or 8 Frames/sec

What if when the second thread put texture data to graphic card, it will be runing under THREAD_PRIORITY_NORMAL?

E.g. second thread:

SetThreadPriority (GetCurrentThred (), THREAD_PRIORITY_NORMAL);
put texture data to graphic card AND your debug GDI output (or without)
SetThreadPriority (GetCurrentThred (), THREAD_PRIORITY_BELOW_NORMAL);
… (whithout GDI prints)

It is from what maybe second thread is running very slowly and first thread in this time is spin lock waiting (100 % CPU load).

I use CCriticalSection to synchronization the two thread in order to prevent the two thread send command at the same time,If It is from what second thread is running very slowly ,the first thread will lock in CCriticalSection.Lock(),but it lock in glClear or some gl functions.

I have divide a big texture data into many small texture data,If I sleep a moment(maybe sleep(1)) when after put each texture data,The situation of block will seldom happen.

while(!Completed)
{
[Do update texture data]
Sleep(1)
glFinish()
}

The situation of block always happen in ATI chip no matter the level of chip

The situation of block seldom happen in high level nVidia chip,even if it happened,the time of block is very short.It usually happened in low level nVidia chip.

I think that nVidia is good in design of pipleline,glFinish can’t guarantee that command have been run,so many command stay in pipleline.If I sleep(1),graphic card will have time to run these command.
If it is true,how to make sure that the command befor I send have been run ?

Do you use this principle?:

THREAD 1:

CS.Lock
glClear or some which lock a trehad 1.
CS.Unlock

CS.Lock
glSome
CS.Unlock

THREAD 2:

CS.Lock
[Do update texture data]
glFlush
Sleep
CS.Unlock

A CS is same to threads 1 and 2;

Maybe does glSome implicitly call the glFinish? As in SwapBuffers. If so then glSome lock the himself thread1 on (necessary_sleep_time - thread2_sleep_time). In my opinion it is working. But bad that it is fuzzy realizations (some gl functions).
Are little lags is native cost of modify model when at thread1 add the run of thread2 in moment [Do update texture data].


[If I sleep(1),graphic card will have time to run these command.]
And to my conclusion it is right. A glFinish always guaraned what command have been run and thus to make sure. (I’m sure just for ATI).

No,I use this principle:

THREAD 1://For draw model

while(run)
{
CS.Lock
glClear//Often block on here

[Draw Model]
SwapBuffers
MyFinish()
CS.Unlock
//avoid draw too many times per seconds,so sleep
Sleep(TimeInterval};
}

THREAD 2://For generate model

CS.Lock
some gl function
MyFinish()
CS.Lock

CS.Lock
[Do update texture data]
MyFinish()
CS.Unlock

//For make sure command have been run completed
void MyFinish()
{
switch(fence_type)//diference GPU,use difference method
{
case 2://NVidia that have GL_NV_fence
{
glFlush();
GLuint fence=0;
glGenFencesNV(1,&fence);
glSetFenceNV(fence,GL_ALL_COMPLETED_NV);
glFinishFenceNV(fence);
glDeleteFencesNV(1,&fence);
}
break;
case 1://GPU that have Occlusion Culling
{
glFlush();
GLuint querie;
glGenQueriesARB(1,&querie);
glBeginQueryARB(GL_SAMPLES_PASSED_ARB,querie);
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
GLint available=1;
glGetQueryObjectivARB(querie,GL_QUERY_RESULT_AVAILABLE_ARB,&available);
while (!available)
{
Sleep(1);
glGetQueryObjectivARB(querie,GL_QUERY_RESULT_AVAILABLE_ARB,&available);
}
}
break;
case 0://else above
default:
glFinish();
break;
}
}

ans CS is same to threads 1 and 2.

I also have used
void MyFinish()
{
glFinish();
}

It also block in the first gl function of thread1 - glClear sometime,maybe 0.5 second or 5 seconds or more seconds.

In my opinion, you can solve that thus:

THREAD 1://For draw model

while(run)
{
CS.Lock
glClear//Often block on here

[Draw Model]
glFlush
CS.Unlock
Sleep // wait for the GPU pipeline and free the CPU for thread2
SwapBuffers
//avoid draw too many times per seconds,so sleep
Sleep(TimeInterval};
}

THREAD 2://For generate model

CS.Lock
some gl function
glFlush
// maybe sleep for the CPU economy
CS.Unlock

CS.Lock
[Do update texture data]
glFlush
// maybe sleep for the CPU economy
CS.Unlock

It is wihout a glFinish.

How long the sleep should sleep ?
If too long,The ap will run slowly.

It is the X :slight_smile:

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.