synchronization issues

classic Classic list List threaded Threaded
11 messages Options
ac
Reply | Threaded
Open this post in threaded view
|

synchronization issues

ac
Hi guys,

I have encountered some performance issues in Processing that seem to be related to how the drawing thread in Processing synchronizes with JOGL. The problem manifests with choppy rendering, and it is most noticeable with programs that are GPU-bound. It is discussed at length in this thread: https://github.com/processing/processing/issues/1714 

My current understanding of the problem is as follows: Processing calls GLCanvas.display() from its main drawing thread. This thread also calculates how long the rendering of the last frame took, in order to sleep for the right amount of time so to satisfy the target framerate. GLCanvas.display() doesn't call the rendering code right away, but it triggers a callback to GLEventListener.display() (am I correct?). So one immediate problem is that the time interval calculated in the drawing thread for a single frame is most likely incorrect, since it only measures how long does it take to call GLCanvas.display(). Even the gl functions inside GLEventListener.display() could take a very short time to be called on the CPU, while they might take a much longer time to be executed on the CPU. An extreme example of this scenario would be a raymarching algorithm that runs entirely on the fragment shader. The CPU code simply consists in drawing one rectangle, so its execution time is negligible.

I have been trying to figure out how to properly synchronize the display requests from Processing so there is no stuttering, but haven't been successful so far. The only solution I found so far was to call glFinish() at the end of GLEventListener.display(), but the use of glFinish() is in general not recommended.

Any ideas or suggestions?
Andres
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

gouessej
Administrator
Hi

Having a lot of choices, a rich ecosystem, is something fine but it means that basically all developers who implement some backends in 3D engines and middle level APIs will have the same problems than me. It would be fine if everybody respected the same paradigms. Ardor3D has the most reliable JOGL backend. I can look at your code.
Julien Gouesse | Personal blog | Website
ac
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

ac
Ok, here there is some self-contained code that hopefully makes the problem more clear. I'm basically rendering this raymarching effect from shadertoy: https://www.shadertoy.com/view/MdX3Rr

If I use an Animator object to drive the rendering loop, I get the same level of smoothness as in shadertoy: http://pastebin.com/1Jwh9ZL0

But if I manually call canvas.display() from the drawing loop of the app, the playback is very choppy: http://pastebin.com/HpsgKQfn

Of course, running it on a very fast GPU could make the stuttering to disappear, as a reference I'm testing on a AMD Radeon HD 6490M.

Strangely enough, both apps report the same framerate (around 12~14 fps for my test system).

The vertex and fragment shaders are the same for both programs: http://pastebin.com/TKhmkUbk, http://pastebin.com/QJkzYpsz

So I guess that the method I'm using to manually drive the rendering loop is incorrect, but cannot realize why. Any ideas/suggestions will be greatly appreciated.

Andres
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

gouessej
Administrator
ac wrote
But if I manually call canvas.display() from the drawing loop of the app, the playback is very choppy: http://pastebin.com/HpsgKQfn
You can use the FrameHandler framework of Ardor3D as an example if you really want to call canvas.display() directly without using any animator, look at the sub-project "ardor3d-jogl", especially the classes JoglNewtWindow, JoglCanvasRenderer and maybe JoglRenderer. You'll notice it contains some weird code to support some extremely crappy drivers (Intel, under Windows).
Julien Gouesse | Personal blog | Website
ac
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

ac
Great, thanks for the lead. I will look at the classes you mentioned and see if I can solve the rendering issues.
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

gouessej
Administrator
You're welcome. You should just use GLWindow.invoke(true,GLRunnable) to put your OpenGL stuff into the queue without using glFinish and it should work, that's the main idea.
Julien Gouesse | Personal blog | Website
ac
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

ac
Hello gouessej,

I followed your suggestion of using (GLCanvas/GLWindow).invoke(), and in order to do so I looked at the rendering framework in Ardor3D (FrameHandler, JoglCanvasRenderer, JoglRenderer, etc).

I put the code I wrote so far in the following test program (which is part of a self-contained Eclipse project on github where I started committing this and other jogl-related "test cases"):

https://github.com/codeanticode/jogl2-tests/blob/master/src/test/applet/InvApplet.java

and although it seems that I'm close to solve the problem, I'm currently stumped with an issue that maybe you can help me with. I get the animation thread running without any errors, using either AWT or NEWT, and I'm able to execute my custom OpenGL code through the invoke() method. On Windows 7, the output appears without any glitches and running smoothly (I tried 2.0-RC11 and 2.0-b982).

However, there is something strange happening on OSX (running 10.8.3). The frame starts by clearing the screen with a red color, and then proceeds to enable the shader program that does all the work (I'm still using the raymarching effect I mentioned at the beginning). However, the output of the shader is never displayed, only a solid red screen as it results from the glClear() call. But if in the initGL() function I replace the lines:

applet.setLayout(new BorderLayout());
applet.add(newtCanvas, BorderLayout.CENTER);

with:

newtWindow.setSize(applet.width, applet.height);
newtWindow.setVisible(true);

then I see a separate NEWT window showing the ongoing shader rendering correctly. I believe I understand why is this happening: the newt windows doesn't get attached to the applet object, so it is all by itself. I though that maybe the problem is the unusual applet->frame structure of this program, but if I attach the newtCanvas to the frame instead, I still get the red screen.

I'm perplexed by the fact that the effect of the glClear() call is visible, but the rest of the frame rendering is not, unless the NEWT window is detached from the applet/frame. Since I'm not getting any error messages, and tried several combinations of things already (AWT vs NEWT, different GLCapabilities options, etc) but always with the same result, I'm not sure how to proceed at this point. Any help will be immensely appreciated!

Andres

Pd: I also starting working on an equivalent test program that uses the FPSAnimator instead (https://github.com/codeanticode/jogl2-tests/blob/master/src/test/applet/AnimApplet.java), but so far I cannot make it work (the screen is not updated), but I will ask about this issue on a separate post.
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

gouessej
Administrator
Hi

The problem is that I have no extremely recent Mac to test. Maybe you have discovered a bug in NEWT this time, I'm not sure. I would feel better if Sven could confirm.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

Sven Gothel
Administrator
In reply to this post by ac
Thank you Andres,

I will have a look at your test case later this week when I am back.

I hope this is not another OSX 10.8 issue, since I only have an OSX 10.7 machine here.
Ofc .. there shall be no choppy effects etc.
ac
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

ac
Hello Sven, thanks for the follow up.

Just to clarify what is the issue as this thread is becoming fairly long: I'm trying to use the invoke() method to execute my GL code in a correct manner. My test case is the following:

https://github.com/codeanticode/jogl2-tests/blob/master/src/test/applet/InvApplet.java

It works without problem on Windows (no stuttering, Java 6 or 7, AWT or NEWT), but on OSX (10.8.3, either Java 6 or 7, AWT or NEWT) it appears that it executes the frame only "partially", since only the color from the glClear() call is visible but not the shader output that happens right afterwards.

As I mentioned in the other thread about the FPSAnimator, I'm conducting all these tests to finally get the JOGL rendering working correctly in Processing, but I wonder if the Frame/Applet structure is causing some fundamental issues with JOGL, at least on OSX.
ac
Reply | Threaded
Open this post in threaded view
|

Re: synchronization issues

ac
In reply to this post by Sven Gothel
The issue is reproducible across different machines running OSX 10.6, 10.7 and 10.8, so I just opened a bug for it:

https://jogamp.org/bugzilla/show_bug.cgi?id=735