PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : OpenGL, VBOs und Treibermurks


Asmodeus
2004-07-01, 10:07:10
Von allen Seiten heisst es immer, man soll so effizent und platzsparend wie möglich programmieren. Dann versteh ich folgende Merkwürdigkeit jedoch nicht.

Angenommen, ich habe ein 3D-Objekt mit 50 Vertices und 70 Indices in einem VBO abgelegt. Wieso ist die Darstellung langsamer, wenn ich für die Indexabspeicherung nur 1 Byte (unsigned byte) verwende, als wenn ich für die Indexwerte 4 Byte (unsigned int) verwende. Theoretisch könnte der Treiber bei 1 Byte Indexwerten doch wesentlich mehr Indexwerte auf einmal übertragen und abarbeiten als bei 4 Byte Werten, oder übersehe ich irgendwas grundlegendes?

Gruss, Carsten.

mrdigital
2004-07-01, 11:04:46
x86 CPUs sind 32bitter. Deswegen sollten Speicherzugriffe immer 4Byte aligned sein, da man bei nicht durch 4 teilbaren Speicheradressen "Strafzyklen" einfügen muss. Also lieber 3 Byte "verschwenden", Speicher ist eh so billig ;)

Corrail
2004-07-01, 12:20:34
Da muss ich mrdigital zustimmen, Speicher ist billig! Vorallem was nützen einem 256MB auf einer GeForce FX5200? ;)

Außerdem kommt es da IMHO auf die Grafikkarte an und die werden nicht alle integer (bzw. unsigned integer) formate nativ unterstützen. Somit müssen diese Daten, wenn du z.B. ein unsigned byte VBO hast und mit dem arbeitest erst konvertiert werden.

Asmodeus
2004-07-01, 12:36:40
Grundsätzlich habt ihr zwar Recht. Aber wieso werden dann 16Bit Indexdaten sehr wohl beschleunigt, im Vergleich zu 32Bit Indexdaten. Auch dort greift ja eigentlich das Argument, dass bei 4Byte Orientierung bei 2Byte Daten immer 2 Strafbytes mitgeführt werden müssten. Dort hat es aber den Anschein, als würden die Treiber 2 x 2Byte zu 4 Byte zusammennehmen und übertragen und somit Bandbreite sparen. Wieso also nicht auch 4 x 1Byte zusammennehmen und übertragen?

Gruss, Carsten.

Corrail
2004-07-01, 12:42:53
Original geschrieben von Asmodeus
Wieso also nicht auch 4 x 1Byte zusammennehmen und übertragen?

Ich würde jetzt mal so aus dem Bauch raus sagen: Weil es sich nicht lohnt. Mit einem Byte Kann man genau 256 verschiedene Indices haben. Welches 3D Object hat heute nur noch 256 Vertices? Da lohnt es sich ja beinahe wieder Immediate Mode zu verwenden... ;)

Xmas
2004-07-01, 12:45:15
Original geschrieben von Asmodeus
Grundsätzlich habt ihr zwar Recht. Aber wieso werden dann 16Bit Indexdaten sehr wohl beschleunigt, im Vergleich zu 32Bit Indexdaten. Auch dort greift ja eigentlich das Argument, dass bei 4Byte Orientierung bei 2Byte Daten immer 2 Strafbytes mitgeführt werden müssten. Dort hat es aber den Anschein, als würden die Treiber 2 x 2Byte zu 4 Byte zusammennehmen und übertragen und somit Bandbreite sparen. Wieso also nicht auch 4 x 1Byte zusammennehmen und übertragen?

Gruss, Carsten.
Corrail hat es doch schon gesagt. Hier geht es nicht um Bandbreite sparen oder CPUs, sondern um die Formate die die GPU nativ unterstützt. Wenn du unsigned byte Indices verwendest, müssen diese erst mal von der CPU in 16/32bit-Werte expandiert werden, damit sie die GPU nachher lesen kann.
Genauso kostet es Zeit, wenn du z.B. einen ARGB-Buffer in RGBA-Order lesen willst.

Asmodeus
2004-07-01, 14:16:43
Ok, wie sieht es dann mit den Geometriedaten innerhalb eines VBOs aus? Profitiert man dort davon, wenn man anstatt Texturkoordinaten, Normalenkoordinaten und Vertexkoordinaten als float anzugeben mit short arbeitet und durch ne kurze Offsetrechnung im Vertexshader die Sachen wieder zurückrechnet? Oder sind auch da die VBOs auf 4Byte Datentypen optimiert?

Gruss, Carsten.

Corrail
2004-07-01, 14:30:04
Ich glaub nicht dass das so viel bringen wird. Vorallem dadurch dass die neueren Grafikkarten schon alle mit intern mit floating-point datentypen rechnen. Ich würde da eher bei floats bleiben (half floats bzw. floats).

Chris Lux
2004-07-01, 15:17:35
Original geschrieben von Asmodeus
Ok, wie sieht es dann mit den Geometriedaten innerhalb eines VBOs aus? Profitiert man dort davon, wenn man anstatt Texturkoordinaten, Normalenkoordinaten und Vertexkoordinaten als float anzugeben mit short arbeitet und durch ne kurze Offsetrechnung im Vertexshader die Sachen wieder zurückrechnet? Oder sind auch da die VBOs auf 4Byte Datentypen optimiert?

glaub nicht, das das viel bringen würde, denn erstens verbrauchst du leistung durch die zusätzliche berechnung und zweitens, wie hier schon angesprochen, sind solche formate heute kaum so optimiert wie die single precision floating point datentypen, die nunmal am weitesten verbreitet eingesetzt werden. ich glaube auch, dass du im vertex shader dann auch schon floating point werte erhälst (eben vorher konvertiert, was ja auch kosten kann).

hinzu kommt, dass die GPU internen caches wohl auch auf 4byte daten vektoren hin optimiert sind, was IMO beim transport zur pipeline hin probleme machen kann (wieder durch konvertieren oder umfüllen von daten).


vielleicht ein beispiel vom framebuffer:
bei tests ist mir aufgefallen, dass nvidia intern den framebuffer immer als bgra zu halten scheint, denn dies war mit und ohne PDR am schnellsten auszulesen, auch wenn der framebuffer/pbuffer als RGBA angelegt wurde. so werden mit sicherheit auch deine VBO daten intern anders gehandhabt als du dir das von aussen denken magst. wie bei texturen werden sicherlich auch im hauptspeicher kopien gehalten (mit denen du interagierst), die bei bedarf in den lokalen grafikspeicher geladen werden und dabei sicherlich auch in passende formate konvertiert werden.

Asmodeus
2004-07-02, 17:57:22
Jetzt habe ich noch folgende "Merkwürdigkeit entdeckt":

Bisher habe ich wie gesagt pro Vertex 8 Werte gespeichert (2x Texturkoordinaten, 3x Normalenkoordinaten und 3x Vertexkoordinaten), dafür habe ich das Format GL_T2F_N3F_V3F verwendet. Nun habe ich meine 2 Float Texturkoordinaten zu einem Floatwert komprimiert und 2 meiner Float Normalenkoordinaten zu einem Floatwert komprimiert. Somit habe ich insgesamt nur noch 6 Floatwerte pro Vertex, die ich im Format GL_N3F_V3F oder GL_C3F_V3F ablege. Im Vertexshader dekomprimiere ich die Sachen dann wieder (sind nur sehr wenige Instruktionen dafür nötig). Und trotz, dass jetzt pro 3D-Modell nur noch 75 Prozent der ursprünglichen Daten verarbeitet werden müssen, hat sich die Framerate kein Stück verbessert.

Und falls jetzt wieder jemand sagt, 8 Float-Werte lassen sich eben effizienter übertragen als 6 Float-Werte, dann kann ich nur sagen, dann find ich das trotzdem lausig von den Grafikkartenherstellern und Treiberentwicklern ;)

Ich mein, es kann doch nicht sein, dass man alles nur für jeweils einen "Spezialfall" optimiert, auch wenn es mehr Speicher und mehr Bandbreite kostet.

Gruss, Carsten.

zeckensack
2004-07-02, 19:18:28
Original geschrieben von Asmodeus
<...>
Und trotz, dass jetzt pro 3D-Modell nur noch 75 Prozent der ursprünglichen Daten verarbeitet werden müssen, hat sich die Framerate kein Stück verbessert.Ääääh ...
Was erwartest du denn von dieser Optimierung? Bist du überhaupt transferlimitiert?

Original geschrieben von Asmodeus
<...> ich habe ein 3D-Objekt mit 50 Vertices und 70 Indices in einem VBO abgelegt.Sieht eigentlich nicht danach aus :grübel:

Asmodeus
2004-07-03, 10:45:35
Original geschrieben von zeckensack
Ääääh ...
Was erwartest du denn von dieser Optimierung? Bist du überhaupt transferlimitiert?

Sieht eigentlich nicht danach aus :grübel:

:D guter Einwand. Aber keine Sorge, die Sache mit dem kleinen 3D Objekt, welches dann massenweise instanziiert ist, war ja als Test für die geschrumpfte Indexabspeicherung gedacht. Für den Test mit den komprimierten Textur- und Normalenkoordinaten habe ich natürlich eine Szene mit etwa 500 MByte Geometriedaten verwendet, die garantiert nicht mehr in den Grafikkartenspeicher passen ;)

Gruss, Carsten.