Les mystères du 30 et 60 fps expliqués
Le site JulienChièze.com propose aux joueurs et créateurs de jeu vidéo de partager un avis, un point de vue. Les articles contributeurs ne reflètent que l'opinion de leur auteur et sont regroupés dans la section CLUB JV.
--------------------
Le but de tous les moteurs 3D est de créer, en temps réel, des rendus réalistes d’environnements 3D, d’objets (appelés Mesh) et de personnages. L’idée est d’essayer d’imiter le « monde réel » de la manière la plus crédible possible en termes de qualité graphique et de fluidité. Pour atteindre les 60 fps (frames per second ou images par seconde), nous faisons appel à de nombreuses astuces (voir triches) pour simuler les matériaux, ainsi que l’éclairage et les ombres en utilisant de la manière la plus efficace possible la puissance disponible.
J’aimerais partager avec vous un peu de ce que je sais sur les moteurs et jeux en 3D à travers une petite série d’articles. Ce premier s’occupera de faire une introduction générale aux moteurs 3D. Nous verrons aussi plus spécifiquement pourquoi et comment nous essayons de viser les sacro-saintes 60 images par seconde. Je vous expliquerai également pourquoi la plupart des jeux tournent à 30 fps sur console ou pourquoi nous avons besoin de 90 fps en VR. Nous essaierons ensuite de comprendre quelles sont les limites physiologiques de l’œil humain pour analyser une image en mouvement. Pour finir, nous parlerons du V-Sync et pourquoi le VRR (Variable Refresh Rate ou taux de rafraichissement variable) est la solution que nous attendions tous !
Mais au fait, savez-vous pourquoi nous essayons souvent de viser du 60 fps, le but ultime pour faire plaisir aux joueurs les plus exigeants ?
Tesla, le fautif désigné pour les 60 fps
Il nous faut voyager dans le passé et comprendre comment un choix, fait il y a longtemps par Tesla, a eu un impact sur les jeux vidéo (l’ingénieur prodige, pas le fabricant de voiture). Comment ça ?!? Tesla est à l’origine du 60 fps dans les jeux ? Eh oui !
Comme expliqué dans cet article (en anglais) : Why Is the US Standard 60 Hz?, lorsque Tesla faisait ses recherches sur la manière optimale de construire un réseau pour distribuer l’électricité, il s’est aperçu que le 220V / 60Hz était la solution la plus efficace. Cependant, toujours à cause de discussions avec Edison, son meilleur ennemi, il a dû faire un compromis. Ils se sont alors mis d’accord sur du 110V 60Hz (en courant alternatif). En Europe, nous avons décidé après la guerre de plutôt partir sur du 220V 50Hz.
Vous allez me dire : mais quel est le rapport avec la choucroute ?
C’est que l’air de rien, ce choix a dicté le taux de rafraîchissement de nos TVs et moniteurs cathodiques ! Cela est parfaitement expliqué dans cet article : What so special about the 60Hz refresh rate?. En substance, il indique que les écrans cathodiques étaient très sensibles aux champs magnétiques externes. Afin de minimiser les problèmes associés, il fut décidé d’aligner la fréquence de rafraîchissement verticale des TVs avec celle du courant électrique, soit 60Hz aux US et 50Hz en Europe. Pour des raisons de bande passante / performance, l’image était entrelacée 1 ligne sur 2. C’est avec l’arrivée du VGA progressif à 60Hz (640 x 480 pixels pour les plus vieux d’entre nous) que nous avons eu une image progressive à 60 images par seconde. Ensuite, même si les écrans plats (LCD, Plasma, OLED) n’avaient pas ce même problème de sensibilité électro-magnétique que les cathodiques, ils sont restés sur les standards établis, principalement à cause de la quantité monstrueuse de contenus vidéo existant en 50/60Hz.
Par ailleurs, comme expliqué précédemment, pour des raisons de bande passante, nous ne regardions pas de vidéos en 50 ou 60 images par seconde sur nos téléviseurs cathodiques mais à la moitié de cela (à cause de l’entrelacement d’une ligne sur deux). Cela nous donne donc du 25 fps en Europe et 30 fps aux US. Voilà. Vous savez désormais pourquoi les vidéos sont affichées en 30 fps aux US et 25 en Europe. Je ne vous expliquerai pas dans cet article pourquoi les films au cinéma (et sur les BluRay) sont en 24 fps, vous pouvez facilement trouver la raison en cherchant dans votre moteur de recherche favori. Spoiler : cela était principalement dû à des raisons économiques ; pas du tout lié à nos capacités physiologiques comme je peux parfois le lire, à tort.
Aujourd’hui, l’immense majorité des panneaux LCD de nos ordinateurs portables, smartphone ou TV utilise une fréquence de rafraîchissement de 60 Hz. C’est donc simplement pourquoi nous essayons de générer avec la carte graphique 60 images par seconde pour être parfaitement aligné avec le taux de rafraîchissement de l’écran.
Au passage, je vous demande de bien faire attention à deux concepts différents : le taux de rafraichissement (refresh rate) et la fréquence d’image (frame rate). Le refresh rate est la vitesse à laquelle l’écran est capable de mettre à jour / afficher une image complète. En général, il le fait ligne par ligne de haut en bas. Le frame rate est la vitesse à laquelle la machine est capable de produire / générer une nouvelle image en mémoire. Bien entendu, vous aurez sûrement déjà compris que ces deux taux ne seront pas forcément toujours synchronisés. La carte graphique (GPU) va peut-être générer moins d’images par seconde que ce que l’écran est capable d’afficher et vice-versa. Nous verrons alors plus loin quelles sont les différences stratégies pour gérer ces conflits en parlant du concept de V-Sync.
Mais avant cela, essayons rapidement de découvrir la difficile vie d’un développeur de jeux vidéo chargé de créer des mondes pour vous faire voyager.
Tout gérer en 16ms !
Pour faire du temps réel, cela implique de rendre une nouvelle image (frame) en moins de 16ms si vous visez les 60 fps (sur PC bien souvent) et 33ms pour du 30 fps (consoles). Vous voulez faire de la VR ? Votre budget frame vient de descendre à 11ms pour viser les 90 fps !
Nous verrons pourquoi ces chiffres exacts plus tard. Mais croyez-moi, c’est un exercice particulièrement difficile. En effet, un développeur de jeux vidéo travaille dans ce que l’on appelle une boucle de rendu ou game loop. Dans cette boucle, il faut bien évidemment demander au GPU de calculer la prochaine image à afficher mais il faut également gérer l’IA des méchants, le moteur physique (car vous aimez tout détruire sur votre passage), le moteur de collisions (pour ne pas passer à travers un mur), les effets sonores, les entrées (manettes, clavier/souris, casques VR, etc.), charger les ressources depuis le disque dur ou le SSD, gérer le réseau, etc. Bref, si un seul de ces éléments prends trop de temps pour faire son travail, votre budget de millisecondes va augmenter au-dessus de votre cible, le frame rate va descendre et l’expérience de jeu sera moins bonne. Vous allez louper la cible magique des 16ms et donc votre frame rate va être en dessous des 60fps. Et c’est là que commence le drame dans les réseaux sociaux… 😉
Un moteur 3D doit donc faire appel à beaucoup d’optimisations astucieuses pour tenter de faire un rendu photoréaliste avec le moins de ressources possible. C’est une bataille, ou un jeu pour certains, contre la machine afin d’extraire le moindre milliwatt de l’énergie disponible. Vous pouvez aussi considérer que les moteurs 3D passent leur temps à tricher. Ils vont essayer de vous faire croire que certains rendus visuels sont réels en utilisant des astuces optiques. Nous verrons cela dans le prochain article consacré aux shaders.
Les deux pièces maitresses utilisées par le moteur 3D est le CPU principal (ou plutôt devrais-je dire le multi-CPUs comme tous les CPUs sont désormais multicœurs) ainsi que le GPU, la puce graphique, qui embarque des centaines (si ce n’est des milliers) de petits processeurs dédiés. Dans le schéma précédent, le GPU est chargé du rendu de la frame (de l’image) et le CPU du reste. Bien entendu, c’est le GPU qui va faire le plus gros du boulot sur le rendu 3D. Cependant, le CPU a également un rôle primordial pour les performances, ainsi que la vitesse du flot de données transitant entre le CPU et le GPU. L’architecture complète a donc un impact énorme sur les performances globales ainsi que sur la qualité du rendu final : la quantité de mémoire principale et vidéo, leur bande passante, les différents bus de données entre chaque composant, la présence de hardware dédié pour certaines tâches complexes, le type et la vitesse du disque (SSD ou non), etc. Aujourd’hui, on entend fréquemment parler de TeraFLOPS ou TFLOPS pour évaluer la puissance d’une machine. Il évalue souvent la puissance du GPU seul. C’est un indicateur intéressant pour avoir une idée de la performance d’un système (dans le cas d’un pur rendu 3D) mais on ne peut pas non plus résumer la performance d’un système complet à cette seule unité. 2 architectures proposant des TFLOPS similaires peuvent montrer des performances globales en jeu très différentes en fonction du reste de l’architecture. Tout est question d’équilibre. Malgré tout, si l’un des 2 systèmes propose un chiffre en TFLOPS vraiment supérieur à l’autre, il proposera normalement de meilleurs graphismes ou des rendus plus rapides.
Mais revenons au CPU. Si ce dernier prends trop de temps pour effectuer son travail (IA, physique, calculs matriciels ou chargement de données depuis le disque par exemple), le GPU sera condamné à attendre et ne pourra pas délivrer le FPS souhaité. Vous serez alors dans un scénario appelé CPU-bound en anglais. Le CPU sera le goulot d’étranglement, le facteur limitant. Le GPU, même si très puissant, ne pourra jamais être utilisé à son potentiel maximum. En effet, vous ne devez jamais oublier que les 16ms/60fps représentent le temps alloué à la machine pour effectuer l’ensemble de ses tâches : CPU, GPU, accès mémoire, I/O, etc. Pour être honnête, bien souvent en 3D, c’est le CPU qui ralenti l’ensemble et qui est le facteur limitant. C’est pourquoi cela ne sert à rien d’avoir un monstre de GPU si le CPU associé ou l’architecture l’accompagnant n’est pas à la hauteur ou si les bus de communication entre les 2 ne suivent pas.
De manière opposée, il peut avoir des cas où c’est la scène 3D qui est trop complexe pour être rendue : des objets avec trop de géométrie (polygones), des shaders trop complexes, etc. C’est alors le GPU qui va galérer à rendre une frame en dessous de 16ms. Vous serez alors dans un scénario GPU-bound.
Écrire un moteur de jeux 3D représente donc un art de gérer l’équilibre entre toutes ces contraintes. Comme vous pouvez vous en douter, c’est bien plus simple de trouver le bon équilibre sur une configuration matérielle figée (comme les consoles) plutôt que sur un PC proposant une riche diversité de composants hétérogènes. C’est pour cela également que vous avez plus d’options à gérer vous-même sur PC pour vous laisser choisir où mettre le curseur entre performance et qualité graphique, en fonction de vos préférences.
Ok, mais que se passe-t-il si le jeu n’arrive pas à atteindre le frame rate voulu (30 ou 60fps) ? Dans ces cas-là, nous utilisons ce que nous appelons des « profilers », des outils permettant de cartographier où nous passons le plus de temps. Cela permet alors de trouver l’éventuel goulot d’étranglement. Imaginons que l’outil révèle que c’est le CPU qui est à la peine dans une séquence particulière. C’est peut-être qu’il y a trop d’objets indépendants (des ennemis par exemple) à mettre à jour. Il suffit alors de baisser ce nombre d’objets. Si le GPU est celui qui souffre le plus, peut-être que nos modèles 3D sont trop détaillés. Vous voulez absolument conserver cette qualité graphique pour des raisons artistiques mais cela empêche d’atteindre les 60 fps ? Descendez à 30 fps si cela n’affecte pas trop le gameplay. Sinon il faut les simplifier. Il existe alors des outils ultra efficaces pour aider l’artiste 3D comme Simplygon destiné à faire de la « décimation ». Le logiciel va tenter de réduire le nombre de polygones et/ou de réduire la qualité des textures tout en gardant un rendu acceptable et proche de l’original. Vous voyez donc que le rôle de l’artiste 3D ainsi que du « level design » sont également critiques dans la gestion de la performance globale du jeu. Ils doivent également comprendre l’architecture cible de la machine de jeu afin de fabriquer leur contenu de la manière la plus optimisée qu’il soit. Il faut donc à tous les niveaux jouer à ce jeu d’équilibriste.
Afin d’illustrer tout cela, étudions ensemble un exemple interactif dans le navigateur. Nous allons jouer avec Babylon.js, un moteur WebGL open source géré et utilisé par Microsoft sur le web (Office l’utilise beaucoup aujourd’hui par exemple). C’est un moteur que j’ai co-crée avec mon copain David Catuhe (également appelé le maître des shaders et des matrices) il y a plusieurs années. J’ai appris énormément grâce à lui. Ouvrez la démo suivante puis cliquez sur « Control panel » puis « Debug » :
Cela va afficher notre « profiler » (appelé inspecteur) dans le panneau de droite.
Rendez-vous dans le tab dédié aux statistiques. Notre moteur affiche alors là où il passe le plus de temps pour chaque passe de rendu. Dans le cas de cette démo particulière, elle ne tourne pas à 60 fps sur la machine que j’utilise pour écrire l’article. Cela tourne plutôt entre 50 et 60 fps. Pourtant, comme vous pouvez le voir dans la copie d’écran, le temps pour calculer l’image complète (frame total) est bien inférieur à 16 ms puisqu’il est autour des 6 ms. Cela veut sûrement dire que ce n’est pas le GPU le goulot d’étranglement. En effet, si le CPU était assez puissant, et si l’écran le permettait, le GPU serait capable de rendre cette scène à 166 fps (valeur « Absolute FPS »). Alors que se passe-t-il ? Pour le comprendre, on peut utiliser les outils développeurs de Edge / Chrome (appuyez sur la touche F12 sur PC) et tenter d’analyser ce qu’il se passe grâce au tab « Performance » :
Dans cet copie d’écran, on peut voir que la « game loop » (gérée par l’API requestAnimationFrame en JavaScript) a besoin de 19 ms pour s’exécuter complètement, soit environ 52 fps (1000 / 19). Comme le GPU n’a consommé que 6 ms sur ces 19, nous sommes en dessous des 60 fps à cause du CPU. Nous sommes dans un scénario CPU-Bound. Si le sujet vous intéresse et que vous avez l’âme d’un développeur, jetez un œil à nos autres démos sur notre playground : https://playground.babylonjs.com
Après cette petite escapade technique avec les mains dans le cambouis, essayons maintenant de comprendre un peu comment fonctionne notre perception du mouvement.
Quelles sont les limites de l’œil humain et pourquoi 60 fps c’est mieux que 30 bon sang ?
Il faut absolument se pencher sur une question qui revient en boucle autour de ce fameux « frame rate ». Peut-on vraiment voir et sentir la différence entre du 30 et 60 fps voir plus ? Quelles sont les limites physiologiques de notre œil humain et de notre cerveau ?
Cette question m’a longtemps intriguée. Le meilleur article en parlant que j’ai trouvé est de loin le suivant : Why movies look weird at 48fps, and games are better at 60fps, and the uncanny valley…. Si vous maitrisez l’anglais, vous devez absolument le lire pour mieux comprendre comment notre œil fonctionne. Selon moi, la partie centrale dans cet article est la suivante : « le micro-trémoussement oculaire est un phénomène où les muscles de l’œil vibrent doucement à une fréquence d’environ 83,68 Hz (en moyenne, pour la plupart des gens). La plage s’étend en fait de 70 à 103 Hz ». L’article explique ensuite pourquoi une cadence de 41 fps semble la cible minimum pour avoir les meilleurs résultats d’extraction de l’information spatiale en mouvement.
Cet article, que je trouve génial, vous expliquera également comment orienter son choix entre résolution plus haute ou frame rate plus haut. Il explique notamment comment l’usage de grain simulé (comme dans TLOU2) ou d’anti-aliasing temporel permettent d’augmenter le confort visuel. Il permet également d’avoir des données factuelles et scientifiques expliquant pourquoi il est plus confortable pour nous de jouer à 60 fps plutôt que 30.
J’ai trouvé plein d’autres articles tentant de répondre à cette même question mais avec moins de références factuelles. Un bon exemple : What is the highest frame rate (fps) that can be recognized by human perception? At what rate do we essentially stop noticing the difference? . On peut ainsi lire que nous sommes capables de voir un flash très rapide ayant une fréquence de 1000 Hz dans une pièce totalement noire, ce qui est tout à fait vrai. Mais cela veut-il dire pour autant que nous sommes capables de capter correctement un objet en mouvement à 1000 fps ? D’après l’article précédent, je ne pense pas. Il y a apparemment une différence énorme entre notre capacité à être stimulé par une image / flash super rapide et notre capacité à traiter l’information spatiale en mouvement.
Cela est confirmé par un autre excellent article que je vous recommande : How many frames per second can the human eye really see? dont voici les grands extraits :
« La première chose à comprendre est que nous percevons inégalement les différents aspects de la vision. Détecter un mouvement n'est pas la même chose que détecter de la lumière. Autre chose : les différentes parties de l'œil se comportent différemment. Le centre de votre vision n'est pas aussi performant que la périphérie. De plus, il existe des limites naturelles et physiques à ce que nous pouvons percevoir. Il faut du temps pour que la lumière qui traverse votre cornée devienne une information sur laquelle votre cerveau peut agir, et notre cerveau ne peut traiter cette information qu'à une certaine vitesse ». D’ailleurs, le fait que nous soyons plus sensibles au mouvement en périphérie est le fruit de notre évolution en tant qu’animal pour fuir au plus vite face au danger 😉
Au passage, l’article explique en partie pourquoi nous visons les 90 fps en VR : « Mais à la périphérie de nos yeux, nous détectons incroyablement bien les mouvements. Avec un écran remplissant leur vision périphérique qui se met à jour à 60 Hz ou plus, de nombreuses personnes déclarent avoir la forte impression de bouger physiquement. C'est en partie pourquoi les casques RV, qui peuvent fonctionner dans la vision périphérique, se mettent à jour si rapidement (90 Hz) ». Des études ont également montré que ce taux de 90 fps permettait de réduire le phénomène de motion sickness en VR (ou cinétose en français) sur la plupart des gens.
La conclusion est intéressante :
- Certaines personnes peuvent percevoir les variations (clignotements) d’une source lumineuse à 50 ou 60 Hz. Certains le voient même sur une ampoule. Des fréquences supérieures permettent alors de réduire cette perception de clignotement de l’image.
- Nous détectons mieux le mouvement à la périphérie de notre vision mais l’image est moins nette qu’au centre.
- La manière dont nous percevons un flash dans une image est différente de la manière dont nous percevons le mouvement.
- Les gamers sont susceptibles d’avoir les yeux les plus sensibles et entrainés lorsqu’il s’agit de percevoir des changements dans une image. Eh oui, cela sert aussi à cela de jouer aux jeu vidéo 😊
- Ce n’est pas parce que l’on peut détecter une différence entre 2 frame-rates que cela implique nécessairement que notre temps de réaction sera supérieur.
En combinant tout ce que j’ai pu lire, j’en suis arrivé à la conclusion que d’aller au-dessus de 120 fps ne servira à rien pour la grande majorité des gens. Même si j’ai conscience des débats animés et passionnés à ce sujet. Ce qui est certain en revanche, c’est que l’on peut clairement ressentir la différence entre 30 et 60 fps.
Au passage, on comprend également mieux pourquoi les nouvelles technologies comme le VRS (Variable Rate Shading) sont particulièrement intéressantes. Notre vision centrale est très sensible aux détails là où notre vision périphérique est inversement plus sensible au mouvement. Profitons de cela pour baisser la qualité du rendu à la périphérie de l’image justement afin de pouvoir augmenter le FPS et donc satisfaire nos besoins de perception de mouvement !
La nouvelle Xbox Series X supporte cette technologie.
Arrivé ici, nous savons pourquoi nous sommes plus sensibles au 60 fps et pourquoi à cause de Tesla on est obligé de viser ce plateau. Mais que se passe-t-il au niveau de l’écran quand le rendu se trouve en dessous ou au-dessus de 60 fps ?
Les différentes stratégies pour adapter le nombre d’images par seconde au taux de rafraichissement
Comme expliqué précédemment, le frame rate est la puissante brute de votre machine/GPU pour générer un certain nombre d’images par seconde. Le refresh rate ou taux de rafraichissement est la vitesse à laquelle le matériel (l’écran) se nettoie et dessine une nouvelle image. Cela est exprimé en Hz. Le taux de rafraichissement d’un moniteur est fixe. La plupart du temps, il sera de 60 Hz. Cela veut donc dire que quelle que soit la source vidéo fournie, l’écran se mettra à jour toutes les 1/60s = 16,66ms. Bien entendu, comme nous en avons déjà parlé, le FPS lui va varier en fonction de la charge actuelle du GPU ou si le CPU a des difficultés à gérer la logique du jeu. Bref, la quasi-totalité du temps, vous devez faire rentrer un taux variable d’images par seconde dans un taux fixe de rafraichissement de l’écran. Donc comment s’en sortir ?
V-Sync on ou off ? Stuttering ou tearing ?
Qu’est-ce que le V-Sync ? Cela veut dire synchronisation verticale avec la fréquence fixe du moniteur. Comme je vous l’ai dit, la quasi-totalité des moniteurs tournent à 60 Hz. Il va donc demander au GPU une nouvelle image toutes les 16,6ms. Il va ensuite la dessiner à l’écran ligne par ligne de haut en bas.
Mais vous avez alors 2 options. Soit, vous synchronisez le GPU avec le taux de rafraichissement vertical. Soit, vous vous en fichez et vous balancez l’image vers l’écran dès qu’elle est prête sans tenir compte du taux de rafraichissement de ce dernier. C’est le mode V-Sync off.
Commençons par étudier ce cas.
V-Sync off
Si votre GPU génère plus d’images par seconde que ce que le moniteur peut afficher, une nouvelle image va donc arriver avant que l’écran n’ait fini de dessiner la précédente. Souvenez-vous, un écran va dessiner de haut en bas une nouvelle image à une cadence fixe, peu importe ce qu’il arrive. Résultat, le moniteur va commencer à dessiner une image en partant du haut et, en cours de route, il va dessiner le contenu d’une nouvelle image. Cela va être aléatoire. Il peut par exemple dessiner 40% d’une image puis continuer avec 60% de l’image suivante. Cela va engendre un déchirement de l’image (ou tearing en anglais) comme on peut le voir ci-dessous :
Bien entendu, vous aurez le même phénomène si le GPU génère moins d’images par seconde que le moniteur avec le V-Sync à off. Si l’image prend plus que 16ms à être calculée, l’écran se contentera de dessiner à nouveau l’image qu’il a en mémoire jusqu’à ce qu’il reçoive la nouvelle quelques ms plus tard. Il va donc continuer de dessiner en cours de route avec cette nouvelle image arrivant en retard et créer le même genre de déchirement d’image. Ce défaut dans l’image peut parfois être difficile à voir en mouvement s’il se trouve tout en haut ou tout en bas de l’écran. Mais si le déchirement se produit en plein milieu, vous pouvez être sûr que vous allez le voir et ne pas aimer cela.
En revanche, l’avantage de ce mode est que vous laissez le GPU produire autant d’images par seconde qu’il le peut, ce qui vous permettra d’avoir les meilleurs temps de réponse à vos inputs en jeu. C’est donc souvent le mode de jeu retenu par les joueurs qui veulent le taux de réponse le plus rapide qui à sacrifier le rendu de l’image en échange.
Regardons le fonctionnement de l’autre mode désormais.
V-Sync on
A nouveau, 2 cas possibles. Commençons par le meilleur des cas : votre GPU est suffisamment rapide pour produire plus d’images par seconde que le moniteur.
Comme vous pouvez le voir avec mes petites boites vertes, le GPU est en attente du signal du moniteur avant d’envoyer sa nouvelle image. Cela a pour conséquence bénéfique de totalement faire disparaitre le déchirement puisque le buffer d’image du GPU est synchronisé avec celui de l’écran. Dès que le GPU a fini de calculer son image, il se met en attente le temps que le moniteur finisse son job. Il sera donc certainement sous-utilisé.
Par ailleurs, pour être tout à fait exact, on utilise des « frame buffers » au niveau GPU. Le GPU n’attends pas vraiment totalement s’il est plus rapide que le moniteur. En général, on utilise une technique de « double buffering ». On dispose donc de 2 mémoires tampons dans lesquelles on dessine avec le GPU. Pendant que l’une des mémoires tampon (buffer) est lue pour être envoyée au moniteur pour affichage, un deuxième buffer est utilisé pour calculer l’image suivante. Une fois que le buffer 1 a été envoyé à l’écran, le buffer 2 devient le buffer principal pour la prochaine demande de rendu par l’écran et le buffer 1 devient le cache pour la prochaine image. Et ainsi de suite. Il existe même des techniques de « triple buffering » permettant du coup d’encaisser d’éventuels pics de charge ponctuelles du GPU. Cependant, si vous avez suivi les épisodes précédents, vous devriez avoir compris que cette technique de cache a un impact sur le temps de réponse de vos actions (input lag). Les jeux nerveux n’utilisent donc jamais le triple buffering.
Cet article de Techspot explique très bien les différentes stratégies de gestion de synchronisation. Je me suis permis de leur piquer ce graphique qui explique parfaitement ce qu’il se passe lorsque le V-Sync est activé et que le taux d’images par seconde est sous les 60 fps :
Ce diagramme est super intéressant. Si vous ne devez retenir qu’une seule chose de cet article, c’est lui. En le regardant, vous comprendrez que si vous manquez votre cible des 16.6ms (60 fps), l’écran doit absolument faire quelque chose pendant que le GPU est en train de terminer la prochaine image. Le plus simple ? Redessinons l’image précédente en attendant ! Malheureusement, cela va générer des saccades dans le mouvement (stutter en anglais).
Faisons une pause.
Il est extrêmement important que vous compreniez ce qu’il se passe. Si vous ne pouvez maintenir un rendu solide à 60 fps, la même image sera affichée 2 fois. Donc, c’est comme si vous affichiez une image pendant 33ms. Et donc, cela veut dire que vous faites un rendu à 30 fps ! Pour être plus précis, vous allez alterner entre du 30 et du 60 fps sur certaines frames (en fonction de la complexité de la scène actuelle). Cette bascule entre 30 et 60 fps, même temporaire, est très désagréable. Le double ou triple buffering permet d’absorber des baisses très brèves de frame rate mais si le rendu global moyen est sous les 60 fps, vous aurez de toutes façons des saccades dans les images en mouvement.
C’est donc pourquoi on choisit bien souvent de viser du 30 fps sur console plutôt que du 60. Le coût pour passer de 30 à 60 fps est très important et il n’est pas intéressant d’être entre les 2. Imaginez ainsi que votre GPU soit capable de rendre votre jeu à 45 fps. Et bah, sur un écran à fréquence fixe de 60 Hz, avec le V-Sync activé, il tournera de toutes façons à 30 fps à cause des explications précédentes. Vous ne pouvez pas être entre les 2 eaux. Si vous tournez à 45 fps sur une console, comme vous disposez d’un hardware figé, il est préférable d’utiliser ce budget de 15 images par seconde disponible pour en faire quelque chose d’autre : un rendu graphique supérieur, des objets plus détaillés, une meilleure IA, etc. Pour faire un jeu qui tourne à 60 fps, il faut avoir un rendu moyen super stable à 60 fps ou au-dessus. La moindre faute avec une image prenant plus de 16ms et vous descendez d’un seul coup à 30 fps. Cela ne pardonne pas.
Malgré tout, pour être honnête, 30 fps reste une expérience acceptable pour l’œil humain. Et nous avons vu qu’il existe des astuces pour augmenter la perception d’informations en mouvement même à 30 fps (grain simulé). Cela dépend bien entendu également du style de jeu. Un jeu à contenu narratif ne sera pas désagréable à 30 fps, là où un jeu de tir à la première personne ou un jeu de plateforme sera plus à l’aise sur du 60 fps. Nous avons également vu précédemment que nous commençons à être vraiment à l’aise autour de la plage des 40 fps pour percevoir le mouvement correctement. Mais il est préférable d’avoir un rendu stable à 30 fps que de tenter de viser du 60 fps rempli de saccades.
Rah, c’est quand même dommage cette histoire de 60 Hz qui force du 60 fps ! En plus, divisé par 2 à cause du V-Sync, on tombe à 30. Juste en dessous de notre plage de confort… Tout ça à cause de Tesla !
La solution tout attendue : Variable Refresh Rate
Jusqu`à présent, on forçait le GPU à s’adapter au taux de rafraichissement du moniteur avec tous les problèmes et la complexité que cela engendre. Mais pourquoi ne tout simplement pas inverser les rôles ? Pourquoi ne pas demander au GPU de piloter l’écran et de lui dire quand il doit se rafraichir ?
C’est exactement le concept du taux variable de rafraichissement ou Variable Refresh Rate en anglais. Le GPU va générer ses images aussi vite qu’il le peut puis va ensuite avertir le moniteur qu’il peut récupérer l’image pour la dessiner en temps réel. L’écran devient synchronisé sur la carte graphique et plus l’inverse. Nous avons simplement hérité des approches et technologies issues de l’ère des tubes cathodiques. Mais les panneaux LCD ou OLED ne sont pas forcés de suivre ces vieilles règles.
Grâce à cela, si le GPU rend la scène à 42 fps, le moniteur se mettra à jour à 42 Hz. Encore mieux, imagions que le rendu varie entre 30 et 60 fps. L’écran s’adaptera automatiquement entre 30 et 60 Hz en temps réel ! Cela élimine tous nos problèmes : plus de déchirement d’image, plus de saccades, plus de baisse soudaine à 30 fps. Cela permet une perception globale de fluidité grandement améliorée. Tenter d’aller au-dessus de 60 Hz dépendra de la puissance de la machine et de la technologie d’écran. Certains moniteurs peuvent monter jusqu’à 144 Hz voir plus et certaines TV récentes à 120 Hz.
Sur PC, cette technologie existe sous plusieurs formes. Soit chez nVidia avec le G-Sync, soit chez AMD avec le FreeSync. Sur consoles, les Xbox One S et Xbox One X supportent déjà la technologie FreeSync d’AMD. La prochaine génération de consoles PS5 et Xbox Series X supportent également le VRR grâce au HDMI 2.1 et ce, jusqu’à 120 Hz. Très récemment, quelques TV haut de gamme Samsung QLED ou LG OLED supportent le mode VRR via une prise HDMI 2.1. Cela veut dire qu’elles seront capables d’afficher des images plus fluides si les développeurs de jeux vidéo décident de faire appel à ce type de rendu.
Nous allons donc bientôt enfin nous libérer de cette prison des 60 fps dans laquelle Tesla nous avait honteusement enfermé.
J’espère que cet article vous aura aider à mieux comprendre la différence entre taux de rafraichissement et taux d’images par seconde. Vous devriez aussi mieux comprendre pourquoi il est préférable de viser un bon 30 fps lorsque le 60 devient trop contraignant, même si afficher du 60 fps ou plus permet d’avoir la meilleure des expériences sur notre perception du mouvement.
Auteur : David Rousset
David est Senior Program Manager dans la division Windows+Device / PAX à Microsoft Corp". Il a co-crée un moteur 3D open-source appelé Babylon.js et gère aujourd'hui un projet open-source appelé pwabuilder.com. Il travaille également avec des partenaires stratégiques pour les accompagner sur nos futurs OS et devices.
-----------------
Vous êtes joueur, créateur ou acteur de l'industrie du jeu vidéo et vous souhaitez partager un article, un édito, un dossier ? Vous pouvez proposer vos contenus via le formulaire de Contact (l'article doit être intégralement rédigé lors de l'envoi). Une curation en amont sera effectuée et les auteurs sélectionnés seront contactés avant publication sur le site.