I am experimenting with the Camera to MP4 example here:
https://bigflake.com/mediacodec/CameraToMpegTest.java.txt
My test app uses roughly the same code, and when I record at 1280x720 then everything is fine.
But for some reason switching to use 1920x1080 then the FPS drops and CPU usage increases.
Profiling CPU usage the problem seems to be the GLES20.glDrawArrays call.
It goes from using about 2% of CPU cycles to almost 40%. The only thing that's different is the camera preview resolution.
It seems to be crossing some sort of cache or memory re-allocation boundary. I don't have much OpenGL experience, and am not sure how I could debug this. Any advice on what I could look for?
EDIT:
Enabling Androids GPU usage overlay indicates no noticeable difference.
Related
I created an application with Starling, on the new mobile devices it performs amazingly well, however on the older devices (e.g. iPhone 4) I encounter a very odd lag.
I have as far as I can tell a completely static situation:
There are quite a few display objects added to stage, many of them are buttons in case it matters, their properties are not changed at all after initialization (x, y, rotation, etc...).
There are no enterframes / timeouts / intervals / requests of any kind in the background.
I'm not allocating / deallocating any memory.
In this situation, there's an average of 10 FPS out of 30, which is very odd.
Since Starling is a well established framework, I imagine it's me who's doing something wrong / not understanding something / not aware of something.
Any idea what might be causing it?
Has anyone else experienced this sort of problem?
Edit:
After reading a little I've made great optimizations in every possible way according to this thread:
http://wiki.starling-framework.org/manual/performance_optimization
I reduced the draw calls from around 90 to 12, flattened sprites and set blendmode to none in specific cases to ease on CPU, and so on...
To my surprise when I tested again, the FPS was unaffected:
fps: 6 / 60
mem: 19
drw: 12
Is it even possible to get normal fps with Starling on mobile? What am I missing?
I am using big textures that are scaled down to the size of the device, is it possible that such a thing affects the fps that much?
Regarding "Load textures from files/URLs", I'm downloading different piles of assets for different situations, therefore I assumed compiling each pile into a SWF would be way faster than sending a separate request for each file. The problem is, for that I can only use embed, which apparently uses twice the memory. Do you have any solution in mind to enjoy the best of both worlds?
Instead of downloading 'over-the-wire' your assets and manually caching them for re-use, you can embed the assets into your app bundle vs. embedding them and then use the Starling AssetManager to load the textures at the resolution/scale that you need for the device:
ie.
assets.enqueue(
appDir.resolvePath("audio"),
appDir.resolvePath(formatString("fonts/{0}x", scaleFactor)),
appDir.resolvePath(formatString("textures/{0}x", scaleFactor))
);
Ref: https://github.com/Gamua/Starling-Framework/blob/master/samples/scaffold_mobile/src/Scaffold_Mobile.as
Your application bundle gets bigger of course, but you do not take the 2x ram hit of using 'embed'.
Misc perf ideas from my comment:
Testing FPS with "Release" mode correct?
Are you using textures that are scaled down to match the resolution of the device before loading them?
Are you mixing BLEND modes that are causing additional draw calls?
Ref: The Performance Optimization is great reading to optimize your usage of Starling.
Starling is not a miracle solution for mobile device. There's quite a lot of code running in the background in order to make the GPU display anything. You the coder has to make sure the amount of draw call is kept to a minimum. The weaker the device and the less draw call you should force. It's not rare to see people using Starling and not pay any attention to their draw calls.
The size of graphics used is only relevant for the GPU upload time and not that much for the GPU display time. So of course all relevant texture need to be uploaded prior to displaying any scenes. You simply cannot try to upload any new texture while any given scene is playing. Even a small texture uploading will cause idling.
Displaying everything using Starling is not always a smart choice. In render mode the GPU gets a lot of power but the CPU still has some remaining. You can reduce the amount of GPU uploading and GPU charge by simply displaying static UI elements using the classic display list (which is where the Staling framework design is failing). Starling was originally made to make it very difficult to use both display system together that's one of the downsides of using this framework. Most professional I know including myself don't use Starling for that reason.
Your system must be flexible and you should embed your assets for mobile and not use any external swf as much as possible and be able to switch to another system for the web. If you expect to use one system of asset for mobile/desktop/web version of your app you are setting yourself up for failure. Embedding on mobile is critical for memory management as the AIR platform internally manages the cache of those embedded assets. Thx to that when creating new instances of those assets the memory consumption stays under control, if you don't embed then you are on your own.
Regarding overall performance a very weak Android device will probably never be able to go passed 10 fps when using Starling or any Stage3D framework because of the amount of code those framework need to run (draw calls) in the background. On weak device that amount of code is already enough to completely overload the CPU. On the other hand on weak device you can still get a good performance and user experience by using GPU mode instead of render mode (so no Stage3D) and displaying mostly raster graphic.
IN RESPONSE TO YOUR EDIT:
12 draw calls is very good (90 was pretty high).
That you still get low FPS on some device is not that surprising. Especially low end Android device will always have low FPS in render mode with Stage3D framework because of the amount of code that those framework have to run to render one frame. Now the size of the texture you are using should not affect the FPS that much (that's the point of Stage3D). It would help with the GPU uploading time if you reduce the size of those graphics.
Now optimization is the key and optimizing on low end device with low FPS is the best way to go since whatever you do will have great effect on better device as well. Start by running tests and only displaying static graphics with no or very little code on your part just to see how far the Stage3D framework can go on its own on those weak device without losing any FPS and then optimize from there. The amount of object displayed on screen + the amount of draw calls is what affects FPS with those Stage3D framework so keep a count of those and always seek ways to reduce it. On some low end device it's not practical to try to keep a 60fps so try to switch to 30 and adjust your rendering accordingly.
I am developing a simple player shooting game. It worked fine for me. But when I tried deploying it on the device the FPS reduced to almost 3-4FPS.
Can anyone list out what are the factors that reduces the FPS in unity game.
Minimize the Draw calls, optimize the shaders and Reduce the number of vertices.
Graphic Optimization
iOS specific Optimiztion
This article may help
And try deep profiling of game using Unity Profiler to find the memory overhead.
I'm developing a GL live wallpaper that uses very little CPU and only modest GPU. On my older test phone, it can run at a full 58fps or so most of the time. But occasionally the effects ramp up, and then the render times jitter between 16ms and 50ms per frame. For example, it'll render several frames at 16ms, slide up to 50ms over a dozen frames or so, render several more frames at 50ms, then slide back down to 16ms and repeat. I discovered that if I set the CPU governor to "performance" (or "conservative", curiously enough) instead of the default "ondemand" it'll render with full effects at full speed. Alternatively, if I leave the governor alone and insert a busy loop in my code (increment a variable 100,000 times per frame) that bumps my CPU usage up enough to transition to a higher clock rate and render smoothly as well.
So it seems on this phone my app is bottlenecked by the GPU, but only when it throttles down. Now, I wouldn't mind if the GLSurfaceView rendered at a slower rate according to the GPU clock, but my problem here is that I'm getting the bursts of alternating high and low frame rates which makes my animation look fluid/frameskippy/fluid/frameskippy/etc. several times per second. It seems like the GPU clock is ramping up and down like crazy?
I got a visible improvement by using RENDERMODE_WHEN_DIRTY and calling requestRender() on a strictly timed thread, but the darn GPU keeps ramping up and down. Why won't it either render as fast as it can at the slower clock, or just jump to and STAY AT the higher clock?
The best solution I've come up with so far is using a sliding window to detect the average frame update time, then applying the difference from the target frame time until the two values converge. The time between render updates is slower but at least it's roughly constant. So that works in theory, but it takes several seconds to reach a steady state and it looks bad in the meantime.
I think a third option might be to cannibalize the GLSurfaceView source and make a custom version. From what I understand, the blocking GL calls are made in there, so it would be much easier for me to time render calls and react accordingly. I'm not very comfortable attempting that though because there's a lot of code in there that I'd have to spend a lot of time understanding before I could even begin to mess with it. Plus I'd then have to worry about how well version X of GLSurfaceView plays with any version Y of Android.
So, with all that said, do I have any other options here? Is there an easier fix to this?
try fixing the frame rate by pausing the thread (thread sleep) for the remaining time to reach a constant frame rate.
I've been developing a game for Android for the past few months, and it's just about finished. I recently acquired a Motorola Droid for testing purposes, as I developed the game using a HTC Incredible. On my Incredible I can get a pretty solid 59 fps throughout the game. On the Droid, the game becomes very choppy with an average of about 40 fps. Both phones are running Android 2.2.
I looked up the tech specs are here are the only differences I noted that might affect gameplay: 1 GHz processor vs 550 MHz and 512 MB RAM vs 256 MB RAM.
Just for giggles, I thought I would strip down the game to a very minimal state to see if it was my coding to blame. I stripped it down to the point where the only thing being down was drawing the main menu and moving various bitmaps around the screen. Not a hair over 45 fps.
So, is this the approximate cap for the Motorola Droid? If so...my game is pretty simple and non-CPU intensive, so what can I do? There are thousands of other Android games that are much more demanding than my own, yet they seem to run very smoothly.
Is it the fact that I'm using Android's built-in Canvas and not Open-GL or some other alternative? Would anybody recommend doing that?
Could somebody enlighten me to what might be my problem here?
Thanks in advance.
OpenGL ES is the way to go. Canvas is most likely implemented on top of OpenGL ES anyway, and not very efficiently by the sounds of it.
40fps is pretty good, the human eye can only detect jerkiness when the framerate falls below 25fps. Anything above 15fps is considered 'full motion'.
If you can see jitter then it may be the game pausing while the garbage collector kicks in - you can reduce this by reducing the number of objects that you create and you should be able to see it happening by using ddms.
Other than that perhaps there is a glitch calculating the frame rate?
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.