Czy bufory powinny być niezwiązane?

12

Robię testy z OpenGL ES 2 i mam pytania, mój obecny program jest taki:

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

Problem

Podany błąd kodu, po kilku badaniach, zrozumiałem, dlaczego: muszę rozpiąć mój bufor indeksu w części początkowej (po „wypełnieniu bufora indeksu glBufferData”) lub usunąć powiązanie przed pierwszym „Bind VAO”

Moje pytania to:

  • Czy mogę umieścić bufor indeksu w VAO (bufor indeksu giełdowego VAO?)?
  • Czy musiałem rozpinać bufory po każdej aktualizacji (glBufferData)?

W mojej aplikacji mam kilka buforów, które są aktualizowane w każdej ramce (Exemple: Particles), więc mam taki stos OpenGL:

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

Pierwsze 3 linie aktualizują bufor wierzchołka, dwa ostatnie obiekty do rysowania, które powinny wyglądać mniej więcej tak:

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

Dzięki

użytkownik30088
źródło

Odpowiedzi:

12

Wygląda na to, że dużo robisz na temat niepotrzebnego wiązania / rozpinania. Jeśli używasz VAO, powiąż go tylko podczas jego konfigurowania i rysowania geometrii. Ponownie wiążesz VBO / IBO tylko wtedy, gdy musisz je zaktualizować.

Po narysowaniu lub zaktualizowaniu bufora niekoniecznie musisz go odznaczyć, chociaż może to być dobry pomysł, aby uniknąć przypadkowego zapisu do buforów, które zostały ograniczone.

Biorąc teraz pod uwagę sekwencję operacji na pięści, oto ogólna kolejność, jakiej bym się spodziewał:

Na init:

  1. Utwórz i powiąż VAO. Wszelkie VBO i IBO, które powiążesz w sekwencji, zostaną powiązane z bieżącym VAO (tym).

  2. Utwórz i powiązaj bufor indeksu.

    • Wypełnij bufor indeksu za pomocą glBufferData/glMapBuffer.
  3. Utwórz i powiąż bufor wierzchołków.

    • Wypełnij bufor wierzchołków glBufferData/glMapBuffer.
  4. Ustaw atrybuty wierzchołków za pomocą glEnableVertexAttribArray/glVertexAttribPointeritp.

  5. Opcjonalnie odznacz wszystko, aby uniknąć przypadkowej modyfikacji buforów i VAO. Pamiętaj, aby najpierw odłączyć VAO . Na przykład:glBindVertexArray(0);

Przy losowaniu:

  1. Jeśli tylko rysujesz bufory :

    • Powiązanie VAO;
    • Wykonaj połączenie losowania.
  2. W przypadku aktualizacji i rysowania :

    • Powiązanie VAO, VBO, IBO;
    • Zaktualizuj bufory (aktualizacja atrybutów wierzchołków jest konieczna tylko wtedy, gdy zmienił się format wierzchołków);
    • Wykonaj połączenie losowania.
  3. Opcjonalnie usuń powiązanie, aby uniknąć przypadkowej modyfikacji buforów i VAO.

To takie proste. Ta kolejność operacji powinna działać bez problemów.

glampert
źródło
2
Chciałbym dodać, że w moich eksperymentach (2014) z rzeczywistymi przypadkami (ale prostymi modułami cieniującymi, aby nie wąskim gardłem na GPU) stwierdziłem, że poprawa wydajności przy użyciu VAO była nieznaczna (<2% oszczędności procesora) po prawidłowym zamówieniu wywołań renderowania zostało zaimplementowane, aby całkowicie pominąć konfigurację VBO podczas używania tego samego VBO podczas kolejnych wywołań renderowania (10 do 33% oszczędności procesora), i natrafiłem na niektóre błędy sterowników z VAO, więc ostatecznie je wyłączyłem. Było to nawet mniej znaczące, gdy korzystano ze złożonych shaderów, MSAA itp., Które to wąskie gardło na GPU pozostawiły procesor bezczynnie i tak nawet na telefonie komórkowym.
Stephane Hockenhull
2
Należy pamiętać, że nieprawidłowe wyrównanie danych wierzchołków w sposób, który nie jest obsługiwany przez sprzęt, zmusi sterowniki GPU do zmiany kolejności danych VBO przy każdej konfiguracji podczas gdy sterowniki mogą zmienić kolejność raz w VAO, o ile nic się nie zmieni, więc YMMV. Mimo to najlepiej wyrównać i uzupełnić dane wierzchołków.
Stephane Hockenhull
1
Dlaczego VAO musi być rozwiązane przed wszystkim innym?
Daniel Safari,
@DanielSafari, masz na myśli po instalacji? Jeśli najpierw rozpiszesz bufor (bufor wiązania 0 / null), wyczyści on ten punkt wiązania w bieżącym VAO. Dlatego najpierw należy ustawić wartość VAO zerową.
glampert,
@glampert - nie, nie tak działają wiązania; powiązanie bufora jest używane, gdy wywoływane jest glVertexAttribPointer, a nie inaczej (wyjątek: GL_ELEMENT_ARRAY_BUFFER). Zmiana wiązania bufora po wywołaniu glVertexAttribPointer nie ma wpływu.
Maximus Minimus