¿Cómo resolvemos los grandes requisitos de memoria de video en un juego 2D?
Estamos desarrollando un juego 2D (Factorio) en allegro C / C ++, y enfrentamos un problema con el aumento de los requisitos de memoria de video a medida que aumenta el contenido del juego.
Actualmente recopilamos toda la información sobre las imágenes que se utilizarán primero, recortamos todas estas imágenes tanto como sea posible y las organizamos en grandes atlas de la forma más ajustada posible. Estos atlas se almacenan en la memoria de video, cuyo tamaño depende de las limitaciones del sistema; Actualmente, generalmente son 2 imágenes de hasta 8192x8192, por lo que requieren una memoria de video de 256Mb a 512Mb.
Este sistema funciona bastante bien para nosotros, ya que con algunas optimizaciones personalizadas y dividiendo el hilo de renderizado y actualización, podemos dibujar decenas de miles de imágenes en la pantalla en 60 fps; Tenemos muchos objetos en la pantalla, y permitir un gran alejamiento es un requisito crítico. Como nos gustaría agregar más, habrá algunos problemas con los requisitos de memoria de video, por lo que este sistema no puede funcionar.
Una de las cosas que queríamos probar es tener un atlas con las imágenes más comunes y el segundo como caché. Las imágenes se moverían allí desde el mapa de bits de la memoria, bajo demanda. Hay dos problemas con este enfoque:
- El dibujo del mapa de bits de memoria al mapa de bits de video es dolorosamente lento, en allegro.
- No es posible trabajar con un mapa de bits de video que no sea el hilo principal, en allegro, por lo que es prácticamente inutilizable.
Aquí hay algunos requisitos adicionales que tenemos:
- El juego debe ser determinista, por lo que los problemas de rendimiento / tiempos de carga nunca pueden alterar el estado del juego.
- El juego es en tiempo real y pronto también será multijugador. Debemos evitar incluso el tartamudeo más pequeño a toda costa.
- La mayor parte del juego es un mundo abierto continuo.
La prueba consistió en dibujar 10 000 sprites en un lote para tamaños de 1x1 a 300x300, varias veces para cada configuración. Hice las pruebas en la Nvidia Geforce GTX 760.
- El dibujo de mapa de bits de video a mapa de bits de video tomó 0.1us por sprite, cuando el mapa de bits de origen no estaba cambiando entre mapas de bits individuales (la variante atlas); el tamaño no importaba
- El dibujo de mapa de bits de video a mapa de bits de video, mientras que el mapa de bits de origen se cambió entre dibujos (variante no atlas), tomó 0.56us por sprite; el tamaño tampoco importaba.
- El dibujo de mapa de bits de memoria a mapa de bits de video era realmente sospechoso. Los tamaños de 1x1 a 200x200 tomaron 0.3us por mapa de bits, por lo que no es tan terriblemente lento. Para tamaños más grandes, el tiempo comenzó a aumentar dramáticamente, a 9us para 201x201 a 3116us para 291x291.
El uso de atlas aumenta el rendimiento en un factor mayor que 5. Si tuviera 10 ms para el renderizado, con un atlas estoy limitado a 100 000 sprites por cuadro, y sin él, un límite de 20 000 sprites. Esto sería problemático.
También estaba tratando de encontrar una forma de probar la compresión de mapa de bits y el formato de mapa de bits de 1 bpp para sombras, pero no pude encontrar una forma de hacerlo en allegro.