Quel problème la mise en mémoire tampon double ou triple résout-elle dans les jeux modernes?

31

Je veux vérifier si ma compréhension des causes de l'utilisation de la mise en mémoire tampon double (ou triple) est correcte:

Un moniteur avec un rafraîchissement de 60 Hz affiche le moniteur 60 fois par seconde. Si le moniteur rafraîchit l'affichage du moniteur, il met à jour pixel par pixel et ligne par ligne. Le moniteur demande les valeurs de couleur des pixels à la mémoire vidéo.

Si je lance maintenant un jeu, alors ce jeu manipule constamment cette mémoire vidéo.

Si ce jeu n'utilise pas de stratégie de tampon (double tampon, etc.), le problème suivant peut se produire:

Le moniteur rafraîchit maintenant son écran. À ce moment, le moniteur avait déjà actualisé la première moitié du moniteur. Dans le même temps, le jeu avait manipulé la mémoire vidéo avec de nouvelles données. Maintenant, le moniteur accède à la seconde moitié du moniteur pour afficher ces nouvelles données manipulées à partir de la mémoire vidéo. Les problèmes peuvent être déchirants ou vacillants.

Ma compréhension des cas d'utilisation d'une stratégie de tampon est-elle correcte? Y a-t-il d'autres raisons?

krokvskrok
la source

Réponses:

62

Fondamentalement, un objectif principal du rendu est que chaque image affichée sur le moniteur présente une seule image cohérente. Plusieurs stratégies différentes sont ou ont été utilisées pour y parvenir.

Dans ce qui suit, je mentionne "vsync". Vsync est le moment où le moniteur commence à dessiner une nouvelle image d'écran; c'est le point où "vblank" commence sur un écran CRT traditionnel, où la ligne de balayage arrête momentanément de dessiner et revient en haut du moniteur. Ce moment est très important pour de nombreuses approches de la cohérence des cadres.

"Déchirure" est ce que nous appelons quand un écran rend à partir de deux images différentes, dans une seule image. Si, par exemple, j'ai dessiné deux images d'écran qui sont destinées à être affichées l'une après l'autre, mais que le moniteur a plutôt affiché la moitié supérieure de la première image et la moitié inférieure de la deuxième image, c'est "déchirer". Cela se produit en raison de la modification des données depuis lesquelles le moniteur lit pendant que le moniteur dessine, plutôt que pendant vblank. (Dans les programmes modernes, cela se produit généralement parce que l'utilisateur a désactivé l'attente de vsync dans ses paramètres de pilote)

Zero-Buffer

Sur le matériel le plus ancien, il n'y avait souvent pas assez de mémoire pour contenir une image plein écran, et donc au lieu de dessiner une image d'écran, vous deviez spécifier les couleurs pour chaque ligne de numérisation individuellement, tandis que le moniteur était en train de dessiner cette ligne. Sur l'Atari 2600, par exemple, vous n'aviez que 76 cycles d'instructions machine pour spécifier la couleur de chaque pixel de la ligne de balayage, avant que le téléviseur ne commence à dessiner cette ligne de balayage. Et puis vous avez eu 76 cycles d'instructions pour fournir le contenu de la prochaine ligne de balayage, etc.

Tampon unique

Lorsque vous dessinez dans un contexte de "tampon unique", vous dessinez directement dans la VRAM qui est lue par le moniteur. Dans cette approche, vous "faites la course avec la ligne de balayage". L'idée générale est que lorsque la ligne de balayage commence à dessiner le contenu de l'image précédente en haut de l'écran, vous dessinez dans VRAM derrière elle. Ainsi, pendant que la ligne de balayage dessine l'image d'écran pour la dernière image, vous dessinez l'image suivante derrière la ligne de balayage.

En général, vous essayez de terminer le dessin de l'image de l'image suivante avant que la ligne de numérisation ne vous "chevauche" en revenant et en dépassant les pixels que vous dessinez, et aussi pour ne jamais devancer la ligne de numérisation, ou bien votre nouveau cadre pourrait s'insérer dans ce qui aurait dû être le cadre précédent.

Pour cette raison, le rendu à tampon unique fonctionnait généralement lui-même en dessinant des lignes de balayage, de haut en bas et de gauche à droite. Si vous dessiniez dans un autre ordre, il était probable que la ligne de balayage se reproduirait et repèrerait des morceaux de la "prochaine" image que vous n'aviez pas encore pu dessiner.

Notez que dans les systèmes d'exploitation modernes, vous n'avez généralement jamais la possibilité de dessiner à tampon unique, bien que cela soit assez courant il y a trente ans. (ça alors je me sens vieux - c'est ce que je faisais quand j'ai commencé dans le développement de jeux)

Double tampon

C'est beaucoup, beaucoup plus simple que l'une ou l'autre des stratégies précédentes.

Dans un système à double tampon, nous avons suffisamment de mémoire pour stocker deux images d'écran différentes, et nous désignons donc l'une d'entre elles comme "tampon avant" et l'autre, "tampon arrière". Le "tampon avant" est ce qui est actuellement affiché, et le "tampon arrière" est l'endroit où nous dessinons actuellement.

Une fois que nous avons fini de dessiner une image d'écran sur le tampon arrière, nous attendons jusqu'à vsync, puis échangez les deux tampons. De cette façon, le tampon arrière devient le tampon avant, et vice versa, et tout l'échange s'est produit alors que le moniteur ne dessinait rien.

Triple tampon

Un problème souvent soulevé avec les approches à double tampon est qu'après avoir fini de dessiner sur le tampon arrière, nous devons simplement nous asseoir en attendant vsync avant de pouvoir échanger les tampons et continuer à travailler; nous aurions pu faire des calculs pendant ce temps! De plus, tout le temps que nous attendons pour permuter entre les tampons, l'image dans ce tampon arrière vieillit de plus en plus, augmentant ainsi la latence perçue de l'utilisateur.

Dans les systèmes à triple tampon, nous créons nous-mêmes trois tampons - un tampon avant et deux tampons arrière. L'idée est la suivante:

Le moniteur affiche le tampon avant, et nous dessinons dans le tampon arrière # 1. Si nous finissons de dessiner dans le tampon arrière # 1 avant que le moniteur ne termine de dessiner le tampon avant, alors au lieu d'attendre vsync, nous commençons immédiatement à dessiner la prochaine image dans le tampon arrière # 2. Si nous terminons et que vsync n'est toujours pas venu, nous commençons à revenir dans le tampon arrière n ° 1, etc. L'idée est que lorsque vsync se produira finalement, l'un ou l'autre de nos tampons arrière sera complet et que l'un pourra être échangé contre le tampon avant.

L'avantage de la triple mise en mémoire tampon est que nous ne perdons pas le temps que nous avons passé à attendre vsync dans l'approche de double mise en mémoire tampon, et l'image permutée sur la mémoire tampon avant peut être "plus fraîche" que celle qui attendait vsync depuis 8 ms. L'inconvénient de la triple mise en mémoire tampon est que nous avons besoin de mémoire supplémentaire pour stocker l'image d'écran supplémentaire, et que notre utilisation CPU / GPU sera plus élevée (encore une fois, car nous ne ralentissons pas pour attendre vsync).

En règle générale, les pilotes modernes effectuent souvent une triple mise en tampon transparente, en arrière-plan. Vous écrivez votre code pour effectuer une double mise en mémoire tampon, et le pilote vous rendra le contrôle tôt, et gérera simplement en interne le nombre de tampons antérieurs qu'il souhaite utiliser, sans que votre code ne s'en rende compte.

Les fournisseurs de GPU recommandent actuellement de ne pas implémenter vous-même la triple mise en mémoire tampon - le pilote le fera automatiquement pour vous.

Trevor Powell
la source
7
Ceci est une réponse incroyablement détaillée, et explique pourquoi beaucoup de choses sont faites comme elles sont (comme l'espace de coordonnées d'écran, etc.). A également répondu à ma question "pourquoi ne pas quadrupler les tampons? Quintuple?" Je ne savais pas que l'échange de tampons s'était produit en arrière-plan, ce qui signifie que deux tampons arrière sont le maximum nécessaire. Upvote.
lunchmeat317
En fait, il existe une mémoire tampon quad. Il s'agit d'un double tampon pour une vue stéréoscopique. swiftless.com/tutorials/opengl/smooth_rotation.html
Narek
@Narek No. Citant à partir de votre lien: "Vous ne pouvez pas vraiment activer la mise en mémoire tampon quad réelle dans les environnements graphiques informatiques car il n'y a pas de vrai point". Le fait de suggérer que la double mise en mémoire tampon sur deux vues différentes simultanément serait une "mise en mémoire tampon quadruple" est juste un jeu de mots amusant; pas quelque chose de réel.
Trevor Powell,
@TrevorPowell Ajout d'une partie que vous avez oublié d'inclure: "Eh bien, la mise en mémoire tampon quad se réfère généralement à la double mise en mémoire tampon dans un environnement stéréoscopique. Par exemple: vous avez deux écrans, généralement à des fins 3D et chaque œil est à double tampon." Maintenant, le contexte pourrait être plus clair.
Narek
@TrevorPowell Votre point est tout à fait clair cependant. Il n'est pas logique d'avoir plus de 3 tampons pour un seul tampon de rendu.
Narek