Essa é uma pergunta complexa, com muitos pequenos detalhes que realmente importam; o desempenho varia de acordo com a plataforma e o aplicativo. Portanto, você deve analisar possíveis gargalos antes de investir em otimizações.
Dito isto, em primeiro lugar, presumo que você deve reduzir o máximo de uploads e atualizações, por exemplo, usar instanciamento.
Em segundo lugar, observe que as GPUs não podem transferir buffers e renderizar ao mesmo tempo, portanto, todos os comandos OpenGL na fila de comandos são processados sequencialmente pelo dispositivo. Existem diferentes maneiras de copiar dados e / ou torná-los disponíveis para serem usados pela GPU.
Existem várias maneiras de transmitir dados para a GPU
1- glBufferData
ou glBufferSubData
método
Usando glBufferData
ou glBufferSubData
é como memcpy. você passa um ponteiro e a operação de DMA pode ser executada, como eu disse, porque a memória pode ser fixada na memória da CPU e usada diretamente pela GPU, sem que ocorra uma transferência de memória para a GPU, dependendo do sinalizador de uso (GL_STREAM). Na opinião, você deve tentar isso primeiro porque é mais simples de implementar.
2- obter um ponteiro para a memória interna usando glMapBuffer
Se o descrito acima não for bom o suficiente, você poderá usar glMapBuffer
um ponteiro para a memória interna e usá-lo para preencher diretamente o buffer, isso é bom para operações de leitura e gravação de arquivos, pois é possível mapear diretamente os dados do arquivo na memória da GPU em vez de copiar primeiro para um buffer temporário. Se você não deseja mapear o buffer inteiro, pode usar o glMapBufferRange
que pode ser usado para mapear uma parte do buffer.
Um truque é criar um buffer grande, use a primeira metade para renderização e a segunda metade para atualização.
3- Órfão de buffer
Em relação ao órfão de buffer, isso pode ser feito usando glBufferData com nulo e os mesmos parâmetros que possuía. O driver retornará o bloco de memória assim que não for usado. E será usado pela próxima chamada glBufferData (nenhuma memória nova será alocada).
Todos os métodos mencionados causam muita sincronização cara, novamente as GPUs não podem transferir buffers e renderizar ao mesmo tempo.
4- Unsynchronized Buffers
O método mais rápido (e mais difícil de acertar) é usar buffers sem sincronização com os quais você pode usar GL_MAP_UNSYNCHRONIZED_BIT
sinalizadores glMapBufferRange
; o problema é que nenhuma sincronização é feita; portanto, podemos fazer o upload de dados para um buffer que começa a ser usado e, portanto, estragar tudo. Você pode usar vários buffers com bit unsync para facilitar um pouco as coisas.