Que recherchez-vous ?
Hero background image
Gestion de l'utilisation du GPU pour les jeux PC et console

Il s'agit du troisième d'une série d'articles qui présente des conseils d'optimisation pour vos projets Unity. Utilisez-les comme guide pour fonctionner à des fréquences d'images plus élevées avec moins de ressources. Une fois que vous avez essayé ces bonnes pratiques, assurez-vous de consulter les autres pages de la série :

Comprenez les limites de votre matériel cible et comment profiler le GPU pour optimiser le rendu de vos graphiques. Essayez ces conseils et bonnes pratiques pour réduire la charge de travail sur le GPU.

Découvrez de nombreuses autres bonnes pratiques dans le livre électronique gratuit, Optimisez vos performances de jeu pour console et PC.

SRP Batcher dans le moteur Unity
SRP BATCHER VOUS AIDE À GROUPER LES REQUÊTES.
Utiliser le traitement par lots d'appels de tirage

Pour dessiner un GameObject à l'écran, Unity émet un appel de dessin à l'API graphique (par exemple, OpenGL, Vulkanou Direct3D). Chaque appel au tirage au sort nécessite beaucoup de ressources.

Les changements d'état entre les appels de tirage, tels que la commutation de matériaux, peuvent entraîner une surcharge de performances du côté du processeur. Le matériel PC et console peut générer de nombreux appels de tirage, mais la surcharge de chaque appel reste suffisamment élevée pour justifier d'essayer de les réduire. Sur les appareils mobiles, l’optimisation des appels est vitale. Vous pouvez y parvenir grâce au tirage par lots d'appels.

Le traitement par lots d’appels Draw minimise ces changements d’état et réduit le coût CPU du rendu des objets. Unity peut combiner plusieurs objets en moins de lots en utilisant plusieurs techniques avec le pipeline de rendu haute définition (HDRP) ou le pipeline de rendu universel (URP) :

  • Lotage SRP : Activez le SRP Batcher dans Pipeline Asset sous Advanced. Lors de l'utilisation de shaders compatibles, SRP Batcher réduit la configuration du GPU entre les appels de dessin et rend les données matérielles persistantes dans la mémoire du GPU. Cela peut également accélérer considérablement les temps de rendu de votre processeur. Utilisez moins de variantes de shader avec un minimum de mots-clés pour améliorer le traitement par lots SRP. Consultez la documentation SRP pour voir comment votre projet peut tirer parti de ce flux de travail de rendu.
  • Instanciation GPU : Si vous disposez d'un grand nombre d'objets identiques avec le même maillage et le même matériau, utilisez l'instanciation GPU pour les regrouper via le matériel graphique. Pour activer l'instanciation GPU, sélectionnez votre matériel dans la fenêtre Projet de l' Inspecteur, puis cochez Activer l'instanciation.
  • Lotage statique : Pour une géométrie immobile, Unity peut réduire les appels de dessin pour les maillages partageant le même matériau. C'est plus efficace que le traitement par lots dynamique, mais utilise plus de mémoire. Marquez tous les maillages qui ne bougent jamais comme Batching Static dans l’inspecteur. Unity combine tous les maillages statiques en un seul grand maillage au moment de la construction. La classe StaticBatchingUtility vous permet également de créer ces lots statiques au moment de l'exécution (par exemple, après avoir généré un niveau procédural de pièces immobiles).
  • Traitement par lots dynamique : Pour les petits maillages, Unity peut regrouper et transformer les sommets sur le CPU, puis les dessiner tous en une seule fois. Notez cependant que vous ne devez pas l'utiliser à moins d'avoir suffisamment de maillages low-poly (pas plus de 300 sommets chacun et 900 attributs de sommet au total). Sinon, l’activer fera perdre du temps CPU à rechercher de petits maillages à regrouper.

Vous pouvez maximiser le traitement par lots de quelques manières simples :

  • Utilisez le moins de textures possible dans une scène. Moins de textures nécessitent moins de matériaux uniques, ce qui les rend plus faciles à mélanger. De plus, utilisez des atlas de textures dans la mesure du possible.
  • Créez toujours des cartes lumineuses à la plus grande taille d'atlas possible. Moins de lightmaps nécessitent moins de changements d’état des matériaux, mais gardez un œil sur l’empreinte mémoire.
  • Faites attention à ne pas créer d'instances de matériaux involontairement. L'accès à Renderer.material dans les scripts duplique le matériau et renvoie une référence à la nouvelle copie. Cela rompt tout lot existant qui inclut déjà le matériau. Si vous souhaitez accéder au matériel de l'objet par lots, utilisez plutôtRenderer.sharedMaterial .
  • Gardez un œil sur le nombre de comptes de lots statiques et dynamiques par rapport au nombre total d'appels de tirage en utilisant le profileur ou les statistiques de rendu pendant l'optimisation.

Reportez-vous à la documentation sur le traitement par lots des appels Draw pour plus d'informations.

Interface du Frame Debugger
LA SOLUTION FRAME DEBUGGER DÉCOMPOSE CHAQUE FRAME DE RENDU.
Vérifiez le débogueur de trame

Utilisez Frame Debugger pour geler la lecture sur une seule image et suivre le processus de construction d'une scène par Unity. Ce faisant, vous pouvez identifier les opportunités d’optimisation. Recherchez les GameObjects qui s'affichent inutilement et désactivez-les pour réduire les appels de dessin par image.

L'un des principaux avantages de Frame Debugger est que vous pouvez associer un appel draw à un GameObject spécifique dans la scène. Cela facilite l'investigation de certains problèmes qui pourraient ne pas être possibles dans les débogueurs de trames externes.

remarque Le Frame Debugger n’affiche pas les appels de dessin individuels ni les changements d’état. Bien que seuls les profileurs GPU natifs puissent vous fournir des informations détaillées sur les appels de tirage et le timing, le Frame Debugger peut toujours être très utile pour déboguer les problèmes de pipeline ou les problèmes de traitement par lots.

Lisez la documentation de Frame Debugger pour plus de détails.

Optimiser le taux de remplissage et réduire le découvert

Le taux de remplissage fait référence au nombre de pixels que le GPU peut restituer à l'écran chaque seconde. Si votre jeu est limité par le taux de remplissage, cela signifie qu'il essaie de dessiner plus de pixels par image que ce que le GPU peut gérer.

Dessiner plusieurs fois sur le même pixel est appelé overdraw. L'overdraw diminue le taux de remplissage et coûte plus de bande passante mémoire. Les causes les plus courantes de découvert sont :

  • Géométrie opaque ou transparente superposée
  • Shaders complexes, souvent avec plusieurs passes de rendu
  • Particules non optimisées
  • Chevauchement des éléments de l'interface utilisateur

Bien que vous deviez minimiser son effet, il n’existe pas d’approche unique pour résoudre l’overdraw. Expérimentez avec les techniques suivantes pour réduire son impact.

Réduisez le nombre de lots

Comme pour les autres plateformes, l’optimisation sur consoles impliquera souvent de réduire les lots d’appels de tirage. Voici quelques techniques qui pourraient aider :

  • Utilisez l'élimination d'occlusion pour supprimer les objets cachés derrière les objets de premier plan et réduire le dépassement. Sachez que cela nécessite un traitement CPU supplémentaire, utilisez donc le profileur pour vérifier que déplacer le travail du GPU vers le CPU est réellement bénéfique.
  • L'instanciation GPU peut également réduire vos lots si vous avez de nombreux objets partageant le même maillage et le même matériau. Limiter le nombre de modèles dans votre scène peut améliorer les performances. Si c'est fait avec art, vous pouvez créer une scène complexe sans la rendre répétitive.
  • Le SRP Batcher peut réduire la configuration du GPU entre les appels de tirage en regroupant les commandes GPUBind et Draw . Pour bénéficier de ce traitement par lots SRP, utilisez autant de matériaux que nécessaire, mais limitez-les à un petit nombre de shaders compatibles (par exemple, les shaders Lit et Unlit dans URP et HDRP).
Interface d'Occlusion Culling
UN EXEMPLE D'OCCLUSION CULLING.
Faites attention à l'abattage

L'élimination se produit pour chaque caméra et peut avoir un impact important sur les performances, en particulier lorsque plusieurs caméras sont activées simultanément. Unity utilise deux types de sélection :

  • L'élimination des troncs est effectuée automatiquement sur chaque caméra. Il garantit que les GameObjects en dehors de View Frustum ne sont pas rendus pour économiser les performances.
  • Vous pouvez définir manuellement les distances de sélection par couche via Camera.layerCullDistances. Cela vous permet d'éliminer les petits GameObjects à une distance plus courte que la propriétéfarClipPlane par défaut. Pour ce faire, organisez les GameObjects en Layers. Utilisez le tableau .layerCullDistances pour attribuer à chacune des 32 couches une valeur inférieure à farClipPlane (ou utilisez 0 pour définir par défaut farClipPlane).
  • Unity sélectionne d'abord par couche. Il conserve uniquement les GameObjects sur les calques utilisés par la caméra. Ensuite, l'élimination de Frustum supprime tous les GameObjects en dehors de Camera Frustum.
  • L'élimination du Frustum est effectuée sous la forme d'une série de tâches qui exploitent les threads de travail disponibles. Chaque test d'élimination des couches est rapide (essentiellement juste une petite opération de masque). Cependant, ce coût pourrait encore s’additionner à un grand nombre de GameObjects. Si cela devient un problème pour votre projet, vous devrez peut-être implémenter un système pour diviser votre monde en « secteurs » et désactiver les secteurs qui se trouvent en dehors du Camera Frustum afin de soulager une partie de la pression sur le système de sélection des couches/Frustum d'Unity.
  • L'élimination de l'occlusion supprime tous les GameObjects de la vue Jeu si la caméra ne peut pas les voir. Les objets cachés derrière d'autres objets peuvent potentiellement encore restituer et coûter des ressources. Utilisez l’élimination par occlusion pour les supprimer.
  • Par exemple, le rendu d'une pièce n'est pas nécessaire si une porte est fermée et que la caméra ne peut pas voir l'intérieur de la pièce. Si vous activez l'élimination d'occlusion, cela peut augmenter considérablement les performances, mais également utiliser plus d'espace disque, de temps CPU et de RAM. Unity prépare les données d'occlusion pendant la construction, puis doit les charger du disque vers la RAM lors du chargement d'une scène.
  • Alors que l'élimination de Frustum en dehors de la vue Caméra est automatique, l'élimination d'Occlusion est un processus complexe. Marquez simplement vos objets comme Static, Occludersou Occludees, puis effectuez une cuisson via la boîte de dialogue Fenêtre > Rendu > Occlusion .

Consultez le didacticiel Travailler avec l’élimination des occlusions pour en savoir plus.

Tirer parti de la résolution dynamique

Le paramètre Autoriser la caméra à résolution dynamique vous permet de mettre à l'échelle dynamiquement des cibles de rendu individuelles afin de réduire la charge de travail sur le GPU. Dans les cas où la fréquence d'images de l'application diminue, vous pouvez réduire progressivement la résolution pour maintenir une fréquence d'images cohérente.

Unity déclenche cette mise à l'échelle si les données de performances suggèrent que la fréquence d'images est sur le point de diminuer en raison de la limitation du GPU. Vous pouvez également déclencher cette mise à l’échelle de manière préventive manuellement avec un script. Ceci est utile si vous approchez d’une section de l’application gourmande en GPU. Si elle est mise à l'échelle progressivement, la résolution dynamique peut être presque imperceptible.

Reportez-vous à la page de manuel de résolution dynamique pour obtenir la liste des plates-formes prises en charge.

Démonstration de Camera stacking
EMPILEMENT DE CAMÉRA EN URP : LE PISTOLET ET LE RENDU D'ARRIÈRE-PLAN AVEC DIFFÉRENTS RÉGLAGES DE CAMÉRA.
Vérifier plusieurs vues de caméra

Parfois, vous devez effectuer le rendu depuis plusieurs points de vue au cours de votre partie. Par exemple, il est courant dans un jeu de tir à la première personne (FPS) de dessiner l'arme du joueur et l'environnement séparément avec différents champs de vision (FOV). Cela empêche les objets du premier plan de paraître déformés à travers le champ de vision grand angle de l'arrière-plan.

Vous pouvez utiliser Camera Stacking dans URP pour afficher plusieurs vues de caméra. Cependant, une sélection et un rendu importants sont encore effectués pour chaque caméra. Chaque caméra entraîne une certaine surcharge, qu'elle effectue un travail significatif ou non.

Utilisez uniquement les composants de caméra requis pour le rendu. Sur les plates-formes mobiles, chaque caméra active peut utiliser jusqu'à 1 ms de temps CPU, même sans aucun rendu.

Utiliser le niveau de détail

À mesure que les objets s'éloignent, le niveau de détail (LOD) peut les ajuster ou les modifier pour utiliser des maillages de résolution inférieure avec des matériaux et des shaders plus simples. Cela renforce les performances du GPU.

Consultez le cours Travailler avec les LOD sur Unity Learn pour plus de détails.

Interface de post-traitement
SIMPLIFIEZ AU MAXIMUM LES EFFETS DE POST-TRAITEMENT.
Effets de post-traitement du profil

Profilez vos effets de post-traitement pour voir leur coût sur le GPU. Certains effets plein écran, comme Bloom et Depth of Field, peuvent être coûteux, cela vaut donc la peine d'expérimenter jusqu'à ce que vous trouviez l'équilibre souhaité entre qualité visuelle et performances.

Le post-traitement ne fluctue pas beaucoup au moment de l'exécution. Une fois que vous avez déterminé vos remplacements de volume, attribuez aux effets de post-traitement une partie statique de votre budget total d'images.

Évitez les shaders de tessellation

La tessellation subdivise une forme en versions plus petites d'elle-même, ce qui peut améliorer les détails grâce à une géométrie accrue. Bien qu'il existe des exemples où la tessellation a le plus de sens, comme l'écorce d'arbre dans la démo Unity Book of the Dead, essayez d'éviter la tessellation sur les consoles car elles sont chères sur le GPU.

En savoir plus sur la démo de Book of the Dead ici.

Remplacer les shaders de géométrie par des shaders de calcul

Comme les shaders de tessellation, les shaders de géométrie et de vertex peuvent s'exécuter deux fois par image sur le GPU : une fois pendant le pré-passage en profondeur, et de nouveau pendant le passage d'ombre.

Si vous souhaitez générer ou modifier des données de sommet sur le GPU, un shader de calcul est souvent le meilleur choix, surtout par rapport à un shader géométrique. Effectuer le travail dans un shader de calcul signifie que le vertex shader qui restitue réellement la géométrie peut fonctionner beaucoup plus rapidement.

En savoir plus sur les concepts fondamentaux de Shader.

Graphiques sur le rapport entre bonne et mauvaise occupation du front d'onde
RAPPORT ENTRE BONNE ET MAUVAISE OCCUPATION DU FRONT D'ONDE
Viser une bonne occupation du front de mer

Lorsque vous envoyez un appel de dessin au GPU, ce travail est divisé en plusieurs fronts d'onde que Unity distribue sur les SIMD disponibles dans le GPU. Chaque SIMD dispose d’un nombre maximum de fronts d’onde pouvant fonctionner en même temps.

L'occupation du front d'onde fait référence au nombre de fronts d'onde actuellement utilisés par rapport au maximum. Il mesure dans quelle mesure vous utilisez le potentiel du GPU. Les outils de profilage pour le développement de consoles montrent l'occupation du front d'onde de manière très détaillée.

Dans l'exemple ci-dessus tiré du Book of the Deadde Unity, les fronts d'onde du vertex shader apparaissent en vert et les fronts d'onde du pixel shader apparaissent en bleu. Sur le graphique du bas, de nombreux fronts d'onde du vertex shader apparaissent sans grande activité du pixel shader. Cela montre une sous-utilisation du GPU.

Si vous effectuez beaucoup de travaux de vertex shader qui ne génèrent pas de pixels, cela peut indiquer une inefficacité. Même si une faible occupation du front d'onde n'est pas nécessairement mauvaise, c'est une mesure que vous pouvez utiliser pour commencer à optimiser vos shaders et à rechercher d'autres goulots d'étranglement. Par exemple, si vous rencontrez un blocage dû à des opérations de mémoire ou de calcul, l’augmentation de l’occupation peut améliorer les performances. D’un autre côté, un trop grand nombre de fronts d’onde en vol peut entraîner une destruction du cache et une diminution des performances.

Utiliser le calcul asynchrone

Si vous sous-utilisez parfois le GPU, vous pouvez tirer parti du calcul asynchrone pour déplacer le travail des shaders de calcul en parallèle avec votre file d'attente graphique. Par exemple, lors de la génération de la carte d'ombre, le GPU effectue un rendu en profondeur uniquement. Très peu de travaux de pixel shader ont lieu à ce stade et de nombreux fronts d'onde restent inoccupés.

Si vous pouvez synchroniser certains travaux de shader de calcul avec le rendu en profondeur uniquement, cela permet une meilleure utilisation globale du GPU. Les fronts d’onde inutilisés peuvent aider à l’occlusion ambiante de l’espace d’écran (SSAO) ou à toute tâche complétant le travail en cours.

Regardez cette session sur l'optimisation des performances pour les consoles haut de gamme de Unite.

Art clé de l'unité 21 11
Obtenez le livre électronique gratuit

L'un de nos guides les plus complets rassemble plus de 80 conseils pratiques sur la façon d'optimiser vos jeux pour PC et console. Créés par nos ingénieurs experts en Accelerate Solutions , ces conseils approfondis vous aideront à tirer le meilleur parti de Unity et à améliorer les performances de votre jeu.

Vous avez aimé ce contenu ?