performance - Android: Understanding OnDrawFrame, FPS and VSync (OpenGL ES 2.0) -


for while i've experienced intermittent 'stuttering' of sprites in motion within android game. it's fiarly simple 2d opengl es 2.0 game. (this ongoing problem have re-visited many times).

in game loop, have 2 'timers' - 1 log number of frames in previous second, , counts time (in milliseconds) end of current ondrawframe iteration start of next.

this i've found:

when not rendering anything, 60fps (for part), , every time ondrawframe called, reports taking longer 16.667ms. now, if render (doesn't matter if it's 1 quad or 100 quads, result same), 60fps (for part) now, 20% of ondrawframe calls report taking longer 16.667ms last call.

i don't understand why happens, firstly, why, when ondrawframe isn't doing anything, called 'slowly' - , more importantly, why gl call (one simple quad), still make time between ondrawframe calls longer 16.667ms (albeit less frequently).

i should when ondrawframe reports taking longer 16.667ms last iteration, accompanied drop in fps (to 58 or 59), not of time, sometimes, fps stays constant. , conversely, when fps drops, ondrawframe called within 16.667ms of last iteration completing.

so......

i'm trying fix game-loop , eradicate these 'stutters' - other things note:

  • when method profiling, shows glswapbuffers, taking long time
  • when gl trace, scenes says renders in less 1ms, odd frame takes 3.5-4ms - same scene. nothing changes apart time takes
  • almost every time frame dropped, or ondrawframe reports long delay (or both), there visual glitch, not every time. big visual glitches seems coincide multiple 'delayed' ondrawframe calls , /or dropped frames.
  • i don't think scene complexity issue 2 reasons: 1) if render scene twice, doesn't make problem worse, still part, 60fps occasional drop, before , 2), if strip scene bare, still problem.

i misunderstanding something, push in right direction appreciated.

ondrawframe

@override public void ondrawframe(gl10 gl) {      starttime = system.nanotime();             fps++;                             totaltime = system.nanotime() - timesincelastcalled;          if (totaltime > 16667000) {              log.v("logging","time between ondrawframe calls: " + (totaltime /(double)1000000));     }      //grab time     newtime = system.currenttimemillis() * 0.001;     frametime = newtime - currenttime; //time last frame took      if (frametime > 0.25)         frametime = 0.25;      currenttime = newtime;     accumulator += frametime;      while (accumulator >= dt){                     savegamestate();       updatelogic();       accumulator -= dt;     }      interpolation = (float) (accumulator / dt);      matrix.multiplymm(mmvpmatrix, 0, mprojmatrix, 0, mvmatrix, 0);      render(interpolation);      if (starttime > lastsecond + 1000000000) {                   lastsecond = starttime;         log.v("logging","fps: "+fps);         fps=0;               }      endtime = starttime;     timesincelastcalled = system.nanotime();         } 

this game loop above 1 featured in excellent article.

some thoughts:

  • don't use system.currenttimemillis() timing things. it's based on wall clock, can updated network. use system.nanotime(), based off monotonic clock.
  • see this appendix notes on game loops. queue-stuffing fine many things, understand you're not working off of vsync, timings tend inaccurate.
  • some devices (notably based on qcom socs) reduce cpu speed when think they're idle. take timings while actively moving finger around on touch screen.
  • if want debug frame rate issues need using systrace. traceview profiling isn't useful here.

see grafika's "record gl app" activity example of simple gles app drops frames, adjusts animation such it's noticeable.


Comments