2009-03-24 4 views
4

Voici ce qui se passe:Quelles sont les causes de la fluctuation des temps d'exécution lors de la présentation du Renderbuffer? (OpenGL)

  • La fonction drawGL est appelée à la fin exacte du cadre grâce à un usleep, comme l'a suggéré. Cela maintient déjà un framerate stable. La présentation réelle du rendu est effectuée avec drawGL(). La mesure du temps nécessaire pour cela, me donne des temps d'exécution variables, ce qui entraîne un bégaiement dans mon animation. Cette minuterie utilise mach_absolute_time donc c'est extrêmement précis. À la fin de mon cadre, je mesure timeDifference. Oui, il est en moyenne 1 milliseconde, mais il dévie beaucoup, allant de 0,8 millisecondes à 1,2 avec des pics allant jusqu'à plus de 2 millisecondes.

Exemple:

// Every something of a second I call tick 
-(void)tick 
{ 
    drawGL(); 
} 

- (void)drawGL 
{ 
    // startTime using mach_absolute_time; 

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer); 
    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 

// endTime using mach_absolute_time; 
// timeDifference = endTime - startTime; 
} 

Ma compréhension est que, une fois le framebuffer a été créé, présentant le renderbuffer doit toujours prendre le même effort, quelle que soit la complexité du cadre? Est-ce vrai? Et sinon, comment puis-je empêcher cela? Par ailleurs, ceci est un exemple pour une application iPhone. Nous parlons ici d'OpenGL ES, bien que je ne pense pas que ce soit un problème spécifique à une plate-forme. Si c'est le cas, que se passe-t-il? Et ne devrait-il pas s'agir de et non de? Et encore une fois, si oui, comment puis-je empêcher cela?

Répondre

1

Les écarts que vous rencontrez peuvent être causés par de nombreux facteurs, y compris le planificateur de système d'exploitation qui intervient et donne un processeur à un autre processus ou à des problèmes similaires. En fait, l'homme normal ne fera pas la différence entre des temps de rendu de 1 et 2 ms. Les images animées tournent à 25 ips, ce qui signifie que chaque image est montrée pendant environ 40ms et qu'elle a l'air fluide pour l'œil humain. En ce qui concerne le bégaiement d'animation, vous devriez examiner comment maintenir une vitesse d'animation constante. approche la plus commune que j'ai vu ressemble à peu près comme ceci:

while(loop) 
{ 
    lastFrameTime; // time it took for last frame to render 
    timeSinceLastUpdate+= lastFrameTime; 

    if(timeSinceLastUpdate > (1 second/DESIRED_UPDATES_PER_SECOND)) 
    { 
    updateAnimation(timeSinceLastUpdate); 
    timeSinceLastUpdate = 0; 
    } 

    // do the drawing 

    presentScene(); 
} 

Ou vous pouvez simplement passer lastFrameTime à updateAnimation chaque image et interpoler entre les états d'animation. Le résultat sera encore plus fluide.

Si vous utilisez déjà quelque chose comme ce qui précède, vous devriez peut-être chercher des coupables dans d'autres parties de votre boucle de rendu. Dans Direct3D, les choses coûteuses étaient des appels pour des primitives de dessin et des états de rendu changeant, donc vous pourriez vouloir vérifier les analogues OpenGL de ceux-ci.

+0

Je chronomètre d'ailleurs déjà mes calculs afin de maintenir un framerate stable. Le dessin actuel a toujours lieu exactement à la fin du cadre. (J'utilise une minuterie de sommeil pour cela) Je vais clarifier la question pour cela. – Kriem

0

Il est préférable de ne pas compter sur une fréquence d'images constante élevée pour un certain nombre de raisons, la plus importante étant que l'OS peut faire quelque chose en arrière-plan qui ralentit les choses. Mieux vaut échantillonner une minuterie et déterminer combien de temps a passé chaque image, ce qui devrait assurer une animation fluide.

0

Est-il possible que le temporisateur ne soit pas précis au niveau de sous-ms même s'il renvoie des décimales de 0,8 à> 2,0?

+0

Pourrait être. C'est un NSTimer. Malgré cela, même si, le framerate semble bégayer. – Kriem

1

Mon expression OpenGL préférée de tous les temps: "implementation specific". Je pense que cela s'applique très bien ici.

+0

Pourriez-vous élaborer? – Kriem

+0

Je ne pense pas qu'il est absolument exigé par la spécification que le temps de rendu pour les images suivantes du même contenu doit être absolument le même. Autrement dit, le fabricant de GPU est probablement autorisé à faire fluctuer le temps. –

1

Une recherche rapide des résultats de mach_absolute_time dans cet article: Link

On dirait une précision de cette horloge sur un iPhone est seulement 166,67 ns (et peut-être pire). Bien que cela puisse expliquer la grande différence, cela n'explique pas qu'il y a une différence du tout.

Les trois principales raisons sont probablement:

  • chemins différents d'exécution lors de la présentation renderbuffer. Beaucoup de choses peuvent se produire en 1ms et ce n'est pas parce que vous appelez les mêmes fonctions avec les mêmes paramètres que les mêmes instructions sont exécutées. Cela est particulièrement vrai si d'autres matériels sont impliqués. Interruptions/autres processus, il se passe toujours quelque chose d'autre qui distrait le processeur.
  • Pour autant que je sache, l'iPhone OS n'est pas un système d'exploitation en temps réel et donc il n'y a aucune garantie que toute opération se terminera dans un certain délai (et même un système d'exploitation en temps réel aura des variations de temps).
  • S'il y a d'autres appels OpenGL en cours de traitement par le GPU qui pourraient retarder presentRenderbuffer. C'est le plus facile à tester, appelez glFinish() avant d'avoir l'heure de début.
Questions connexes