Dosagem eficiente de sprites

7

Estou pensando em migrar do XNA para as APIs do Stage3D (Molehill). Portanto, como um exame de desempenho, implementei lotes por sprite, mas o desempenho não é tão bom assim, enquanto que com o XNA eu posso desenhar facilmente 500.000 quads, mas com a minha implementação Molehill eu posso desenhar uns míseros 1000 quads e enquanto era esperada uma diferença de desempenho bastante dramática no lado da CPU, devido ao fato de estar vinculado à GPU.

Portanto, atualmente a implementação é a seguinte.

set render states

let texture be null
let batchSize be arbitrary

for each sprite in queue
    if texture is not sprite texture
    or buffers are full

        upload vertex data to index buffer
        upload index data to vertex buffer

        bind texture
        draw triangles

        flush vertex data
        flush index data


    add sprite vertices to vertex data
    add sprite indices to index data
end

upload remaining vertex data to vertex buffer
upload remaining index data to index buffer
draw remaining triangles

flush data

O gargalo está carregando os buffers, mas quanto a uma implementação melhor, espero uma discussão aqui.

Felicidades.

Revisão:

Uma otimização que vem à mente é manter o buffer do índice, pois os índices são previsíveis e sempre seguirão o mesmo formato. Vou avaliar isso agora.


O armazenamento em cache do buffer de índice não teve ganhos de desempenho perceptíveis; portanto, em um esforço para tentar entender onde está o gargalo, eu o transportei para C # / XNA, um pouco mais lento que a implementação da Microsoft, mas ainda tem uma capacidade de GPU 500 vezes mais que a implementação da Molehill.

Molehill é simplesmente uma camada de abstração extremamente ruim?

Casper Beyer
fonte
Tornar o buffer de índice persistente é uma boa idéia, que pode ajudar a obter um pouco de desempenho. A única outra coisa que consigo pensar ao olhar para seu pseudo-código é que você sempre liga novamente a textura. Você deve verificar se a textura mudou entre as chamadas e só depois vincular uma nova textura; caso contrário, não obterá ganho de desempenho ao usar um Texture Altas, por exemplo.
Jonathan Connell
Na verdade, a textura é encadernada apenas uma vez, talvez seja lida novamente.
Casper Beyer
Ah, sim, está implícito que "textura" é atribuída à textura do sprite na encadernação.
Casper Beyer
Você tem 'Bind Texture' no para cada loop. Eu estava dizendo que deveria ser se você não chamar Bind Texture quando a textura não mudou entre dois sprites. No momento, você está pedindo à GPU para vincular novamente uma textura em cada loop; é uma operação cara e pode não ser necessária.
Jonathan Connell
Novamente, ele é vinculado apenas uma vez. Uma verificação condicional dificilmente é uma operação cara.
Casper Beyer #

Respostas:

2

Você pode ter um mapa múltiplo de sprites no qual a chave é a textura e, ao renderizar, percorrer cada chave no mapa e renderizar cada grupo de sprites que estão associados a essa textura. Se todos os sprites compartilharem a mesma textura, você poderá representar todos os sprites com dois triângulos e coordenadas de textura, o que significa que é possível desenhar todos os sprites que usam a mesma textura em uma única passagem, com um único buffer de vértice e buffer de índice.

Embora eu esteja usando o XNA, rolei meu próprio processo de renderização e lote em vez de usar o lote de sprites, e estou processando cerca de 3000 sprites por vez e atualmente obtendo cerca de 600 fps em uma Nvidia GTX 275, usando o processo I descrito acima. Quando eu estava passando os sprites para o método spritebatch, o XNA fornece cerca de 25 fps.

No meu caso, em vez de um multimap, tenho uma classe (SpriteData) que contém a textura e uma lista de vértices. Sempre que um sprite se registra no renderizador, ele percorre uma Lista de SpriteData até encontrar um tipo de textura correspondente e adiciona esse sprite à lista de vértices.

Também estou particionando espacialmente para garantir que apenas os sprites em exibição estejam sendo considerados.

Nic Foster
fonte