Como resolvemos grandes requisitos de memória de vídeo em um jogo 2D?
Estamos desenvolvendo um jogo 2D (Factorio) em allegro C / C ++, e estamos enfrentando um problema com o aumento dos requisitos de memória de vídeo à medida que o conteúdo do jogo aumenta.
No momento, reunimos todas as informações sobre as imagens que serão usadas primeiro, recortamos todas essas imagens o máximo possível e as organizamos em grandes atlas o máximo possível. Esses atlas são armazenados na memória de vídeo, cujo tamanho depende das limitações do sistema; atualmente, geralmente são 2 imagens de até 8192x8192, portanto, elas requerem memória de vídeo de 256Mb a 512Mb.
Esse sistema funciona muito bem para nós, pois, com algumas otimizações personalizadas e dividindo o segmento de renderização e atualização, podemos desenhar dezenas de milhares de imagens na tela em 60 fps; temos muitos objetos na tela e permitir um grande zoom é um requisito crítico. Como gostaríamos de acrescentar mais, haverá alguns problemas com os requisitos de memória de vídeo, portanto esse sistema não pode suportar.
Uma das coisas que queríamos tentar é ter um atlas com as imagens mais comuns e o segundo como um cache. As imagens seriam movidas para lá a partir do bitmap de memória, sob demanda. Há dois problemas com esta abordagem:
- O desenho do bitmap de memória para o bitmap de vídeo é dolorosamente lento, no allegro.
- Não é possível trabalhar com bitmap de vídeo que não seja o thread principal, no allegro, portanto é praticamente inutilizável.
Aqui estão alguns requisitos adicionais que temos:
- O jogo deve ser determinista, para que os problemas de desempenho / tempo de carregamento nunca possam alterar o estado do jogo.
- O jogo é em tempo real, e em breve será multiplayer também. Precisamos evitar até a menor gagueira a todo custo.
- A maior parte do jogo é um mundo aberto contínuo.
O teste consistiu em desenhar 10.000 sprites em um lote para tamanhos de 1x1 a 300x300, várias vezes para cada configuração. Eu fiz os testes na Nvidia Geforce GTX 760.
- O bitmap de vídeo para o desenho de bitmap de vídeo levou 0,1 us por sprite, quando o bitmap de origem não estava mudando entre bitmaps individuais (a variante atlas); o tamanho não importava
- O bitmap de vídeo para o desenho de bitmap de vídeo, enquanto o bitmap de origem foi alternado entre desenhos (variante não atlas), levou 0,56us por sprite; o tamanho também não importava.
- O bitmap de memória para o desenho de bitmap de vídeo era realmente suspeito. Os tamanhos de 1x1 a 200x200 levaram 0,3us por bitmap, portanto, não é tão terrivelmente lento. Para tamanhos maiores, o tempo começou a aumentar muito, de 9us para 201x201 a 3116us para 291x291.
O uso de atlas aumenta o desempenho em um fator maior que 5. Se eu tivesse 10ms para a renderização, com um atlas estou limitado a 100.000 sprites por quadro e, sem ele, um limite de 20.000 sprites. Isso seria problemático.
Eu também estava tentando encontrar uma maneira de testar a compactação de bitmap e o formato de bitmap de 1bpp para sombras, mas não consegui encontrar uma maneira de fazer isso no allegro.