Sbloccare i buffer?


12

Sto facendo dei test con OpenGL ES 2 e ho ricevuto alcune domande, il mio programma attuale è così:

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

Il problema

Il crash del codice dato, dopo alcune ricerche, ho capito perché: ho bisogno di separare il mio buffer di indice nella parte init (dopo "riempire il buffer di indice glBufferData") o separarlo prima del primo "Bind VAO"

Le mie domande sono:

  • Posso inserire il mio buffer di indice in VAO (buffer di indice azionario VAO?)?
  • Ho dovuto separare i buffer dopo ogni aggiornamento (glBufferData)?

Nella mia applicazione ho alcuni buffer che vengono aggiornati su ciascun frame (Esempio: Particelle), quindi ho uno stack OpenGL del genere:

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

Le prime 3 righe aggiornano il buffer dei vertici, gli ultimi due oggetti di disegno, che dovrebbero essere qualcosa del genere:

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

Grazie

Risposte:


12

Sembra che tu stia facendo molto su rilegature / svincoli inutili. Se si utilizza un VAO, è necessario associare il VAO solo quando lo si imposta e quando si disegna la geometria. Associare nuovamente VBO / IBO solo quando è necessario aggiornarli.

Dopo aver disegnato o aggiornato un buffer, non è necessario separarlo, anche se potrebbe essere una buona idea farlo per evitare scritture accidentali sui buffer che sono stati lasciati rilegati.

Ora prendendo la prima sequenza di operazioni, questo è l'ordine generale che mi aspetterei di vedere:

Su init:

  1. Crea e associa un VAO. Qualsiasi VBO e IBO che vincoli nella sequenza verranno associati al VAO corrente (questo).

  2. Crea e associa il buffer dell'indice.

    • Riempi il buffer dell'indice con glBufferData/glMapBuffer.
  3. Crea e associa buffer vertici.

    • Riempi il buffer dei vertici glBufferData/glMapBuffer.
  4. Imposta gli attributi del vertice con glEnableVertexAttribArray/glVertexAttribPointer, ecc.

  5. Opzionalmente separare tutto per evitare modifiche accidentali dei buffer e VAO. Ricorda di separare prima il VAO . Per esempio:glBindVertexArray(0);

In pareggio:

  1. Se solo disegnando i buffer :

    • Associare il VAO;
    • Eseguire le chiamate di estrazione.
  2. In caso di aggiornamento e disegno :

    • Associare VAO, VBO, IBO;
    • Aggiorna i buffer (l'aggiornamento degli attributi dei vertici è necessario solo se il formato dei vertici è cambiato);
    • Eseguire le chiamate di estrazione.
  3. Opzionalmente separare per evitare modifiche accidentali dei buffer e VAO.

È così semplice. Questo ordine di operazioni dovrebbe funzionare senza problemi.


2
Vorrei aggiungere che nei miei esperimenti (2014) con casi di vita reale (ma semplici shader da non strozzare alla GPU) ho trovato insignificanti i miglioramenti delle prestazioni usando VAO (<2% di risparmio CPU) dopo un corretto ordinamento delle chiamate di rendering è stato implementato per saltare completamente la configurazione di VBO quando si utilizza lo stesso VBO su chiamate di rendering consecutive (dal 10 al 33% di risparmio della CPU) e ho riscontrato alcuni bug dei driver con VAO, quindi alla fine li ho disattivati ​​per impostazione predefinita. È stato ancora meno significativo quando si utilizzano shader complessi, MSAA, ecc., Che il collo di bottiglia nella GPU ha lasciato la CPU pigramente in attesa, anche sui dispositivi mobili.
Stephane Hockenhull,

2
Si noti che il disallineamento dei dati dei vertici in un modo che non è supportato dall'hardware costringerà i driver GPU a riordinare i dati VBO su ciascuna configurazione mentre i driver possono riordinarli una volta con VAO a condizione che nulla sia cambiato così YMMV. Meglio allineare e riempire i dati dei vertici comunque.
Stephane Hockenhull,

1
Perché il VAO deve essere libero da ogni altra cosa?
Daniel Safari,

@DanielSafari, intendi dopo l'installazione? Se si separasse prima un buffer (buffer di associazione 0 / null), si eliminerebbe quel punto di associazione nel VAO corrente. Ecco perché il VAO null deve essere impostato per primo.
glampert

@glampert: no, non è così che funzionano i binding; l'associazione buffer viene utilizzata quando viene chiamato glVertexAttribPointer e non diversamente (eccezione: GL_ELEMENT_ARRAY_BUFFER). La modifica dell'associazione buffer dopo la chiamata glVertexAttribPointer non ha alcun effetto.
Maximus Minimus,
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.