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.