Open GL stutter when rendering on Galaxy S2 - android

Our Android game has an issue which appears unique to the Galaxy S2.
Occasionally the render will stutter. By this I mean it basically seems to render the last two frames (as though its swapping the last two render buffers without updating either).
What's really odd about this is that the game continues to update, so say the stutter lasts for 2 seconds, the game will have progressed 2 seconds behind the scenes.
This is odd because our code is basically like this:
function Update()
DoGameLogic()
DoRender()
So this means that if our the game has updated, the game has also rendered. The maximum delta time is capped to 1 frame so there must have been more than one Update and thus multiple renders during the stutter.
My current theory is that on most devices the game lags during render, but on the S2 the render calls are executed but they "fall through" without updating the render buffer.
Has anyone run into this problem? I would really appreciate any suggestions about what this could be.

We found out what the problem is.
The Galaxy S 2 was for some reason running out of GL memory. This wasn't apparent on the devices we were testing with, but on other devices it would crash on some Open GL call - not the offending call mind you.
Eventually we tracked it down to using Point sprite VBO's. As the S 2 is a powerful device, we replaced Point sprites with Quad's mimicking point sprites as a workaround.
Incidentally, SoundPool would also run out of memory on this device, requiring another workaround.

Related

Android OpenGL occasional stutter

I've written an OpenGL ES 2 app using NativeActivity that renders around 6 textured triangles that you can drag around using touch input. The app is rendering as fast as possible, calling glClear() before and eglSwapBuffers() after rendering. As expected the frame rate is capped to the display frequency of around 60 fps and the scene moves around smoothly. However, after some time (10 to 60 seconds) the movement starts to stutter even though the frame rate is still 60 fps. The device I'm using is OnePlus 3.
At first I suspected the culprit was battery saving mode, but investigation revealed no correlation between cpus' frequencies and the stutter.
I did notice something interesting though, the stutter starts when queueBuffer() execution time goes up.
This is the systrace before stutter:
This is the systrace after stutter:
This is the systrace during the transition from before to after:
How do I stop the app from stuttering?
I still don't know the exact cause of the stuttering, but I managed to find a work-around: Only render frames on Choreographer.postFrameCallback and set eglPresentationTimeANDROID to two vsyncs in the future. This avoids filling up the buffer queue, which seems to be one of the causes of the stuttering.
As a bonus it also improved the touch input latency a little.
More info here: Minimize Android GLSurfaceView lag

Webview (chromium) misses frames for no reason?

I have trouble debugging an performance issue on a div with overflow:auto. As you can see in the image below (and read in the the breakdown below that) it looks like the webview is wasting precious time by not delivering frames.
Weirdest thing is that the same content scrolls pretty smoothly on two older devices (Moto G and X 2013, Lollipop 5.1) but shows noticeable framedrops on newer ones (Moto X 2014 (Marshmallow 6.0) and Pixel C (Nougat 7.0)).
Between 990 and 995ms it does some compositing, rasterizing and gpu stuff. Then it sits idly for 15ms (that's almost an entire frame), updates the layer tree, then waits for another 18ms.
So we've missed ~2 frames by now even when it looks like it should have been able to deliver at least one.
Then it fires a scroll event and gets to chew on the javascript that is tied to that. That takes ~5ms and now it does some painting and compositing, then waits ANOTHER 10ms and updates the layer tree, then more waiting and then, finally, delivers it's first new frame since 990ms.
This entire thing took 66ms but, according to the timeline, the webview used most of that time to sit on its ass. And this is not an exception, I'm seeing this pattern during the entire recording of the scroll.
When I look at a timeline taken from the Moto X 1st gen it looks like the webview wastes a lot less time and tries to deliver frames as often as possible. Sure, it's not doing 60fps all the time but at this point I'm happy it does 40 instead of 20 or even lower.
The obvious question here is "what the hell is happening?" - or maybe more accurate: "why are things (read: frames) NOT happening?"
PS: I've checked the Android System Webview version and all of the devices I tested this on have v52 installed. The only thing I can think of is that the OS is 'causing' this. Did something change since Marshmallow?
UPDATE
I've been able to solve most of the lag by relaying most of the onscroll-logic I did to requestAnimationFrame and hide content that is off-screen (with visibility:hidden). But this doesn't really explain why Chrome seems to just skip frames when it's not really doing anything. It seems it has to do with scrolling a large area fairly complex content but I'd expect to see that in the timeline in some form. Instead, it just shows large empty spaces that block frames from rendering..?

OpenGL ES GL_DEPTH_TEST Performance issue

I'm writing an OpenGL ES 2.0 game in C++ running on multiple (mobile) platforms.
On IOS,Android,.. basically everything runs fine, except one device:
The computation for one frame in a specific scene take about 8ms on an HTC Desire.
Another device, a Samsung Galaxy Nexus, which is much newer takes 18-20ms.
I digged into the problem and found out that it is related to enable/disable of GL_DEPTH_TEST.
if I comment out all glEnable(GL_DEPTH_TEST)/glDisable(GL_DEPTH_TEST) calls the time needed for one frame drops to 1-2ms on the Nexus.
so I optimized the glEnable()/glDisable() calls to occur only when absolutely needed. I have 3d and 2d parts in my scene and therefore need to render 2d without depth_test and 3d with depth test.
currently I enable depth test, draw 3d, disable depth test, draw 2d
but still the computation takes 18-20ms on the nexus
I also checked if the depth buffer is cleared more than needed. But it is just cleared at the start of the frame.
Is it possible that the switch of the depth test takes that much time?
Does anyone have other ideas what can be checked?
UPDATE
I found out that the 3d object I render is somehow responsible for the slow computation.
If I remove the 3d object the performance is good
but the same 3d object is used in another scene without causing such trouble
and the weirdest thing: the Nexus runs Android 4.2 and it has an option in the developer options to visualize the cpu load as an overlay. If I enable this setting and start the game, the computation time is 5-6ms instead of 18-20ms. How can this be related?

lockCanvas() really slow

Testing my game on a slower device (Orange San Francisco aka ZTE Blade) and I have been getting an appalling frame rate.
I put some debug code into the draw loop and discovered the following line is taking over 100ms:
c = mSurfaceHolder.lockCanvas();
Anyone else seen this behaviour? I temporarily replaced the surfaceview by extending View and implementing onDraw(), and I got a much better framerate.
Although in general surfaceView is much faster on my HTC Desire. I am suspicious this may be a Android 2.1 problem. I'm contemplating rooting the phone and upgrading it to 2.2 if possible, but I did want a device running on 2.1 so that might be counter-productive in the long run.
** update **
I've been working on this some more, and have discovered some more puzzling aspects to it.
I rooted the phone and installed 2.2 and the problem still happens. When the app is first started, the lockCanvas is working as expected (0-1 ms). Then at some point during my initialisation, lockCanvas suddenly starts taking approx 100ms.
It might be worth pointing out that I am loading my assets in an Async task, so that I can display a loading screen.
Despite my best efforts to pin down what the program is actually doing when the slowness occurrs I was not able to do so. In fact when I run it in debug mode and single step, it works fast!
Now I discovered that if I add a delay in the constructor of my SurfaceView (of about 10 seconds), the slowness doesn't occur and all works fine.
However if you press Home, and then switch back, the slowness comes back.
I'm pretty much at the end of my tether on this stupid illogical problem! I've got a mind to put it down to a device specific problem.
I feel it could have something to do with memory usage. Maybe something is being swapped out and it affects the video ram?
I'd be interested in theories at least.
About lockCanvas() from docs:
If you call this repeatedly when the
Surface is not ready (before
Callback.surfaceCreated or after
Callback.surfaceDestroyed), your calls
will be throttled to a slow rate in
order to avoid consuming CPU.
Is it possible that your draw loop is initiated too early for some devices? I think this is the problem, since you wrote:
Now I discovered that if I add a delay
in the constructor of my SurfaceView
(of about 10 seconds), the slowness
doesn't occur and all works fine.
So, maybe we could use holder.isCreating() to check state?
this method will return true if canvas still creating.
Something like
while(holder.isCreating()) {}
can=holder.lockCanvas();
But I'm a bit confuse now. As i know colbeck is called when a surfaceview is creates. We should implement SurfaceHolder.Callback interface. And when surface is created callback method
public void surfaceCreated(SurfaceHolder holder) { } will be called.
From surfaceCreated method I'm starting gameloop thread.
I have recently discovered that if large bitmaps are used to draw on the canvas and these bitmaps are stored in the activity class - the "_surfaceHolder.lockCanvas()" command itself takes very long (about 70ms depending on device). HOWEVER, moving these bitmaps storage to other class (in different file, say MY_DATA), and the activity has just a reference to that new class - solves the problem.
I'm have no explanation to this phenomenon.
I was encountered the same mysterious problem with Canvas drawing, but solved it by changing Canvas drawing to drawing on the SurfaceView. But now I have constantly slow lockCanvas() call.
Here is my observation results.
Problem is only present on some devices:
Galaxy Note 3 n900: has problems
Galaxy Note 3 n9005: has problems
Galaxy S4 i9505: has problems
Galaxy Gio: no problems
LG G2 D802: has problems
Galaxy S2 i9100: no problems
I temporarily replaced the surfaceview by extending View and implementing onDraw(), and I got a much better framerate
I also noticed, that Samsung phones using GLES20Canvas instead of regular Canvas with onDraw() drawing, as a result, better performance.

Android OpenGLES - Lag between calls to OnDrawFrame on Moto Droid at large resolution

We are currently developing an Android Game using opengles. We are now trying to support different resolutions, however, when allowing for large resolutions, the moto droid we are testing on seems to lag at it's native resolution (800x400). We have the frames locked at 30 fps, and when we check, our game only takes about 15-20 ms to do it's updating and drawing on the droid, however, there is sometimes 30-60 ms that elapses between calls to ondrawframe. My Galaxy S device doesn't have this problem, and when we put the resolution down on the motorola droid it seems perfectly fine.
We've investigated the issue and have found people with what seems to have been the exact same issue but no one could offer a solution. Other games on the market that seem to use opengles run fine on the moto droid.
Is there something we're missing? Something we need to call or do to? There seems like there should be no reason for there to be 30-60 ms between calls to ondrawframe, especially when the native resolution (800x400) isn't leaps and bounds larger than the default of 533x320, or whatever it is that it goes to when not allowing for large screens, so it seems ridiculous for it to be because of a buffer swap. The lag even happens when near nothing is being drawn to screen, so it's not because we're drawing too much.
Any enlightenment or help as to how to fix this would be great.
You have to give more information. If its not because of drawing, then it should be because of any calculation or object allocation code. Allocating Objects often during a game, invokes the GC, which is bad for games.
Things about performance and allocating memory for Android games is explained in the links below.
I suggest you watch these 2 videos done by Google Android Group.
http://www.youtube.com/watch?v=U4Bk5rmIpic&feature=player_embedded
http://www.youtube.com/watch?v=7-62tRHLcHk&feature=player_embedded
Hope that helps in optimizing.

Categories

Resources