OpenGLComponent flickering animation


#1

I am trying to use OpenGLComponent for 2D animation with some physics simulation using box2D. As continuousRepainting is set to true in OpenGLComponent constructor and

nativeContext->setSwapInterval (1) ;

is also called somewhere inside Juce stuff (which should enable vertical sync), so I expected that my render() function would be called approximately at 60fps.

So I placed my box2D computations inside the render() function. It doesn't take much time (less than 1ms according to my time measurements). I am using std::chrono::high_resolution_clock for getting actual timestep for box2D world step.

The problem is that my animation jerks every 1-2sec. Jerks are quite noticeable on Linux and Windows and much less noticeable on MacOSX but still present.

I also tried to do box2D calculations in HighResolutionTimer callback with timer interval set to 10ms and to use render() only for rendering, which seems to be more appropriate. Big jerks have disappeared, but the animation is flickering continuously.

What am I doing wrong?


#2

What about something like the juce demo 3D teapot or its box2D demo?


#3

3D teapot demo also has these jerks.

Box2d demo looks smooth, but it doesn't use OpenGL.


#4

What of the strategies is at least more correct?

To do calculations in render(), or to do it regularly using HighResolutionTimer?


#5

Do it in render! Absolutely don't try using the GL from your own thread. (That's not even possible on some platforms like Android)

Haven't seen any glitching on our devices, but if this is Windows then you'll get a lot of variation between drivers, CPUs, OS versions etc. If you can profile it and point to the place that's causing issues on your machine then we might be able to figure out a way to improve it. 


#6

I have the same trouble with flickering! Juce Demo has little bit flickering on Mac OSX, Android and Win platform. I want to use Juce in graphic design, but I don't know what I have to do to avoid this problem.


#7

No such problems on our devices here! Are you running on an slower machine?

Or if the glitching is periodic, perhaps there's something happening every second which is interrupting it.. Hard to fix a problem that we can't reproduce though!


#8

My Android platform: Samsung Galaxy Tab3 lite SM-T113, Android 4.4.4. PС platform:  Intel i5-3210M-2.5GHz RAM:6,00Gb,Win 8.1  - they are not so slow. The flicker effect is insignificant, so probably you can't notice it. For opengl teapot you should gaze at it during 1minute. For some game engines (for example Ogre) the flickering is absent.


#9

Well, I think I don't use GL from any thread other than rendering one while using HighResolutionTimer. In timer callback only box2D world step calculation and some variables updates are done. OpenGL commands are called only in render() function, and render() should pick up the most recent calculation results and draw them. Is this not correct?

If timer interval is small enough, time discrepancy between calculation time and display time should be not more than the timer interval.

As to profiling, I'm not sure what to profile, but on Linux I have the following perf command output (for more than 0.5% overhead):

# Overhead          Command                         Shared Object  Symbol
# ........  ...............  ....................................  ......
#
    31.31%       Juce Timer  /usr/lib/fglrx/dri/fglrx_dri.so       [.] 0x00000001581847
    11.82%       Juce Timer  /usr/lib/libfreetype.so.6.3.22        [.] 0x0000000006100a
     7.62%       Juce Timer  /lib/libc-2.11.1.so                   [.] 0x00000000083ee4
     3.21%       Juce Timer  /lib/libc-2.11.1.so                   [.] memcpy
     2.16%       Juce Timer  /lib/libc-2.11.1.so                   [.] memset
     1.91%       Juce Timer  ./Builds/LinuxMakefile/build/Fly1     [.] juce::Flipper<juce::PixelRGB>::flip(juce::HeapBlock<juce::PixelARGB, false>&, unsigned char const*, int, int, int)
     1.73%       Juce Timer  /lib/libc-2.11.1.so                   [.] 0x00000000078982
     1.36%       Juce Timer  /lib/ld-2.11.1.so                     [.] 0x00000000009204
     1.24%       Juce Timer  [kernel]                              [k] __phys_addr
     0.93%       Juce Timer  ./Builds/LinuxMakefile/build/Fly1     [.] void juce::PixelARGB::set<juce::PixelRGB>(juce::PixelRGB const&)
     0.92%       Juce Timer  [kernel]                              [k] clear_page_c
     0.81%       Juce Timer  [kernel]                              [k] free_pcppages_bulk
     0.77%       Juce Timer  [kernel]                              [k] _ZNK21CMMPoolAsicAccessible16getAlignedOffsetEmmbmRK13CMM_ALIGNMENT    [fglrx]
     0.73%       Juce Timer  [kernel]                              [k] __free_pages
     0.67%       Juce Timer  [kernel]                              [k] free_hot_cold_page
     0.66%       Juce Timer  [kernel]                              [k] __ticket_spin_lock
     0.65%       Juce Timer  ./Builds/LinuxMakefile/build/Fly1     [.] juce::PixelRGB::getNativeARGB() const
     0.63%       Juce Timer  [kernel]                              [k] lookup_address
     0.53%       Juce Timer  /lib/libc-2.11.1.so                   [.] __libc_malloc

Obviously video driver does most of the work, but the application uses only 12% of CPU and I cannot imagine why it should be disadvantaged by the system...


#10

Does the problem also occur when you are in full screen mode ?


#11

Yes it does, in full screen mode it can be slightly visible especially when "Draw 2D graphics in background" option is selected.


#12

Use of OpenGL seems very sensitive to other concurrent applications (which, after all, makes sense). In my case I had flickering occuring on a regular basis (like every second), including in Juce demo, and the prblem disappeared when I removed the clock display in the task bar of my Mac.

As you were mentioning that the flickering occurred every minute or so, you may have the same problem on your Android platform (system updating the clock display every minute...)


#13

It might be, however other openGL-based engines are free of flickering. Maybe Juce openGL apps need to set some high thread priority for correct working?


#14

You can try that yourself - just call Thread::setCurrentThreadPriority in the callback to boost it and I'd be interested to know if it helps on your machine.


#15

I had tried that (and just did it again to make sure...):​

        void renderOpenGL() override
        {
            Thread::setCurrentThreadPriority(10);

if that is what you mean. When the app runs in full screen, I have no flickering. If I let it display the time (with seconds) in the task bar, then I get a hiccup every second...

<EDIT> My config: Mac mini 2.3GHz i5 - 8GB - Intel HD Graphics 3000 512MB / O.S. 10.11.3


#16

Ok, then I have no idea what else could be tried here.. It's very odd.

And like I said, it doesn't happen on my machine, even if I enable the seconds on the OSX clock, so I'm guessing it could be a driver-specific glitch. Maybe a particular type of GPU can't task-switch very well..


#17

As I already stated, if I run the same app on a MacBookPro (with time displayed in the task bar) I don't have the problem. I even initially thought it was a 10.11 problem as the MacBookPro runs on 10.10. But it's only when I do NOT display the time on the Mac Mini (10.11.3) that the problem disappears on the Mac Mini (note that it may appear under other circumstances as well, but at least this use case is easily reproduceable for me).

The graphics card on the MacBookPro is an Nvidia GEFORCE 8600M GT 256MB. Maybe the problem is linked to the Intel card driver on the Mac Mini ?


#18

Maybe the problem is linked to the Intel card driver on the Mac Mini ?

Yes, that's what I meant in my last post. Not sure what else we could try that would make a difference..


#19

Here is a simple test project with 1000 moving triangles with flickering effect, where this one is more noticeable than in Juce Demo:

https://drive.google.com/file/d/0B0jULMEAjnIAOTBXdWpVTTViYUU/view?usp=sharing

I have also tried to call Thread::setCurrentThreadPriority(10) in render() and it doesn't change anything essentially.