Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing progress of gl calculations in qt

I have a process that is doing some heavy maths with gl rather than the cpu (gl/gpu is so far doing approximatly 100x faster than cpu) but still it is about a minute for usual problem sizes to be ready, so I wanted a nice progress bar to know how long it will take.

So I set up my classes to inherit from QObject and have a signal currentProgress(int) that is emitted every once in a while. Unfortunately my program freezes during the calculation so no progress is visible. I found the solution in calling QCoreApplication::processEvents() which gave me another problem. During this call a repaint of the whole window is triggered which results in my calculation being called in an infinite recursion, because it is itself triggered by the paint event.

Now all this problems are signals that tell my programming intuition slot that I probably misdesigned something, so I ask you what is the default way to have a refreshing progress bar in qt?

Also note: When I want to push the calculation into another thread I probably need to create a new GL context or at least move the existing one over. So if that is the way to go, might someone explain to me how to achieve this in qt?

EDIT

To make things more clear I am not drawing to the QGLWidget but using a FBO. Probably it is the best to use an own context for the calculations but I don't know if it is the right way to go.

New Information

So I tried to follow your advice but stumbled upon a problem. A QGLContext seems to must have been connected to a screen/gui object so I cannot create one offscreen.

Further I cannot make the QGLWidget current in the other threads. It returns the error QGLContext::makeCurrent(): Failed. Further all entries I read about that were people with the same problem like me: They wanted to do renderings in another thread and did not find a solution.

like image 774
Nobody moving away from SE Avatar asked Aug 23 '11 20:08

Nobody moving away from SE


3 Answers

During this call a repaint of the whole window is triggered which results in my calculation being called in an infinite recursion, because it is itself triggered by the paint event.

Then you should not be triggering your calculations in the paint event. If the window is the OpenGL window (ie: the GPGPU stuff renders to the window), then you should hide it for the duration of the computations. If it's not the OpenGL window, then refreshing it should not be provoking the computations.

Unless you are using OpenGL to actually draw something, you should be using an off-screen render target. Basically, you create a GL window, then create a new context that shares objects with that using WGL_ARB_pbuffers (or the GLX equivalent, depending on your GUI system). This is an off-screen render target. Then you destroy the original window.

As for threading, don't forget: even if you have two GL contexts, you only have one GPU. So if you're using OpenGL to draw to a window, and OpenGL to do some computations, this may not all work out.

like image 183
Nicol Bolas Avatar answered Oct 10 '22 19:10

Nicol Bolas


A setUpdatesEnabled(false); on the painting widget may help.

like image 29
koan Avatar answered Oct 10 '22 20:10

koan


Yes putting this into a own thread is the way to go. QGLWidget provides the following member functions:

void QGLWidget::makeCurrent()
void QGLWidget::doneCurrent()

Call them from the processing thread apropriately. setUpdatesEnables(false); prevents usual signal processing to trigger a redraw.

BTW: Do I know you from the newsgroup comp.graphics.api.opengl? There's a "Nobody" active there, too. Take a look at my user profile to know who I am there.

like image 30
datenwolf Avatar answered Oct 10 '22 18:10

datenwolf