Optimisation Vulkan du moteur Godot pour Android

Image de la mascotte de Godot Engine

Présentation

Godot Engine est un moteur de jeu multiplate-forme Open Source populaire, compatible avec Android. Godot peut être utilisé pour créer des jeux de pratiquement tous les genres et est compatible avec les graphismes 2D et 3D. La version 4 de Godot a introduit un nouveau système de rendu avec des fonctionnalités avancées pour des graphismes haute fidélité. Le moteur de rendu de Godot 4 est conçu pour les API graphiques modernes telles que Vulkan.

La Godot Foundation a fait appel aux experts en optimisation graphique de The Forge Interactive et a collaboré avec Google pour analyser et améliorer le moteur de rendu Vulkan de Godot 4, puis fusionner ces optimisations dans le dépôt du projet. Les optimisations aident les développeurs à améliorer les moteurs de rendu Vulkan personnalisés sur Android.

Méthode et résultats d'optimisation

Le processus d'optimisation a utilisé deux scènes 3D différentes dans Godot comme cibles de benchmarking. Le temps d'affichage des scènes a été mesuré sur plusieurs appareils à chaque itération d'optimisation. Pour être éligibles à l'inclusion, les modifications apportées au moteur de rendu devaient montrer une amélioration des performances sur au moins certains appareils testés et ne pas entraîner de régression des performances sur aucun appareil.

Plusieurs architectures de GPU Android populaires ont été utilisées lors des tests. Bien que de nombreuses optimisations aient apporté des améliorations générales, certaines ont eu un impact plus important sur des architectures de GPU spécifiques. La somme totale de tous les travaux d'optimisation a entraîné une réduction générale de 10 à 20 % du temps de frame du GPU.

Optimisation générale Vulkan

Forge a effectué une refactorisation architecturale générale du backend de rendu Vulkan de Godot pour améliorer les performances et aider le backend à évoluer à mesure que les demandes de rendu de contenu augmentent. Les optimisations ne sont pas spécifiques au matériel mobile, mais profitent à toutes les plates-formes Godot Vulkan.

Prise en charge du décalage UBO dynamique

Lors de la liaison d'un ensemble de descripteurs contenant un objet de tampon uniforme dynamique (UBO), Vulkan permet de spécifier des décalages dynamiques dans l'UBO dans les paramètres de liaison. Cette fonctionnalité peut être utilisée pour empaqueter des données pour plusieurs opérations de rendu dans un seul UBO, en reliant l'ensemble de descripteurs avec un décalage dynamique différent pour sélectionner les données appropriées pour le nuanceur. Le moteur de rendu Vulkan de Godot a été mis à jour pour pouvoir utiliser des décalages dynamiques au lieu d'initialiser toujours le décalage sur zéro. Cette amélioration permet d'optimiser l'efficacité à l'avenir.

Pools d'ensembles de descripteurs linéaires

Auparavant, le comportement par défaut du moteur de rendu Vulkan de Godot consistait à créer tous les pools de jeux de descripteurs à l'aide de l'indicateur VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, ce qui signifie que les allocations de jeux de descripteurs pouvaient être libérées dans le pool et que des reallocations pouvaient être effectuées à partir du pool. Ce mode imposait une surcharge supplémentaire par rapport aux pools de jeux de descripteurs, qui n'autorisent qu'une allocation linéaire suivie d'une réinitialisation totale du pool.

Dans la mesure du possible, les pools d'ensembles de descripteurs sont désormais créés en tant que pools linéaires sans définir VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT. Les pools linéaires sont ensuite réinitialisés dans leur ensemble si nécessaire. Ce travail comprend également une optimisation supplémentaire pour la liaison de lot de jeux de descripteurs lorsque cela est possible, ce qui réduit le nombre d'appels distincts à vkCmdBindDescriptorSets().

Compatibilité avec l'échantillonneur immuable

Les objets d'échantillonneur contenant des données de configuration d'échantillonnage sont généralement liés dans les données du jeu de descripteurs. Cette méthode permet de remplacer dynamiquement les objets d'échantillonnage dans les données de l'ensemble de descripteurs. Vulkan prend également en charge les échantillons immuables, qui encodent les données d'échantillonnage directement dans la mise en page de l'ensemble de descripteurs. Cette configuration d'échantillonneur est liée lors de la création du jeu de descripteurs et de l'état du pipeline, et ne peut pas être modifiée après la création.

Les échantillons immuables sacrifient la flexibilité pour ne plus avoir à gérer et lier des objets d'échantillonnage distincts. Le moteur de rendu Vulkan de Godot a été mis à jour pour prendre en charge l'utilisation d'échantillonneurs immuables. L'utilisation d'échantillonneurs a été modifiée pour utiliser des échantillons immuables lorsque cela est possible.

Optimisation axée sur les mobiles

Des optimisations supplémentaires ont été implémentées pour améliorer spécifiquement les performances de rendu sur le matériel graphique mobile. Les optimisations ne sont généralement pas pertinentes pour le matériel graphique de classe ordinateur de bureau en raison de conceptions architecturales différentes.

Voici quelques-unes des optimisations:

  • Remplacer l'utilisation de grandes constantes de transfert
  • Allocation de tampon différée
  • Compatibilité avec les tampons persistants
  • Modification du mode de décodage ASTC
  • Prérotation de l'écran

Remplacer l'utilisation de grandes constantes de transfert

Les constantes de poussée sont une fonctionnalité qui permet d'injecter des valeurs constantes pour le programme de nuanceur actif dans le tampon de commandes. Les constantes de transfert sont pratiques, car elles ne nécessitent pas de création et de remplissage de tampons, et ne sont pas liées aux descripteurs. Cependant, les constantes de transfert ont une taille maximale limitée et peuvent avoir un impact négatif sur les performances sur le matériel mobile.

Lors des tests sur des appareils Android, les performances ont été améliorées en remplaçant l'utilisation constante de plus de 16 octets par des tampons uniformes. Les nuanceurs qui utilisaient 16 octets ou moins de données constantes étaient plus performants avec les constantes push. En plus des considérations de performances, certains matériels graphiques ont un alignement minimal de 64 octets pour les tampons uniformes, ce qui réduit l'efficacité de la mémoire en raison de la marge intérieure inutilisée par rapport à l'utilisation de constantes push.

Allocation de tampon différée

La plupart du matériel graphique mobile utilise une architecture de rendu différé basé sur des tuiles (TBDR, Tile-Based Deferred Rendering). Les GPU qui utilisent TBDR divisent la plus grande région de l'écran en une grille de petites tuiles et effectuent le rendu par tuile. Chaque carte est associée à une petite quantité de RAM haute vitesse utilisée pour le stockage par le GPU lorsqu'il effectue le rendu d'une carte. Avec TBDR, les cibles de rendu qui ne sont jamais échantillonnées par une autre cible en dehors de leur passage de rendu peuvent rester entièrement dans la RAM de la carte et ne nécessitent pas de tampon pour un espace de stockage en mémoire principale.

VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT a été ajouté lors de la création de cibles de rendu appropriées, telles que les cibles de couleur et de profondeur principales, pour éviter d'allouer de la mémoire tampon qui ne serait jamais utilisée. Les économies de mémoire liées à l'allocation paresseuse dans des scènes d'exemple ont été estimées à environ 50 mégaoctets de RAM.

Compatibilité avec les tampons persistants

Le matériel mobile utilise une architecture de mémoire unifiée (UMA) au lieu d'une différenciation matérielle entre la RAM principale et la RAM graphique. Lorsque la RAM principale et la RAM graphique sont distinctes, les données doivent être transférées de la RAM principale vers la RAM graphique pour être utilisées par le GPU. Godot implémente déjà ce processus de transfert dans son moteur de rendu Vulkan à l'aide de tampons de mise en scène. Sur le matériel UMA,un tampon de mise en scène n'est pas nécessaire pour de nombreux types de données. La mémoire peut être utilisée à la fois par le processeur et le GPU. Forge a implémenté la prise en charge des tampons partagés persistants sur le matériel compatible afin d'éliminer le pré-traitement lorsque cela est possible.

Images d'une scène godot affichant des informations de profilage avec et sans tampons persistants activés.
Figure 1. Différences de profilage entre les tampons persistants activés et désactivés dans un exemple de scène.

Modification du mode de décodage ASTC

La compression de texture adaptative évolutive (ASTC) est le format de compression de texture moderne privilégié sur les appareils mobiles. Lors de la décompression, le GPU peut, par défaut, décoder les texels en une valeur intermédiaire dont la précision est supérieure à celle requise pour la fidélité visuelle, ce qui entraîne une perte d'efficacité de texturation. Si le matériel cible est compatible, l'extension VK_EXT_astc_decode_mode est utilisée pour spécifier des valeurs non normalisées de 8 bits par composant lors du décodage au lieu de valeurs à virgule flottante de 16 bits.

Prérotation de l'écran

Pour des performances optimales lors de l'utilisation de Vulkan sur Android, les jeux doivent concilier l'orientation de l'écran de l'appareil avec l'orientation de leur surface de rendu. Ce processus est appelé prérotation. L'absence de prérotation peut entraîner une réduction des performances, car l'OS Android doit ajouter un pass de compositeur pour faire pivoter manuellement les images. La prérotation sur Android a été ajoutée au moteur de rendu Godot.

Améliorations apportées au débogage

En plus d'optimiser les performances, The Forge a amélioré l'expérience de débogage des problèmes graphiques dans le moteur de rendu Godot avec les ajouts suivants:

  • Extension de la période de dépannage de l'appareil
  • Fils d'Ariane
  • Repères de débogage

Extension de la période de dépannage de l'appareil

Lorsque le GPU rencontre un problème lors des opérations de rendu, le pilote Vulkan peut renvoyer un résultat VK_ERROR_DEVICE_LOST à partir d'un appel d'API Vulkan. Par défaut, aucune information contextuelle supplémentaire n'est fournie sur la raison pour laquelle le pilote a renvoyé VK_ERROR_DEVICE_LOST. L'extension VK_EXT_device_fault fournit un mécanisme permettant au pilote de fournir des informations supplémentaires sur la nature de l'erreur. Godot a ajouté la possibilité d'activer l'extension de défaut de l'appareil (si disponible) et de signaler les informations renvoyées par le pilote.

Il peut être difficile de déboguer un plantage ou un blocage d'exécution du GPU. Pour vous aider à identifier le contenu graphique qui aurait pu être affiché au moment d'un défaut, la prise en charge des maillons de navigation a été ajoutée au moteur de rendu Godot. Les miettes de pain sont des valeurs définies par l'utilisateur qui peuvent être associées au contenu des listes de dessin dans le graphique de rendu. Les données de fil d'Ariane sont écrites avant le démarrage d'une nouvelle passe de rendu. En cas de plantage ou d'arrêt de l'exécution, la valeur actuelle du fil d'Ariane peut être utilisée pour déterminer quelles données peuvent avoir causé le problème.

Repères de débogage

Les repères de débogage, lorsqu'ils sont compatibles avec le pilote, sont utilisés pour nommer les ressources. Cela permet d'associer des chaînes lisibles par l'utilisateur à des opérations telles que les passes de rendu et des ressources telles que les tampons et les textures lorsque vous utilisez un outil graphique tel que RenderDoc. La prise en charge des annotations de repères de débogage a été ajoutée au moteur de rendu Vulkan de Godot.

Blog Godot Engine : Informations sur la collaboration avec Google et The Forge

Pull request de collaboration Vulkan pour Godot Engine