Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Optimisation GPU

Introduction

La demande de nouvelles fonctionnalités graphiques et de progrès garantit presque que vous rencontrerez des goulots d'étranglement graphiques. Certains d'entre eux peuvent être du côté du CPU, par exemple dans les calculs à l'intérieur du moteur Godot pour préparer les objets pour le rendu. Des goulots d'étranglement peuvent également se produire dans le CPU dans le pilote graphique, qui trie les instructions à transmettre au GPU, et dans le transfert de ces instructions. Et enfin, des goulots d'étranglement se produisent également dans le GPU lui-même.

Les goulets d'étranglement dans le rendu sont très spécifiques au matériel. Les GPU mobiles en particulier peuvent avoir du mal à rendre des scènes qui s'exécutent facilement sur un ordinateur de bureau.

La compréhension et l'étude des goulets d'étranglement GPU sont légèrement différentes de la situation du CPU. En effet, souvent, vous ne pouvez modifier les performances qu'indirectement, en changeant les instructions que vous donnez au GPU. De plus, il peut être plus difficile de prendre des mesures. Dans de nombreux cas, la seule façon de mesurer les performances est d'examiner les changements dans le temps passé à rendre chaque image.

Draw calls, les changements d'état et APIs

Note

La section suivante ne concerne pas les utilisateurs finaux, mais elle est utile pour fournir des informations générales qui seront utiles dans les sections suivantes.

Godot sends instructions to the GPU via a graphics API (Vulkan, OpenGL, OpenGL ES or WebGL). The communication and driver activity involved can be quite costly, especially in OpenGL, OpenGL ES and WebGL. If we can provide these instructions in a way that is preferred by the driver and GPU, we can greatly increase performance.

Presque chaque commande API dans OpenGL nécessite une certaine quantité de validation, pour s'assurer que le GPU est dans le bon état. Même des commandes apparemment simples peuvent entraîner une avalanche de tâches internes en coulisses. Par conséquent, l'objectif est de réduire ces instructions au strict minimum et de grouper autant que possible les objets similaires afin qu'ils puissent être rendus ensemble, ou avec le minimum de ces changements d'état coûteux.

Traitement 2D par lots

In 2D, the costs of treating each item individually can be prohibitively high - there can easily be thousands of them on the screen. This is why 2D batching is used with OpenGL-based rendering methods. Multiple similar items are grouped together and rendered in a batch, via a single draw call, rather than making a separate draw call for each item. In addition, this means state changes, material and texture changes can be kept to a minimum.

Vulkan-based rendering methods do not use 2D batching yet. Since draw calls are much cheaper with Vulkan compared to OpenGL, there is less of a need to have 2D batching (although it can still be beneficial in some cases).

Traitement 3D par lots

In 3D, we still aim to minimize draw calls and state changes. However, it can be more difficult to batch together several objects into a single draw call. 3D meshes tend to comprise hundreds or thousands of triangles, and combining large meshes in real-time is prohibitively expensive. The costs of joining them quickly exceeds any benefits as the number of triangles grows per mesh. A much better alternative is to join meshes ahead of time (static meshes in relation to each other). This can be done by artists, or programmatically within Godot using an add-on.

Il y a également un coût au traitement par lots d'objets en 3d. Plusieurs objets rendus comme un seul ne peuvent pas être occultés individuellement. Une ville entière qui est hors écran sera quand même rendue si elle est jointe à un seul brin d'herbe qui est à l'écran. Par conséquent, vous devez prendre en compte l'emplacement des objets et de leur occlusion en compte quand vous tentez de traiter des objets 3D en lot. Malgré cela, les avantages de joindre des objets statiques l'emportent souvent sur d'autres considérations, en particulier pour un grand nombre d'objets à peu de polygones.

Pour plus d'informations sur les optimisations spécifiques à la 3D, voir Optimiser les performances 3D.

Reuse shaders and materials

The Godot renderer is a little different to what is out there. It's designed to minimize GPU state changes as much as possible. StandardMaterial3D does a good job at reusing materials that need similar shaders. If custom shaders are used, make sure to reuse them as much as possible. Godot's priorities are:

  • Réutilisation des matériaux : Moins il y a de matériaux différents dans la scène, plus le rendu sera rapide. Si une scène a une quantité énorme d'objets (des centaines ou des milliers), essayez de réutiliser les matériaux. Dans le pire des cas, utilisez des atlas pour réduire la quantité de changements de texture.

  • Reusing Shaders: If materials can't be reused, at least try to reuse shaders. Note: shaders are automatically reused between StandardMaterial3Ds that share the same configuration (features that are enabled or disabled with a check box) even if they have different parameters.

If a scene has, for example, 20,000 objects with 20,000 different materials each, rendering will be slow. If the same scene has 20,000 objects, but only uses 100 materials, rendering will be much faster.

Coût en pixel contre coût en sommet

Vous avez peut-être entendu dire que plus le nombre de polygones dans un modèle est faible, plus le rendu est rapide. C'est vraiment relatif et cela dépend de nombreux facteurs.

Sur un PC et une console modernes, le coût du sommet est faible. À l'origine, les GPU ne rendaient que les triangles. Cela signifie que chaque image :

  1. Tous les sommets ont dû être transformés par le CPU (y compris le clipping).

  2. Tous les sommets ont dû être envoyés à la mémoire GPU depuis la RAM principale.

Nowadays, all this is handled inside the GPU, greatly increasing performance. 3D artists usually have the wrong feeling about polycount performance because 3D modeling software (such as Blender, 3ds Max, etc.) need to keep geometry in CPU memory for it to be edited, reducing actual performance. Game engines rely on the GPU more, so they can render many triangles much more efficiently.

Sur les appareils mobiles, l'histoire est différente. Les GPU PC et Console sont des monstres de force brute qui peuvent tirer autant d'électricité qu'ils en ont besoin du réseau électrique. Les GPU mobiles sont limités à une petite batterie, ils doivent donc être beaucoup plus économes en énergie.

Pour être plus efficaces, les GPU mobiles tentent d'éviter l'overdraw. Overdraw arrive quand le même pixel à l'écran est rendu plus d'une fois. Imaginez une ville avec plusieurs bâtiments, les GPU ne savent pas ce qui est visible et ce qui est caché jusqu'à ce qu'ils le dessinent. Une maison peut être dessinée, puis une autre maison devant elle (le rendu a eu lieu deux fois pour le même pixel !). Les GPU PC ne s'en soucient normalement pas beaucoup et se contentent d'ajouter des processeurs de pixels au hardware pour augmenter les performances (mais cela augmente aussi la consommation d'énergie).

L’utilisation de plus d’énergie n’est pas une option sur mobile, donc les appareils mobiles utilisent une technique appelée tile-based rendering qui divise l’écran en grille. Chaque cellule conserve la liste des triangles qui y sont dessinés dessus et les trie par profondeur pour minimiser l'overdraw. Cette technique améliore les performances et réduit la consommation d'énergie, mais a un impact sur les performances des sommets. Par conséquent, moins de sommets et de triangles peuvent être traités pour le dessin.

De plus, le tile-based rendering a des difficultés quand il y a de petits objets avec beaucoup de géométrie dans une petite partie de l'écran. Cela oblige les GPU mobiles à mettre beaucoup de pression sur une seule cellule de l'écran, ce qui diminue considérablement les performances car toutes les autres cellules doivent attendre qu'elle termine pour pouvoir afficher l'image.

Pour faire court, ne vous inquiétez pas trop du nombre de sommet sur mobile, mais évitez les concentration de sommet sur de petites parties de l'écran. Si, un personnage, un PNJ, un véhicule, etc. est éloigné (donc il semble minuscule), utilisez plutôt un modèle à plus petit niveau de détail (LOD). Même sur les GPU de bureau, il est préférable d’éviter d’avoir des triangles plus petits que la taille d’un pixel à l’écran.

Faites attention au traitement supplémentaire des vertex requis lors de l'utilisation :

  • Skinning (animation squelettique)

  • Morphs (clés de forme)

Pixel/fragment shaders et taux de remplissage

In contrast to vertex processing, the costs of fragment (per-pixel) shading have increased dramatically over the years. Screen resolutions have increased: the area of a 4K screen is 8,294,400 pixels, versus 307,200 for an old 640×480 VGA screen. That is 27 times the area! Also, the complexity of fragment shaders has exploded. Physically-based rendering requires complex calculations for each fragment.

Vous pouvez vérifier assez facilement si un projet est limité en termes de taux de remplissage. Désactivez V-Sync pour éviter de limiter le nombre d'images par seconde, puis comparez les images par seconde lorsque vous utilisez une grande fenêtre, à celles très petite fenêtre vous pouvez également réduire de la même manière la taille de votre carte des ombres si vous utilisez des ombres. En général, vous constaterez que les FPS augmentent considérablement lorsque vous utilisez une petite fenêtre, ce qui indique que votre taux de remplissage est limité dans une certaine mesure. Si en revanche, les FPS augmentent peu ou pas du tout, alors votre goulot d'étranglement est ailleurs.

You can increase performance in a fill rate-limited project by reducing the amount of work the GPU has to do. You can do this by simplifying the shader (perhaps turn off expensive options if you are using a StandardMaterial3D), or reducing the number and size of textures used. Also, when using non-unshaded particles, consider forcing vertex shading in their material to decrease the shading cost.

Voir aussi

On supported hardware, Variable rate shading can be used to reduce shading processing costs without impacting the sharpness of edges on the final image.

Lorsque vous ciblez des appareils mobiles, pensez à utiliser les shaders les plus simples possibles que vous pouvez raisonnablement vous permettre d'utiliser.

Lecture des textures

L'autre facteur qui intervient dans les shaders de fragments est le coût de la lecture des textures. La lecture des textures est une opération coûteuse, en particulier la lecture de plusieurs textures dans un seul fragment shader. De plus, il faut tenir compte du fait que le filtrage peut le ralentir davantage (filtrage trilinéaire entre les mipmaps, et calcul de moyenne). La lecture des textures est également coûteuse en termes de puissance, ce qui est un gros problème sur les mobiles.

Si vous utilisez des shaders tiers ou écrivez vos propres shaders, essayez d'utiliser des algorithmes qui nécessitent le moins de lecture de texture possible.

Compression de texture

Par défaut, Godot compresse les textures des modèles 3D lorsqu'ils sont importés en utilisant la compression de la RAM vidéo (VRAM). La compression Video RAM n'est pas aussi efficace en taille que PNG ou JPG lorsqu'elle est stockée, mais augmente considérablement les performances lors du dessin.

En effet, l'objectif principal de la compression de texture est la réduction de la bande passante entre la mémoire et le GPU.

En 3D, les formes des objets dépendent plus de la géométrie que de la texture, la compression n'est donc généralement pas perceptible. En 2D, la compression dépend davantage des formes à l'intérieur des textures, de sorte que les artefacts résultant de la compression 2D sont plus visibles.

En guise d'avertissement, la plupart des appareils Android ne prennent pas en charge la compression de texture des textures avec transparence (seulement opaque), gardez ceci à l'esprit.

Note

Même en 3D, les textures "pixel art" devraient avoir la compression VRAM désactivée car elle affectera négativement leur apparence, sans améliorer significativement les performances en raison de leur faible résolution.

Post-traitement et ombres

Les effets de post-traitement et les ombres peuvent également être coûteux en termes d'activité des shaders de fragments. Testez toujours l'impact de ces effets sur différent hardware.

Réduire la taille des shadowmaps peut augmenter les performances, tant en termes d'écriture que de lecture des shadowmaps. De plus, la meilleure façon d'améliorer les performances des ombres est de désactiver les ombres pour le plus grand nombre possible de lumières et d'objets. Les OmniLights/SpotLights plus petits ou plus éloignés peuvent souvent voir leurs ombres désactivées avec un faible impact visuel.

Transparence et mélange

Les objets transparents posent des problèmes particuliers d'efficacité de rendu. Les objets opaques (surtout en 3D) peuvent être rendus dans n'importe quel ordre et le tampon Z garantit que seuls les objets les plus à l'avant sont traité par un shader. Les objets transparents ou mélangés sont différents. Dans la plupart des cas, ils ne peuvent pas compter sur le tampon Z et doivent être rendus dans "l'ordre du peintre" (c'est-à-dire de l'arrière vers l'avant) pour avoir une apparence correcte.

Les éléments transparents sont aussi particulièrement mauvais pour le taux de remplissage, car chaque élément doit être dessiné, même si plus tard des éléments transparents seront dessinés par-dessus.

Les objets opaques n'ont pas à faire cela. Ils peuvent généralement tirer parti du tampon Z en écrivant d'abord dans le tampon Z, puis en exécutant le shader de fragment sur le fragment "gagnant", l'objet qui se trouve à l'avant pour un pixel particulier.

La transparence est particulièrement coûteuse lorsque plusieurs objets transparents se chevauchent. Il est généralement préférable d'utiliser une zone transparente aussi petite que possible afin de minimiser ces exigences de taux de remplissage, en particulier sur les téléphones portables, où le taux de remplissage est très coûteux. En effet, dans de nombreuses situations, rendre une géométrie opaque plus complexe peut s'avérer plus rapide que d'utiliser la transparence pour "tricher".

Conseil multi-plateforme

Si vous avez l'intention de publier sur plusieurs plates-formes, testez au début et souvent sur toutes vos plates-formes, en particulier mobiles. Développer un jeu sur un ordinateur de bureau puis essayer de le porter sur le mobile à la dernière minute est une recette pour le désastre.

In general, you should design your game for the lowest common denominator, then add optional enhancements for more powerful platforms. For example, you may want to use the Compatibility rendering method for both desktop and mobile platforms where you target both.

Rendu mobile/tuile

Comme décrit ci-dessus, les GPU des appareils mobiles fonctionnent de manière radicalement différente des GPU des ordinateurs de bureau. La plupart des appareils mobiles utilisent des rendus par tuiles. Ces derniers divisent l'écran en tuiles de taille régulière qui s'intègrent dans une mémoire cache super rapide et réduisent les opérations de lecture et d'écriture dans la mémoire principale.

Il y a cependant quelques inconvénients. Le rendu par tuile rend certaines techniques beaucoup plus compliquées et coûteuses à mettre en œuvre. Les tuiles qui comptent sur les résultats du rendu de différentes tuiles ou sur les résultats d'opérations antérieures qui ont été préservés peuvent être très lents. Soyez très attentifs à tester les performances des shaders, des textures de viewport et du post-traitement.