opengl: glFlush() vs glFinish()
Je vais avoir de la difficulté à distinguer la différence pratique entre un appel glFlush()
et glFinish()
.
Les docs disent que glFlush()
et glFinish()
va pousser tous les tamponnée opérations à OpenGL de sorte que l'on peut être assuré qu'ils seront tous exécutés, la différence étant que glFlush()
retourne immédiatement, où que glFinish()
blocs jusqu'à ce que toutes les opérations sont terminées.
Avoir lu les définitions, j'ai pensé que si je devais utiliser glFlush()
que je serais probablement courir dans le problème de la soumission des opérations à OpenGL qu'il pourrait s'exécuter. Donc, juste pour essayer, j'ai troqué mon glFinish()
pour un glFlush()
et voilà, mon programme est exécuté (autant que je puisse en juger), exactement le même; taux de rafraîchissement, de l'utilisation des ressources, tout était le même.
Alors je me demandais si il y a une grande différence entre les deux appels, ou si mon code ne fait courir aucun différent. Ou l'endroit où il devrait être utilisé contre l'autre.
J'ai aussi pensé que OpenGL aurait certains appellent comme glIsDone()
pour vérifier si oui ou non tous de la mémoire tampon des commandes pour un glFlush()
sont complètes ou pas (donc on n'est pas d'envoyer des opérations d'OpenGL plus vite qu'ils ne peuvent être exécutées), mais j'ai pu trouver pas une telle fonction.
Mon code est le jeu typique de la boucle:
while (running) {
process_stuff();
render_stuff();
}
Vous devez vous connecter pour publier un commentaire.
L'esprit que ces commandes existent depuis les premiers jours de l'OpenGL. glFlush assure que les précédentes commandes OpenGL doit remplir en un temps fini (OpenGL 2.1 spécifications, page 245). Si vous dessinez directement sur le front de la mémoire tampon, ce veillent à ce que les pilotes OpenGL commence le dessin sans trop de retard. Vous pourriez penser à une scène complexe qui apparaît objet après objet sur l'écran, lorsque vous appelez glFlush après chaque objet. Cependant, lors de l'utilisation de la double mise en tampon, glFlush a pratiquement aucun effet, puisque les modifications ne seront pas visibles jusqu'à ce que vous permutez les tampons.
glFinish ne pas revenir jusqu'à ce que tous les effets de déjà émis des commandes [...] sont entièrement réalisés. Cela signifie que l'exécution de votre programme attend ici jusqu'à ce que chaque pixel est dessiné et OpenGL n'a plus rien à faire. Si vous rendre directement sur le front de la mémoire tampon, glFinish est l'appel à faire avant d'utiliser le système d'exploitation appelle pour prendre des captures d'écran. Il est beaucoup moins utile pour le double buffering, parce que vous ne voyez pas les modifications que vous avez forcé à compléter.
Donc, si vous utilisez une double mise en mémoire tampon, vous n'aurez probablement pas besoin ni glFlush ni glFinish. SwapBuffers implicitement dirige les appels OpenGL pour le tampon approprié, il n'y a pas besoin d'appeler glFlush première. Et n'avez pas l'esprit en soulignant le pilote OpenGL: glFlush ne va pas s'étouffer trop de commandes. Il n'est pas garanti que cet appel retourne immédiatement (quoi que cela signifie), de sorte qu'il peut prendre n'importe quel moment elle a besoin pour traiter vos commandes.
Que les autres réponses ont laissé entendre, il n'y a vraiment pas de bonne réponse que par la spécification. L'objectif général de l'
glFlush()
est qu'après l'appel, le PROCESSEUR de l'hôte n'aura pas d'OpenGL liés au travail à faire, les commandes ont été poussés à le matériel graphique. L'objectif général de l'glFinish()
est qu'après qu'il renvoie, pas travail restant est à gauche, et les résultats devraient être disponibles aussi tous les non-OpenGL Api (par exemple lit à partir de la mémoire vidéo, captures d'écran, etc...). Si c'est vraiment ce qui se passe est dépendant du pilote. La spécification permet une tonne de latitude quant à ce qui est légal.J'ai toujours été confus au sujet de ces deux commandes, mais cette image fait tout clair pour moi:
Apparemment, certains GPU pilotes de ne pas envoyer les commandes pour le matériel, à moins qu'un certain nombre de commandes a été accumulé. Dans cet exemple que le nombre est 5.
L'image montre les différentes commandes OpenGL (A, B, C, D, E...) qui ont été émises. Comme on peut le voir en haut, les commandes n'émet encore, parce que la file d'attente n'est pas encore pleine.
Dans le milieu, nous voyons comment
glFlush()
affecte la file d'attente des commandes. Il indique au conducteur d'envoyer tous en file d'attente des commandes pour le matériel (même si la file d'attente n'est pas encore pleine). Cela ne veut pas bloquer le thread appelant. Il se contente de les signaler au conducteur que nous pourrions ne pas être tout envoi de commandes supplémentaires. Donc en attente de la file d'attente pour remplir serait une perte de temps.En bas, nous voyons un exemple d'utilisation de
glFinish()
. Il ne fait presque la même chose queglFlush()
, sauf qu'il fait le thread appelant attendre jusqu'à ce que toutes les commandes ont été traitées par le matériel.Image tirée du livre "Graphiques Avancés de la Programmation OpenGL".
glFlush
etglFinish
faire, et je ne peux pas dire ce que l'image est en train de dire. Ce qui est sur le côté gauche et la droite? Aussi, est que l'image a publié dans le Domaine Public ou sous une licence qui vous permet de publier sur Internet?Si vous ne voyez aucune différence de performance, cela signifie que vous faites quelque chose de mal. Comme certains d'autres l'ont mentionné, vous n'avez pas besoin de l'appeler, mais si vous le faites appel glFinish, alors vous êtes automatiquement perdre le parallélisme que le GPU et le CPU peut atteindre. Permettez-moi de plonger plus profond:
Dans la pratique, tout le travail que vous soumettez pour le conducteur est mis en lots, et envoyé le matériel potentiellement plus tard (par exemple, au SwapBuffer temps).
Donc, si vous êtes d'appel glFinish, vous êtes essentiellement en forçant le pilote à pousser les commandes pour le GPU (qu'il groupées jusqu'alors, et n'a jamais demandé le GPU pour travailler sur), et de décrochage de la CPU jusqu'à ce que les commandes poussé sont complètement exécuté. Donc, pendant tout le temps le GPU fonctionne, le CPU n'a pas (au moins sur ce fil). Et toutes les fois que le CPU fait son travail (surtout le dosage, commandes), le GPU n'est pas n'importe quoi. Donc oui, glFinish devrait nuire à votre performance. (C'est une approximation, car les conducteurs commencent à avoir le GPU de travail sur certaines commandes si beaucoup d'entre eux ont déjà été ajoutés au mélange. Ce n'est pas typique, cependant, que la commande de tampons ont tendance à être assez grande pour contenir beaucoup de commandes).
Maintenant, pourquoi le feriez-vous appel glFinish à tous, alors ? La seule fois où j'ai utilisé c'était quand j'avais des bogues. En effet, si l'une des commandes que vous envoyez vers le bas pour les pannes de matériel de la carte graphique, puis votre option la plus simple pour identifier la commande qui est le coupable est l'appel de glFinish après chaque Tirage. De cette façon, vous pouvez affiner ce qui déclenche exactement le crash
Comme une note de côté, Api comme Direct3D ne prennent pas en charge une Finition concept à tous.
glFlush vraiment remonte à un client-serveur modèle. Vous envoyez tous les gl commandes par l'intermédiaire d'un tuyau à un gl serveur. Le tuyau peut-tampon. Tout comme n'importe quel fichier ou d'un réseau i/o peut-tampon. glFlush dit seulement: "envoyer le tampon maintenant, même si elle n'est pas encore pleine!". Sur un système local, ce n'est presque jamais nécessaire, car un local OpenGL API est peu probable que la mémoire tampon et simplement des questions directement des commandes. Aussi toutes les commandes que la cause réelle de rendu va faire un implicite de la chasse d'eau.
glFinish d'autre part a été faite pour la mesure de la performance. Une sorte de PING pour les GL serveur. Il les allers-retours d'une commande et attend jusqu'à ce que le serveur répond "je suis libre".
Moderne de nos jours, les automobilistes ont tout à fait les idées créatives de ce que signifie être ralenti si. Est-il "tous les pixels sont tracées" ou "ma commande file d'attente a l'espace"? Aussi parce que beaucoup de vieux programmes saupoudré glFlush et glFinish tout au long de leur code sans raison que le vaudou codage de nombreux drivers modernes il suffit de les ignorer comme une "optimisation". Ne pouvez pas les blâmer pour ça, vraiment.
Donc en résumé: pour Traiter à la fois glFinish et glFlush que pas d'ops dans la pratique, sauf si vous êtes codant pour une ancienne télécommande SGI OpenGL serveur.
Ont un look ici. En bref, il dit:
Un autre l'article décrit d'autres différences:
glFlush
glFinish
forces OpenGL pour effectuer les commandes en suspens, ce qui est une mauvaise idée (par exemple, avec le VSync)Pour résumer, cela signifie que vous n'avez même pas besoin de ces fonctions lors de l'utilisation de la double mise en tampon, sauf si votre swap-tampons de mise en œuvre n'est pas automatiquement valider les commandes.
Il ne semble pas être un moyen d'interroger le statut de la mémoire tampon. Il y a cette Apple extension qui pourrait servir le même but, mais il ne semble pas multi-plateforme (n'ai pas essayé.) À ce rapide coup d'œil, il semble avant
flush
vous avais pousser la barrière de commande; vous pouvez ensuite d'interroger le statut de la clôture comme il se déplace à travers la mémoire tampon.Je me demande si vous pourriez utiliser
flush
avant la mise en mémoire tampon jusqu'commandes, mais avant de commencer à rendre l'image suivante vous appelezfinish
. Cela vous permettra de commencer le traitement de l'image suivante que le GPU fonctionne, mais si cela ne se fait pas par le temps que vous obtenez en retour,finish
va bloquer pour s'assurer que tout est dans un état frais.je n'ai pas essayé, mais je le ferai prochainement.Je l'ai essayé sur un vieux application qui a de jolies même CPU & de l'utilisation du GPU. (À l'origine utilisé
finish
.)Quand je l'ai changé pour
flush
à la fin etfinish
au début, il n'y avait pas de problèmes immédiats. (Tout avait l'air bien!) La réactivité du programme a augmenté, probablement parce que le PROCESSEUR n'était pas bloqué en attente sur le GPU. Certainement une meilleure méthode.Pour la comparaison, j'ai enlevé
finished
depuis le début de la trame, laissantflush
, et il fait le même.Je dirais donc utiliser
flush
etfinish
, parce que quand le tampon est vide lors de l'appel àfinish
, il n'y a pas de gain de performance. Et je devine que si le tampon ont été pleine, vous devez voulezfinish
de toute façon.La question est: voulez-vous votre code de continuer à fonctionner alors que les commandes OpenGL sont exécutés, ou uniquement pour exécuter après vos commandes OpenGL a été exécuté.
Ce peut dans les cas, comme sur les retards de réseau, de certains de sortie de la console uniquement après les images ont été tirées ou le tel.