Android: Noções básicas sobre OnDrawFrame, FPS e VSync (OpenGL ES 2.0)

Por um tempo, agora eu experimentei uma 'gagueira' intermitente dos sprites que estão em movimento no meu jogo Android. É um jogo 2D OpenGL ES 2.0 bastante simples. (Esse é um problema contínuo que eu visitei muitas vezes).

No loop do meu jogo, eu tenho 2 'timers' - um que registrará o número de quadros no segundo anterior e outro que conta o tempo (em milissegundos) do final da iteração atual do onDrawFrame até o início do próximo.

Isto é o que eu encontrei:

Quando não estou processando nada, recebo 60fps (na maior parte) e, toda vez que o onDrawFrame é chamado, ele se informa como demorando mais que 16.667 ms. Agora, se eu renderizar algo (não importa se é 1 quad ou 100 quads, o resultado é o mesmo), obtenho 60fps (na maior parte), mas agora, apenas cerca de 20% das chamadas onDrawFrame relatam estar demorando mais tempo de 16,667 ms da última chamada.

Eu realmente não entendo por que isso acontece, em primeiro lugar, por que, quando onDrawFrame não está fazendo nada, é chamado tão 'lentamente' - e mais importante, por que qualquer chamada GL (um quad simples) ainda faz o tempo entre O onDrawFrame chama mais que 16.667ms (embora com muito menos frequência).

Devo dizer que, quando os relatórios do onDrawFrame demoram mais de 16.667 ms da última iteração, quase sempre são acompanhados por uma queda no FPS (para 58 ou 59), mas nem sempre, às vezes, o FPS permanece constante. Por outro lado, às vezes, quando o FPS cai, onDrawFrame é chamado a 16.667ms da conclusão da última iteração.

Assim......

Estou tentando consertar meu ciclo de jogo e erradicar essas 'gagueiras' - algumas outras coisas a serem observadas:

Quando eu faço o perfil do método, ele mostra glSwapBuffers, às vezes demorando muito tempoQuando eu faço um GL Trace, a maioria das cenas é exibida em menos de 1ms, mas às vezes o quadro estranho leva 3,5-4ms - a mesma cena. Nada muda além do tempo que levaQuase toda vez que um quadro é derrubado ou o onDrawFrame relata um longo atraso (ou ambos), há uma falha visual, mas não sempre. Grandes falhas visuais parecem coincidir com várias chamadas onDrawFrame 'atrasadas' e / ou quadros perdidos.Eu não acho que esse seja um problema de complexidade da cena por 2 razões: 1) mesmo que eu renderize minha cena duas vezes, isso não piorará o problema, ainda assim, na maioria das vezes, obtenho 60FPS com uma queda ocasional, apenas como antes e 2), mesmo que eu descubra a cena, eu ainda entendi o problema.

Obviamente, estou entendendo mal alguma coisa, então um empurrão na direção certa seria apreciado.

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 the 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();        
}

Este loop do jogo acima é o apresentado neste excelenteartigo.

questionAnswers(1)

yourAnswerToTheQuestion