Comment résoudre les gros besoins en mémoire vidéo dans un jeu en 2D?
Nous développons actuellement un jeu 2D (Factorio) en allegro C / C ++, et nous rencontrons un problème d'augmentation des besoins en mémoire vidéo à mesure que le contenu du jeu augmente.
Nous rassemblons actuellement toutes les informations sur les images qui vont être utilisées en premier, rognons toutes ces images autant que possible et les organisons dans de grands atlas aussi étroitement que possible. Ces atlas sont stockés dans la mémoire vidéo, dont la taille dépend des limites du système. Actuellement, il s'agit généralement de 2 images de 8192x8192, elles nécessitent donc une mémoire vidéo de 256 Mo à 512 Mo.
Ce système fonctionne assez bien pour nous, car avec certaines optimisations personnalisées et la division du fil de rendu et de mise à jour, nous sommes en mesure de dessiner des dizaines de milliers d'images sur l'écran en 60 ips; nous avons beaucoup d’objets sur l’écran et il est essentiel de permettre un zoom arrière important. Au fur et à mesure que nous souhaiterions en ajouter davantage, les exigences en matière de mémoire vidéo vont poser problème, de sorte que ce système ne peut pas tenir.
Une des choses que nous voulions essayer est d’avoir un atlas avec les images les plus courantes, et le second comme cache. Les images y seraient déplacées de la mémoire bitmap, à la demande. Cette approche pose deux problèmes:
- Le dessin de bitmap mémoire en bitmap vidéo est extrêmement lent, en mode allégro.
- Il n'est pas possible de travailler avec une image bitmap vidéo autrement que dans le fil principal, dans allegro, elle est donc pratiquement inutilisable.
Voici quelques exigences supplémentaires que nous avons:
- Le jeu doit être déterministe, de sorte que les problèmes de performances / temps de chargement ne peuvent jamais modifier l’état du jeu.
- Le jeu est en temps réel et sera bientôt multijoueur également. Nous devons éviter le moindre bégaiement à tout prix.
- La plupart du jeu est un monde ouvert continu.
Le test consistait à tirer 10 000 sprites dans un lot pour des tailles de 1x1 à 300x300, plusieurs fois pour chaque configuration. J'ai fait les tests sur la Nvidia Geforce GTX 760.
- Le dessin d'une image à une autre prend 0,1 us par image-objet, lorsque l'image source ne change pas entre les images individuelles (variante de l'atlas); la taille n'avait pas d'importance
- Dessin de bitmap vidéo en bitmap vidéo, alors que le bitmap source était commuté entre les dessins (variante non atlas), prenait 0,56 us par sprite; la taille n'avait pas d'importance non plus.
- La mémoire bitmap au dessin vidéo bitmap était vraiment suspecte. Les tailles de 1x1 à 200x200 prenaient 0.3us par bitmap, donc pas si lent. Pour les plus grandes tailles, le temps a commencé à augmenter de manière très spectaculaire, à 9US pour 201x201 à 3116US pour 291x291.
Utiliser atlas augmente les performances d'un facteur supérieur à 5. Si j'avais 10 ms pour le rendu, avec un atlas, je suis limité à 100 000 sprites par image, et sans cela, une limite de 20 000 sprites. Ce serait problématique.
J'essayais également de trouver un moyen de tester la compression bitmap et le format bitmap 1bpp pour les ombres, mais j'étais incapable de trouver un moyen de le faire avec allegro.