PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : glBegin() - glEnd() vs. DrawArrays()


Che
2002-12-21, 16:28:00
Ich habe mich gefragt ob es wogl einen Unterschied macht die Vertices mittels glBegin() - glEnd() an die Grafikkarte zu senden oder DrawArrays() zu verwenden. In der OpenGL Spec steht nur dass DrawArrays den selben Effekt hat wie ...<hier kommt das ganze mit glBegin() - glEnd() aufgelöst>
Das es den selben Effekt hat kann ich mir selber denken, ich möchte wissen ob es einen Geschwindigkeitsunterschied gibt, ich denke mir bei ein paar Vertices (so ab 10.000) entsteht doch ein hübscher Overhead für glBegin() - glEnd(). Und dann würde mich noch interessieren was denn diese "Compiled Vertex Arrays" sind. Oder spricht man schon von CVA wenn man DrawArray() verwendent?
Ich habe nämlich vor kurzem ein hübsches Heightmap Demo gezogen (irgendwo auf Stefan Zerbsts Seite unter "IOTW"), wo im Prinzip das gemacht wird was ich auch gerade programmiere, nur eben unter D3D und nicht unter OpenGL. In diesem Demo werden ca. 30.000 Dreicke gerendert - bei 60 FPS! Ich bin schon ab 10.000 auf 25 FPS. (non-T&L Graka) Ich denke mir so falsch kann ich doch gar nicht programmieren, dass so eine großer Geschwindigkeitsunterschied auftritt. Allerdings gibt es in D3D AFAIK keinen "Immediate Mode", dort wird gleich mit dem Pendant zu DrawArrays() gearbeitet. Kann es sein dass mein Programm deshalb so langsam ist weil ich glBegin() - glEnd() nutze?

Demirug
2002-12-21, 16:35:17
Ja der ""Immediate Mode" ist nicht sonderlich schnell aus diesem Grund hat man sich sowas bei D3D auch gespart da man dort ja primär auf Geschwindigkeit abzielt.

NVIDIA hat zu dem Thema Performancens und OpenGL ein paar Folien zum lesen:

http://developer.nvidia.com/docs/IO/1295/ATT/GDC01_Performance.pdf

Che
2002-12-21, 16:46:36
Originally posted by Demirug
Ja der ""Immediate Mode" ist nicht sonderlich schnell aus diesem Grund hat man sich sowas bei D3D auch gespart da man dort ja primär auf Geschwindigkeit abzielt.

NVIDIA hat zu dem Thema Performancens und OpenGL ein paar Folien zum lesen:

http://developer.nvidia.com/docs/IO/1295/ATT/GDC01_Performance.pdf

Hmm, interessant... gilt das nur für NV-Karten? Da steht irgendwo zu lesen man soll lieber die SGIS-Extension zum Mipmap bauen verwenden anstatt gluBuild2dmupmaps...???
Na, dann werd ich das ganze mal auf DrawArrays() umschreiben...
Thx for help

Demirug
2002-12-21, 16:56:05
Originally posted by Che


Hmm, interessant... gilt das nur für NV-Karten? Da steht irgendwo zu lesen man soll lieber die SGIS-Extension zum Mipmap bauen verwenden anstatt gluBuild2dmupmaps...???
Na, dann werd ich das ganze mal auf DrawArrays() umschreiben...
Thx for help

Vieles davon ist unabhängig von der benutzten Karte. Wenn es dann aber um speziele NV Extension geht muss man die entsprechenden Extension der anderen Hersteller benutzten.

zeckensack
2002-12-21, 19:36:39
Wg CVA:
Das ist eine Extension, die du zusätzlich benutzen kannst. Damit gibst du OpenGL quasi den Hinweis, daß du das Array nicht mehr veränderst. Dadurch kann das komplette Array in einem Rutsch auf die Graka oder in AGP-Speicher geschoben werden.

Das ganze hat noch andere Vorteile, die sich aber nur auf Grakas ohne T&L-Hardware auswirken.

Wir hatten auf OpenGL.org vor ein paar Tagen einen möglicherweise hilfreichen Thread zum Thema (http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008236.html).

Ich darf mal Pat Brown (c/o NVIDIA) zititeren:
When you call LockArraysEXT(first, count), you are effectively making a few promises to the driver, including:

(1) for every array enabled at LockArraysEXT time, elements <first> through <first> + <count> - 1 of the array hold valid data, and

(2) for every array enabled at LockArraysEXT time, you're not going to screw with the data until you call UnlockArraysEXT.

As one naive example, a software T&L engine might pre-transform all the vertices in the range, and use the transformed results for subsequent rendering (assuming the matrices don't change). A hardware T&L driver might copy the array contents into AGP or video memory and then process DrawElements calls by sending indices. In general, a driver will take your hint and try to make things faster for your device.

But you do need to keep your end of the bargain. You need to set up your pointers before calling LockArraysEXT. You need to make sure that the index range you give LockArraysEXT holds valid data for all vertices. When you render between LockArraysEXT and UnlockArraysEXT, you have to make sure that you don't pass any indices outside of the locked index array. And you need to make sure you don't overwrite the data, since in the examples above, your changes may have no effect (you'd get the "wrong" results).

Do any of these things wrong and "undefined" results may ensue. For uninitialized pointers (and also possibly out- of-range indices), "undefined" results could well include crashes.

Hope this helps,
Pat

Che
2002-12-22, 15:33:10
Jo danke!
Vorteile für non T&L Grakas - das ist genau was ich brauch (Voodoo 5 :D )
Kann es sein dass allein dieses DrawArray() Zeugs so einen großen Unterschied macht? Ich hab bei einer 64x64 Heightmap dieselbe Performance wie das angesprochene Demo bei einer 1024x1024 - Ok, da sind noch ein paar Vertices-spar-Algorithmen drin, aber trotzdem sind es ca. 8 mal so viele Dreiecke wie bei mir! Und dieselbe Performance!!

Che
2003-01-22, 12:03:22
Neue frage: Machen viele (so um 1000) Aufrufe von DrawArrays() den Vorteil gegenüber glBegin/end wieder zunichte?
-> 1000 Strips á 10 Vertices statt 1 Strip á 10000 Vertices ?

zeckensack
2003-01-22, 15:13:53
Originally posted by Che
Neue frage: Machen viele (so um 1000) Aufrufe von DrawArrays() den Vorteil gegenüber glBegin/end wieder zunichte?
-> 1000 Strips á 10 Vertices statt 1 Strip á 10000 Vertices ? Nein.

glBegin/glEnd ist immer die langsamste Methode.
Trotzdem sind größere Arrays natürlich tendenziell bess[/i]er[/i].

Was schlecht ist, ist ein zu häufiges Wechseln des Arrays (glVertexPointer* und Konsorten).

Trotzdem noch 'ne Gegenfrage:
Warum benutzt du nicht Indizes und glDrawElements? Vielleicht kannst du damit die Vertex-Menge pro Funktionsaufruf weiter steigern?

Unregistered
2003-01-23, 09:17:45
Originally posted by zeckensack
Nein.

Trotzdem noch 'ne Gegenfrage:
Warum benutzt du nicht Indizes und glDrawElements? Vielleicht kannst du damit die Vertex-Menge pro Funktionsaufruf weiter steigern?

Ich fange gerade erst an das Vertex Array Zeugs zu erkunden...mal sehen wo ich hinkomm. Auf jeden Fall danke für die Tipps.

Che
2003-01-23, 09:22:00
^Das war ich übrigens^
Was mir noch einfällt: Ich habe doch keine Möglichkeit drawArrays() oder DrawElements() mitzuteilen wo der eine Fan (oder strip) aufhört und wo der nächste anfängt. Also komme ich um mehrer Aufrufe nicht herum...

Demirug
2003-01-23, 09:48:57
Originally posted by Che
^Das war ich übrigens^
Was mir noch einfällt: Ich habe doch keine Möglichkeit drawArrays() oder DrawElements() mitzuteilen wo der eine Fan (oder strip) aufhört und wo der nächste anfängt. Also komme ich um mehrer Aufrufe nicht herum...

Eine generelle Lösung dafür gibt es leider nicht. Bei der GF FX gibt es eine Extension dafür, aber das dürfte im Moment wohl kaum was nützen.

Bei einem Fan kann man also praktisch gar nichts machen. Zum Verketten von Strips gibt es aber eine Technik:

http://www.gamedev.net/reference/articles/article1871.asp

Und da man aus einem Fan eigentlich auch immer einen Strip machen kann kann man auch diese Problem lösen.

zeckensack
2003-01-23, 14:04:24
Jupps.

Es gibt für solche Fälle auch 'Mesh stripper'-Tools. Einmal bei NVIDIA (weiß jetzt den genauen Link nicht, heißt NVtristrip), oder auch einen ziemlich guten und flexiblen offenen (http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/007900.html).