Perché OpenGL> = 3 consente solo VBO?


21

Vedo che le versioni OpenGL 3 e successive eliminano l'uso del rendering lato client. La modalità immediata è stata eliminata e le matrici di vertici sembrano essere obsolete. Invece, se ho capito bene, i VBO sono il modo principale per il rendering dei vertici.

Mentre vedo la logica dietro avere un modo uniforme di rendere tutto, è vero che i VBO non hanno grandi svantaggi rispetto agli array di vertici? Pensavo che i VBO dovevano essere grandi buffer contenenti> 1 MB di dati, in generale. E se avessi una scena con molte geometrie più piccole? Ho un grafico di scena con un gran numero di nodi, ognuno dei quali ha bisogno della propria trasformazione, ecc. Ogni nodo dovrebbe anche essere in grado di essere eliminato separatamente, aggiunto separatamente, ecc. Prima stavo usando array di vertici. Quindi la mia prima domanda è se, se passerò ai VBO, ora ci sarà un overhead maggiore per i miei oggetti del grafico della scena perché un VBO deve essere allocato per ciascun oggetto.

Un'altra preoccupazione è che la geometria che sto visualizzando può essere altamente dinamica. Nel peggiore dei casi, ci possono essere momenti in cui è necessario inviare nuovamente ogni geometria a ogni frame per un certo periodo di tempo. I VBO avranno prestazioni peggiori rispetto agli array di vertici in questo caso d'uso, o i VBO nella peggiore delle ipotesi funzioneranno tanto quanto gli array di vertici ma non di più?

Quindi, in un formato più conciso, le mie domande sono:

1) Esiste un notevole sovraccarico nell'allocare / deallocare i VBO (intendo il semplice atto di creare un buffer)?

2) Se sto aggiornando i dati dalla CPU ogni frame, può essere sostanzialmente peggio che se avessi usato array di vertici?

E infine, vorrei sapere:

3) Se la risposta a una delle domande precedenti è "sì", perché deprecare altre modalità di rendering che potrebbero avere vantaggi rispetto ai VBO? C'è qualcosa che mi manca qui, come le tecniche che dovrei usare per mitigare alcuni di questi potenziali costi di allocazione, ecc.?

4) Le risposte a una di queste domande cambiano sostanzialmente a seconda della versione OpenGL che sto usando? Se refactoring il mio codice per essere compatibile con OpenGL 3 o 4 utilizzando VBO in modo performante, le stesse tecniche avranno probabilmente le stesse prestazioni con OpenGL 2 o è probabile che alcune tecniche siano molto più veloci con OpenGL 3 + e altri con OpenGL 2?

Ho posto questa domanda su overflow dello stack, ma sto ripubblicando qui perché ho realizzato che questo sito potrebbe essere più appropriato per la mia domanda.


1
Perché un voto per chiudere? È un dup? In tal caso, posso vedere un link in modo da poterne beneficiare?
Gravità

Risposte:


23

Esiste un notevole sovraccarico nell'allocare / deallocare i VBO (intendo il semplice atto di creare un buffer)?

Definisci "sostanziale". È generalmente saggio non crearli nel mezzo di cornici; dovrebbero essere installati durante l'inizializzazione o ovunque. Questo è vero per la maggior parte degli oggetti OpenGL, come trame, renderbuffer o shader.

Se sto aggiornando i dati dalla CPU ogni frame, può essere sostanzialmente peggio che se avessi usato array di vertici?

Può esso? Sì. OpenGL definisce la funzionalità, non le prestazioni . Puoi davvero rendere le cose molto più lente. Oppure puoi rendere le cose più veloci. Tutto dipende da come lo usi.

OpenGL Wiki ha un buon articolo su come trasmettere correttamente i dati .

Se la risposta a una delle domande precedenti è "sì", perché deprecare altre modalità di rendering che potrebbero avere vantaggi rispetto ai VBO? C'è qualcosa che mi manca qui, come le tecniche che dovrei usare per mitigare alcuni di questi potenziali costi di allocazione, ecc.?

Innanzitutto, non erano solo deprecati. Deprecare significa contrassegnare qualcosa come "da rimuovere" nelle versioni future. Sono stati deprecati in 3.0 e rimossi in 3.1 core e versioni successive.

In secondo luogo, l'ARB ha generalmente spiegato il motivo per cui hanno rimosso elementi da OpenGL. Rende le specifiche più piccole e più semplici. Rende l'API più piccola e più snella. Rende più facile sapere quali API dovresti usare; 2.1 aveva 4 modi per fornire dati sui vertici; 3.1+ ha 1. Si sbarazza di un sacco di cruft. Eccetera.

Le risposte a una di queste domande cambiano sostanzialmente in base alla versione OpenGL che sto usando? Se refactoring il mio codice per essere compatibile con OpenGL 3 o 4 utilizzando VBO in modo performante, le stesse tecniche avranno probabilmente le stesse prestazioni con OpenGL 2 o è probabile che alcune tecniche siano molto più veloci con OpenGL 3 + e altri con OpenGL 2?

Più o meno no. Solo su MacOSX la differenza tra le versioni 3.1 + core e pre-3.0 sembra davvero. Il profilo di compatibilità è implementato da tutti i driver per Linux e Windows, quindi puoi presumere che il profilo principale di questi driver stia davvero aggiungendo dei controlli per impedirti di chiamare le funzioni di compatibilità.

In Mac OSX 10.7 è disponibile il core GL 3.2, ma non il profilo di compatibilità. Ciò non significa necessariamente nulla per le tecniche di esecuzione l'una rispetto all'altra. Ma significa che se ci sono differenze, questa è la piattaforma su cui le vedrai.


1
Dal momento che hai appena inviato una domanda a questa domanda , io incrocerò la mia risposta.
Nicol Bolas,

Un altro vantaggio di mantenere concisa l'API è che semplifica l'implementazione dell'API OpenGL. Questa è stata una grande considerazione nelle specifiche originali OpenGL ES.
notlesh

@stephelton: ha senso. La mia domanda "perché deprecare tutto tranne i VBO" si basava sul pensiero che, sebbene abbia perfettamente senso mantenere snella l'API, non ha senso deprecare le funzionalità che potrebbero essere migliori dei VBO per molti casi d'uso. Da quello che sto ascoltando, sembra che non ci siano svantaggi nell'utilizzo dei VBO, quindi ha perfettamente senso deprecare tutto il resto.
Gravità

@gravity Non è necessario utilizzare VBO. Puoi anche usare una serie di vertici.
notlesh

18

Nel modo in cui OpenGL funziona, ogni volta che si utilizzano dati non VBO, il driver deve crearne una copia - in pratica creando un VBO temporaneo - poiché nulla ti impedisce di modificare le matrici nude dello spazio utente tra le chiamate a OpenGL.

Potrebbe esserci qualche trucco lato guidatore per rendere più veloce l'allocazione temporanea, ma non c'è niente che tu possa fare per evitare la copia.

Quindi sì, fintanto che tu e gli sviluppatori dei driver fate tutto bene, i VBO dovrebbero sempre accelerare le cose.


6
Mi piace meglio questa risposta. È più breve e più preciso, imo.
TravisG

@JariKomppa: Sembra una spiegazione molto ragionevole. Ho ancora una preoccupazione: si suppone che i VBO siano oggetti ragionevolmente grandi, spesso allocati come buffer da 1 MB - 4 MB l'ultima volta che ho controllato. Cosa succede se i miei oggetti geometrici non sono così grandi, ma sono ancora preoccupato per le prestazioni perché ho molti oggetti? Sono preoccupato che i VBO potrebbero essere solo per un caso d'uso diverso da quello che ho. Dovrei mettere insieme più oggetti in un singolo VBO e quindi utilizzare glDrawRangeElementsper disegnare ogni singolo oggetto, o è inefficiente proprio come gli array di vertici?
Gravità

Dubito che farà la differenza, ma se ritieni che sia una preoccupazione, confrontala.
Jari Komppa il

@JariKomppa: cosa dubiti farà la differenza? Utilizzando glDrawRangeElementspiù volte su ogni VBO con alcuni VBOs piuttosto che dare ogni oggetto proprio VBO?
Gravità

1
Esattamente. Dubito che vedrai molta differenza lì, ma la profilazione di alcuni casi di test dovrebbe darti maggiori informazioni. Inoltre non mi preoccuperei ora, poiché un cambiamento del genere potrebbe essere applicato in seguito, se necessario.
Jari Komppa,

9

e gli array di vertici sembrano essere deprecati. Invece, se capisco correttamente,

Non proprio. Le matrici di vertici sono la base per gli oggetti buffer di vertici. Solo la memoria è stata spostata dal lato client a quello lato server.

E se avessi una scena con molte geometrie più piccole?

Unisci set di geometria più piccoli in VBO più grandi. Non è necessario disporre di un VBO per batch di geometrie. È possibile indirizzare perfettamente sottoinsiemi di un VBO per il rendering. Utilizzare un offset diverso da zero per il parametro di dati gl… Pointer.

2) Se sto aggiornando i dati dalla CPU ogni frame, può essere sostanzialmente peggio che se avessi usato array di vertici?

Per questo ci sono i flag di utilizzo del buffer GL_DYNAMIC_DRAW e GL_STREAM_DRAW.

Se la risposta a una delle domande precedenti è "sì", perché deprecare altre modalità di rendering che potrebbero avere vantaggi rispetto ai VBO?

Perché non ci sono vantaggi. I dati della geometria devono comunque essere trasferiti alla GPU. L'uso di un normale array di vertici lato client provocherà comunque un trasferimento DMA alla GPU e anche la modalità immediata costruirà un batch da trasferire per primo.

Non c'è assolutamente alcun vantaggio nel non usare i VBO.


Quindi le mie prestazioni non dovrebbero generalmente essere peggiori con i VBO che con gli array di vertici, ma solo se imposto correttamente la modalità su GL_STREAM_DRAW?
Gravità,

@Gravity: Davvero. Tuttavia, la modalità buffer è solo un suggerimento sull'uso previsto, ma ovviamente tale suggerimento dovrebbe essere vero per quello che stai per fare. Inoltre, non dimenticare che è possibile mappare i buffer nello spazio degli indirizzi del processo per gli aggiornamenti (glMapBuffer, glUnmapBuffer).
datenwolf

ma poi il buffer non potrebbe essere in VRAM, giusto? O sarebbe ancora in VRAM ma indirizzabile solo tramite indirizzi di spazio del processo? L'accesso casuale sarebbe economico con questa tecnica o dovrei ancora provare ad aggiornare solo un numero limitato di intervalli contigui?
Gravità

@Gravity: un buffer può essere mappato in sola lettura, sola scrittura o lettura in scrittura. Per gli aggiornamenti che sceglieresti di scrivere solo. Ora diventa importante sapere come i moderni sistemi operativi gestiscono lo spazio degli indirizzi virtuali, in particolare attraverso la memoria paginata. Nel caso di una mappa di sola scrittura, viene mappato un pezzo di memoria di trasferimento DMA e le scritture in quell'intervallo mappato andranno nella memoria GPU più o meno direttamente (i contenuti vengono scritti prima nella RAM della CPU, ma poi trasferiti nella GPU da DMA trasferimento). È importante che questo sia un percorso più diretto rispetto a quando i dati passano attraverso un array di vertici lato client: la memoria di processo normale non è adatta per DMA
datenwolf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.