Os buffers devem ser desvinculados?

12

Estou fazendo alguns testes com o OpenGL ES 2 e tenho algumas perguntas, meu programa atual é assim:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

O problema

O travamento de código fornecido, depois de algumas pesquisas, eu entendi o porquê: preciso desvincular meu buffer de índice na parte init (depois de "preencher o buffer de índice glBufferData") ou desvinculá-lo antes do primeiro "Bind VAO"

Minhas perguntas são:

  • Posso colocar meu buffer de índice no VAO (buffer de índice de ações VAO?)?
  • Eu tive que desvincular buffers após cada atualização (glBufferData)?

Na minha aplicação, eu tenho alguns buffers que são atualizados em cada quadro (exemplo: Partículas), então eu tenho uma pilha OpenGL assim:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

As primeiras 3 linhas atualizam o buffer Vertex, os dois últimos objetos de desenho, que devem ser algo assim:

-> bind buffer 1
-> update buffer 1
-> draw

obrigado

user30088
fonte

Respostas:

12

Você parece estar fazendo muito em ligações / desvinculações desnecessárias. Se você estiver usando um VAO, vincule-o apenas ao configurá-lo e ao desenhar a geometria. Você só vincula o VBO / IBO novamente quando precisar atualizá-los.

Após desenhar ou atualizar um buffer, você não precisa necessariamente desassociá-lo, embora possa ser uma boa idéia fazê-lo para evitar gravações acidentais em buffers que foram deixados no limite.

Agora, tomando sua primeira seqüência de operações, esta é a ordem geral que eu esperaria ver:

No init:

  1. Crie e vincule um VAO. Qualquer VBO e IBO que você vincular na sequência serão associados ao VAO atual (este).

  2. Crie e ligue o buffer de índice.

    • Preencha o buffer de índice com glBufferData/glMapBuffer.
  3. Crie e ligue buffer de vértice.

    • Preencher buffer de vértice glBufferData/glMapBuffer.
  4. Configure atributos de vértice com glEnableVertexAttribArray/glVertexAttribPointer, etc.

  5. Opcionalmente, desmonte tudo para evitar modificações acidentais dos buffers e do VAO. Lembre-se de desligar o VAO primeiro . Por exemplo:glBindVertexArray(0);

No sorteio:

  1. Se apenas desenhar os buffers :

    • Vincule o VAO;
    • Realize as chamadas de sorteio.
  2. Se estiver atualizando e desenhando :

    • Vincular o VAO, VBO, IBO;
    • Atualize os buffers (a atualização de atributos de vértice é necessária apenas se o formato do vértice foi alterado);
    • Realize as chamadas de sorteio.
  3. Opcionalmente, desencaixe para evitar modificações acidentais dos buffers e VAO.

É simples assim. Essa ordem de operações deve funcionar sem problemas.

glampert
fonte
2
Gostaria de acrescentar que, em meus experimentos (2014) com casos da vida real (mas com sombreadores simples para não gargalos na GPU), eu achei as melhorias de desempenho usando o VAO insignificantes (<2% de economia de CPU) após o pedido adequado de chamadas de renderização foi implementada para ignorar completamente a instalação do VBO ao usar o mesmo VBO em chamadas de renderização consecutivas (economia de 10 a 33% da CPU), e eu atingi alguns bugs de drivers com o VAO e acabei desativando-os por padrão. Foi ainda menos significativo ao usar shaders complexos, MSAA etc., que gargalo na GPU deixa a CPU ociosa aguardando de qualquer maneira, mesmo em dispositivos móveis.
Stephane Hockenhull
2
Observe que o desalinhamento de dados de vértices de uma maneira que não seja suportada pelo hardware forçará os drivers da GPU a reorganizar os dados do VBO em cada instalação, enquanto os drivers podem reordená-los uma vez com o VAO, desde que nada seja alterado para o YMMV. Melhor alinhar e preencher os dados de vértices de qualquer maneira.
Stephane Hockenhull
1
Por que o VAO deve ser desvinculado antes de tudo?
Daniel Safari
@DanielSafari, você quer dizer após a instalação? Se você desvincular um buffer primeiro (buffer de ligação 0 / nulo), limpará esse ponto de ligação no VAO atual. É por isso que o VAO nulo deve ser definido primeiro.
glampert
@ glampert - não, não é assim que as ligações funcionam; a ligação do buffer é usada quando glVertexAttribPointer é chamado e não o contrário (exceção: GL_ELEMENT_ARRAY_BUFFER). Alterar a ligação do buffer após a chamada glVertexAttribPointer não tem efeito.
Maximus Minimus