Cet article est une traduction d’un article publié dans le blog de développement de Stadia. Vous pouvez retrouver l’article original en cliquant ici.
Les jeux vidéo sont des médias intéressants où la partie visuelle, les contrôles et le son deviennent une extension de votre expérience – jusqu’à ce que soudain, tout se bloque et que vous fassiez un bond de deux pas par rapport à l’endroit où vous vous trouviez. En tant qu’expérience immersive, nous voulons donc que l’aspect visuel soit fluide et que les transitions entre les zones soient rapides. Il est parfois intolérable qu’un écran de chargement prenne une ou deux minutes pour se terminer !
Un jeu est composé de plusieurs types de fichiers : des films, de l’audio, le binaire du jeu lui-même, des textures (images et descriptions d’objets), etc… Certains de ces éléments ne sont pas réellement pré-générés, du moins pas complètement – notamment les pipelines graphiques, tous les calculs liés aux shaders graphiques et la gestion du cache des pipelines.
Ce qu’on appelle pipeline graphique consiste en la séquence de calculs nécessaires pour aboutir à un rendu donné à un instant donné. Ces actions peuvent être éventuellement mises en cache afin de ne pas être re-calculées inutilement.
Dans cet article, nous parlerons des pipelines graphiques et de la mise en cache des pipelines. La compilation de ces pipelines graphiques est l’une des raisons courantes pour lesquelles les écrans de chargement dans les jeux vidéo peuvent prendre beaucoup de temps, et pourquoi l’image à l’écran peut sauter et bégayer, ou comme on dit en anglais : le jank. Ce jank peut se produire pour un certain nombre de raisons, mais celui résultant de la compilation des pipelines peut être corrigé en stockant les pipelines compilés dans un cache de pipelines. Nous allons jeter un coup d’œil sur la façon dont Stadia fonctionne pour fournir des caches de pipelines aux joueurs qui exécutent des jeux sur Stadia et grâce à l’agrégation des données dans le cloud, comment Stadia peut supprimer ce type de janks pour tous les utilisateurs au fil du temps. Si vous remarquez qu’un jeu fonctionne mieux qu’avant, c’est peut-être grâce à des joueurs comme vous qui font leur part en jouant au jeu !
Les pipelines côté Vulkan
Stadia utilise l’API graphique Vulkan qui fonctionne avec des pipelines de calcul et des pipelines graphiques pour exécuter un jeu. Le cœur d’un pipeline est le shader qui est comme un petit programme conçu pour traiter un élément précis du jeu. Certains jeux simples n’ont qu’une poignée de pipelines tandis que de gros titres plus gourmands peuvent en avoir des centaines de milliers. Le temps nécessaire à la compilation d’un pipeline est également très variable mais partons du principe qu’il faut 100ms en moyenne. Si un jeu doit calculer 35 000 pipelines pendant un écran de chargement, il y a environ une minute de travail à faire. Un GPU plus puissant peut aider bien sûr, mais cela ne suffit pas nécessairement et cela coûte cher.
Le problème de la compilation peut également se poser pendant le jeu lorsqu’un nouvel élément est rencontré par le joueur. Imaginons que vous exploriez un monde et que vous rencontriez un nouveau monstre qui nécessite la compilation de dix nouveaux pipelines pour pouvoir être rendu sur votre écran. Certains jeux abandonneront toutes les images jusqu’à ce que le rendu soit prêt, ce qui se traduira par des saccades, des ralentissements ou d’autres problèmes. D’autres continueront à rendre tout le reste de la scène jusqu’à ce que le monstre soit prêt, ce qui peut également être gênant lorsque le monstre apparaît soudainement alors qu’il était invisible jusque là.
Un cache de pipeline résout ces problèmes en stockant les pipelines compilés et calculés. Le temps de compilation de 100ms pour un pipeline se transforme alors en une simple recherche qui prend moins d’une milli-seconde lorsqu’il est dans le cache de pipeline, de sorte que la minute de travail pendant l’écran de chargement prend maintenant moins d’une seconde et les pipelines pour le monstre sont prêts au moment même du rendu de l’image où ils ont été demandés.
Les pipelines compilés dans un cache de pipeline ne sont valables que sur du matériel et des pilotes graphiques compatibles avec ceux pour lesquels le cache de pipeline a été créé. Lorsque l’un de ces éléments change, les pipelines compilés peuvent ne plus fonctionner et le pipeline devra être recompilé. Sur une console, la plupart des pipelines compilés peuvent être collectés et livrés avec le jeu puisque le matériel et les pilotes sont stables, mais ils peuvent subir des ratés. Pour les jeux sur PC, les pipelines sont généralement compilés pendant le processus d’installation du jeu ou lors d’un de ces caches est manquant, auquel cas ils sont écrits dans le stockage local du PC pour éviter les problèmes futurs pour cet utilisateur.
Pipelines graphiques et caches dans le cloud
En ce qui concerne le cloud gaming, nous savons que nous pouvons faire encore mieux pour empêcher ces ratés avant même qu’un joueur ne commence à jouer. Stadia exploite les capacités des architectures graphiques les plus modernes pour générer des pipelines graphiques pré-compilés. Les développeurs peuvent même fournir et inclure les données nécessaires à la construction d’un cache de pipeline. Ces données comprennent les programmes de shaders ainsi que les données utilisées pour construire le rendu, descripteurs et autres objets utilisés pour construire les pipelines de leurs jeux. Grâce à ces données, nous pouvons nous assurer que nous compilerons les pipelines pour alimenter le cache des pipelines d’un jeu en amont des mises à jour du matériel et des pilotes graphiques de Stadia. De cette façon, les problèmes résultant de la compilation des pipelines sont évités pour les joueurs qui jouent sur n’importe quelle configuration matérielle et pilotes graphiques.
Capturer tous les pipelines d’un jeu peut être une tâche monumentale voire impossible. Les pipelines peuvent avoir des propriétés générées par ordinateur où des parties de différents systèmes se combinent au moment de l’exécution pour générer un nouveau pipeline. Cela peut être évident dans des jeux comme Destiny 2 où un joueur peut mélanger et assortir des parties et des combinaisons de couleurs sur son avatar, alors que l’armure elle-même a une brillance, une réflexion et des textures grossières. La combinaison de tous ces shaders communs avec les shaders dynamiques qui sont ajoutés pendant l’exécution du jeu (comme dans Destiny 2 où l’on peut courir sur Titan tout en se tenant près d’une grenade solaire) forment les pipelines graphiques qui doivent être compilés. Chacune de ces combinaisons est difficile à générer à l’avance, de sorte qu’il y a toujours des problèmes causés par la compilation des pipelines pendant le jeu.
Nous avons résolu ce problème en construisant nos systèmes pour qu’ils ressemblent davantage à un PC, mais avec un répertoire de caches de pipelines distribué. Lorsque les joueurs rencontrent un pipeline qui doit être compilé au moment de l’exécution d’un jeu, nous essayons de collecter les données sources de ces pipelines à la fin de la session. Comme beaucoup de ces pipelines sont générés dynamiquement, nous avons mis en place plusieurs systèmes de confidentialité différentielle pour ne fusionner que les pipelines identiques entre les utilisateurs et supprimer automatiquement ceux qui ne le sont pas.
Ces pipelines sont donc fusionnés avec les pipelines fournis par le développeur et les nouveaux caches de pipelines enrichis sont déployés dans les data centers. La prochaine fois qu’un joueur rencontrera le même scénario, il ne sera pas confronté aux mêmes saccades graphiques ou aux temps de chargement trop longs. Cela permet d’exploiter efficacement la puissance de calcul des utilisateurs jouant à des jeux sur Stadia pour faire des économies pour les utilisateurs suivants. Au fil du temps, nous serons capables d’éliminer complètement les saccades graphiques de la compilation du pipeline grâce aux joueurs qui profitent de nos jeux dans le cloud.
— Derek Bulner, ingénieur logiciel et Bob Fraser, responsable technique.