glGetFloatv – ar trebui să fie evitat? Poate fi înlocuit? (Dezvoltarea jocurilor, Opengl Es, Matrix, Optimizare)

AllCoder a intrebat.

Platforma este OpenGL ES 1.x. Folosesc glGetFloatv() pentru a obține matricea MODELVIEW. Acest lucru îmi permite să calculez punctele, unde trebuie să desenez un efect de umbră. Acest lucru este foarte util, deoarece pot să uit de complexitatea scenei (translațiile, rotațiile etc.) – și printr-o simplă înmulțire a matricei 3×1 obțin punctele.

Dar aici se precizează că apelul trebuie evitat. Este corectă această recomandare? Se poate omite glGetFloatv()?

3 răspunsuri
postgoodism

Din punct de vedere al performanței pure, funcțiile glGet*() ar trebui, în general, să fie evitate, pe cât posibil, deoarece pot introduce puncte de sincronizare inutile în interiorul driverului grafic. Practic, atunci când apelați glGet*(), este posibil ca driverul să fie nevoit să blocheze CPU-ul și să aștepte ca GPU-ul să finalizeze orice operațiune de randare nefinalizată, astfel încât o valoare corectă și actualizată să poată fi returnată din glGet*(). Mai mult decât atât, penalizarea performanței poate varia de la un driver la altul, astfel încât ceea ce rulează bine pe o platformă poate fi inacceptabil de lent pe alta.

Soluția mai rapidă (dar mult mai puțin convenabilă) este de a stoca manual în memoria cache orice stare de randare necesară în codul aplicației. De exemplu, atunci când transmiteți o matrice MODELVIEW către OpenGL, păstrați o copie suplimentară pentru dumneavoastră, astfel încât să nu fie nevoie să apelați ulterior glGetFloatv() pentru a o recupera.

Acestea fiind spuse, un singur apel la glGetFloatv() pe cadru probabil că nu vă va distruge performanța. Folosiți aceste funcții cu moderație, fiți conștienți de potențialele lor efecte secundare și faceți profilul des!

Comentarii

  • În ce fel este mai puțin convenabil? Aveți un apel de funcție miraculoasă mai puțin și o variabilă la îndemână mai mult.-  > Por API-Beast.
  • @Mr.Beast Am vrut doar să spun că adaugă mai multă stare globală pe care aplicația dvs. trebuie să o urmărească și mai mult cod pe care trebuie să îl scrieți pentru a o gestiona. Nu este o corvoadă uriașă, dar este mai puțin convenabil decât să folosești o funcție GL standard.-  > Por postgoodism.
Inginer

Cel mai rapid mod de a rezolva acest lucru ar fi să folosiți OpenGL modern, cu pipeline programabil (2.0 ES), deoarece, de obicei, veți crea modelul, vizualizarea și matricele de proiecție pe partea clientului și, prin urmare, nu va fi nevoie să le solicitați niciodată de la server.

Nu știu dacă aceasta este o opțiune pentru dumneavoastră – este posibil să sprijiniți dispozitive mai vechi.

Maximus Minimus

Acesta va fi un comportament care va depinde de driver, așa că nu va fi posibil un răspuns absolut unic pentru toți. Cu toate acestea, deși regula generală este că orice apel glGet ar trebui evitat, în anumite cazuri acestea pot fi utilizate fără probleme nejustificate.

Motivul pentru aceasta este că nu orice apel glGet va depinde de rezultatul operațiilor anterioare de pe GPU și că numai cele care sunt atât de dependente vor implica probleme de sincronizare și de blocare/închidere a conductei.

În cazul matricei actuale de vizualizare a modelului, aceasta va fi – în general – calculată întotdeauna de către driver pe partea CPU, apoi trimisă la GPU pentru a fi utilizată efectiv atunci când are loc un apel de desenare. Așadar, un glGetFloatv pe matricea actuală a modelului de vizualizare nu va trebui să facă un drum dus-întors către GPU – poate doar să preia copia pe care driverul o stochează pe partea CPU și să o returneze programului dumneavoastră.