Questa è una domanda complessa con molti piccoli dettagli che contano davvero, le prestazioni variano in base alla piattaforma e all'applicazione. Quindi dovresti profilare possibili strozzature prima di investire in ottimizzazioni.
Detto questo, in primo luogo, suppongo che dovresti ridurre il più possibile i caricamenti e gli aggiornamenti, ad esempio utilizzare l'istanziazione.
In secondo luogo, si noti che le GPU non possono trasferire buffer e render allo stesso tempo, quindi tutti i comandi OpenGL nella coda comandi vengono elaborati in sequenza dal dispositivo. Esistono diversi modi per copiare i dati e / o renderli disponibili per essere utilizzati dalla GPU.
Esistono vari modi per trasmettere i dati alla GPU
1- glBufferData
oglBufferSubData
metodo
Usare glBufferData
o glBufferSubData
è come memcpy. si passa un puntatore e l'operazione DMA potrebbe essere eseguita, ho detto che potrebbe perché la memoria potrebbe essere bloccata nella memoria della CPU e utilizzata direttamente dalla GPU senza effettivamente un trasferimento di memoria alla GPU, a seconda del flag di utilizzo (GL_STREAM). In opinione dovresti provarlo all'inizio perché è più semplice da implementare.
2- ottenere un puntatore alla memoria interna usando glMapBuffer
Se quanto sopra non è abbastanza buono da poter usare glMapBuffer
, ottieni un puntatore alla memoria interna e puoi usare questo puntatore per riempire direttamente il buffer, questo è buono con le operazioni di lettura e scrittura dei file, poiché puoi mappare direttamente i dati del file nella memoria GPU anziché copiarlo prima in un buffer temporaneo. Se non si desidera mappare l'intero buffer, è possibile utilizzare glMapBufferRange
quale può essere utilizzato per mappare una parte del buffer.
Un trucco è creare un buffer di grandi dimensioni, utilizzare la prima metà per il rendering e la seconda metà per l'aggiornamento.
3- Orfanotrofio del buffer
Per quanto riguarda il buffer orfano, questo può essere fatto usando glBufferData con null e gli stessi parametri che aveva. Il driver restituirà il blocco di memoria una volta non utilizzato. E verrà utilizzato dalla prossima chiamata glBufferData (non verrà allocata alcuna nuova memoria).
Tutti i metodi citati causano molte costose sincronizzazioni, anche in questo caso le GPU non possono trasferire buffer e render allo stesso tempo.
4- Unsynchronized Buffers
Il metodo più veloce (e più difficile da ottenere a destra) è usare i buffer senza sincronizzazione con cui puoi usare GL_MAP_UNSYNCHRONIZED_BIT
flag glMapBufferRange
, il problema è che non viene eseguita alcuna sincronizzazione, quindi potremmo caricare i dati su un buffer iniziando a usare, e quindi rovinare tutto. È possibile utilizzare più buffer con bit non sincronizzati per semplificare un po 'le cose.