2016-07-08 4 views
2

Je travaille sur un simple jeu 2D avec un dessin de canevas personnalisé (postInvalidate()) et HardwareAcceleration. Après des semaines d'analyse des performances, j'ai décidé de synchroniser mes opérations de mise à jour et de dessin avec l'impulsion VSYNC via l'interface Choreographer.FrameCallback. Je pense que c'est la bonne façon d'obtenir des mouvements fluides.La double mise en mémoire tampon ralentit le rendu du cadre | analyse systrace

Cependant, je suis toujours en train de ressentir des mouvements saccadés. Je l'ai analysé avec systrace et j'ai remarqué que cela a quelque chose à voir avec ma BufferQueue. Dès que le double tampon est activé, le temps de trame dépasse les 16 ms. J'ai fait une capture d'écran de ma trace avec quelques explications:

à dequeue son propre nouveau tampon vide L'ensemble de l'opération de tirage au sort attend la libération de tampon du SurfaceFlinger (consommateur).

Pouvez-vous me dire si c'est un comportement normal ou quelle pourrait en être la raison?

Répondre

1

Sur votre graphique, vous avez une note, "SurfaceFlinger manque VSYNC". Toutefois, si vous regardez la ligne BufferQueue, vous pouvez voir que le tampon est arrivé après la date limite VSYNC. SurfaceFlinger s'est réveillé, mais il n'y avait rien à faire.

Votre application a ensuite fourni un tampon supplémentaire, ce qui signifie que vous aviez deux tampons en attente. Puisque vous avez continué à fournir un tampon sur chaque VSYNC, la file d'attente n'est jamais redescendue à zéro. Lorsque la file d'attente est saturée, chaque tentative d'ajout de tampons supplémentaires entraîne un blocage. FWIW, votre BufferQueue est à triple tampon: deux sont dans la file d'attente, l'autre à l'écran.

Il y a quelques choses que vous pouvez faire:

  1. Demandez aux cadres de goutte d'application si vous avez manqué la date limite.
  2. Spécifiez une heure de présentation pour les cadres afin que SurfaceFlinger les supprime si le temps est dépassé.
  3. Détruisez délibérément une image de temps en temps pour laisser la file d'attente vide. (Pas l'approche préférée.)

# 2 fonctionne seulement avec GLES sur un SurfaceView, donc nous pouvons ignorer celui-là.

# 1 pourrait fonctionner pour vous; vous pouvez voir un example in Grafika. Il dit essentiellement, "si le VSYNC suivant tire en moins de 2ms, ou a déjà tiré, ne pas déranger le rendu de l'image en cours." L'approche View/invalidate ne vous donne pas le même contrôle que GLES, donc je ne suis pas sûr de savoir si cela fonctionnera.

La clé pour faciliter l'animation sur un périphérique occupé ne frappe pas toutes les images à 60 ips. La clé est de faire vos mises à jour en fonction de l'heure delta, de sorte que les choses semblent bien, même si vous déposez une image ou deux.

Pour plus de détails sur l'architecture graphique, voir this doc.

+0

Merci pour la réponse détaillée! J'ai décidé d'opter pour une implémentation OpenGL ES 1 avec GLSurfaceView. Je mesure maintenant l'heure delta dans chaque cadre dans la méthode onDrawFrame(). Une interpolation supplémentaire sur les derniers temps de trame (pour éliminer les gros "sauts de bégaiement") a été une grande amélioration. Maintenant, mon jeu fonctionne très bien! – methusa