Endianness und Layout von GPU-Daten

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Endianness und Layout von GPU-Daten

Beitrag von Schrompf »

Moinzeit!

Ich scheitere mal wieder an der Verfütterung der richtigen Stichwörter an Google, deswegen habe ich jetzt die Hoffnung, dass jemand von Euch mir das sagen kann.

Wie genau interpretiert die GPU die Daten, die ich ihm hochladen? Also in welcher Endianess und in welcher Komponenten-Reihenfolge erwartet die GPU die Daten im Speicher?

Mein akutes Problem: ich habe Millionen von Daten in zwei Texturen zu je 4x uint16_t verpackt. uint16_t, weil ich noch auf DX9 bin, wo es ja per Design keine Integer-Operationen gibt und ein uint32_t demzufolge im Shader an Bits einbüßen würde. Im Shader entpacke ich die Daten wieder und zerlege sie nach Bedarf in 8- und 16Bit-Komponenten. Nur muss ich dazu halt genau wissen, in welche Bytes ich welche Bits verpacken muss, damit ich sie im Shader aus .xyzw rausziehen und zurecht-frac()-en kann.

Hat jemand eine Idee oder einen Link parat? Danke.

[edit]Integer-Texturen dürften als unsigned interpretiert und auf 0...1 normiert werden, wenn ich aus ihnen sample. Hab daher die Datentypen auf uint16_t korrigiert.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Endianness und Layout von GPU-Daten

Beitrag von Krishty »

Die GPU-Endianness ist synchron zum Hostsystem. Das ist offensichtlich, denn sonst könntest du 16-Bit-Texturen nicht auf die gewohnte Art hochladen und im Shader wieder auslesen, sondern müsstest vorm Hochladen die Endianness ändern!

Du weißt jetzt also, dass die 16-Bit-Ints genau so vorliegen wie auf der CPU. Das bedeutet, dass dir die Endianness insgesamt wurscht sein kann. Denn wenn du die hohen 16 Bits eines ints in Textur A packst, und die niedriegen in Textur B, musst sie auf der GPU auch wieder ganz genau so zusammenfügen. In dem Augenblick, wo du samplest, hat die GPU die Endianness ja wieder aufgelöst.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Endianness und Layout von GPU-Daten

Beitrag von Schrompf »

Nuja, ich ging bisher eigentlich davon aus, dass der Treiber heftig was konvertiert beim Hochladen der Daten. Also z.B. Texturen in dieses hilbert-transformierte Segmentsystem, so dass mehr Pixel in 2D relativ zueinander naheliegen. Aber vielleicht habe ich da ein HörenSagen-Wissen wiedermal überinterpretiert. Hm. Genaugenommen kann er das zumindest bei VertexBuffern gar nicht wissen, weil die ja erst später je nach Eingabedeklaration Sinn ergeben.

Ergebnis also für 4xuint16_t:

Code: Alles auswählen

 Rot Grün Blau Alpha - Low/High
RL RH GL GH BL BH AL AH
und als uint64_t Little Endian demzufolge

Code: Alles auswählen

 0xAHALBHBLGHGLRHRL
Richtig? Dann mach ich das mal so.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Endianness und Layout von GPU-Daten

Beitrag von Krishty »

Ja; passt. Alle D3D9-Formate sind in Little Endian gegeben -- RGBA ist im Speicher also A-B-G-R. Mit D3D 10 wurde das geändert und RGBA gibt nun die Speicherreihenfolge an; pass da also später auf.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
Schrompf
Moderator
Beiträge: 4838
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: Endianness und Layout von GPU-Daten

Beitrag von Schrompf »

Krishty hat geschrieben:Ja; passt. Alle D3D9-Formate sind in Little Endian gegeben -- RGBA ist im Speicher also A-B-G-R.
Watt? Du schreibst "Ja, passt", aber schreibst dann das Gegenteil von dem, was ich oben geschrieben habe? Jetzt hab ich ernsthaft Angst.

Nochmal: wenn ich eine Textur mit D3DFMT_A16B16G16R16 aufmache, ist jeder Pixel 8 Byte groß.

Ist ein D3DFMT_A16B16G16R16-Pixel im Speicher also so rum:

Code: Alles auswählen

RedLow RedHigh GreenLow GreenHigh BlueLow BlueHigh AlphaLow AlphaHigh
wie ich oben schrieb, oder ist es

Code: Alles auswählen

AlphaLow AlphaHigh BlueLow BlueHigh GreenLow GreenHigh RedLow RedHigh
wie Du in Deinem letzten Beitrag geschrieben hast?

Das Ganze ist in der Hinsicht halt recht spannend, weil ein 4Byte-ARGB ja klassisch als Little Endian Integer gespeichert wird, im Speicher also in Reihenfolge Blue Green Red Alpha steht. Daher heißt der bei D3D in BigEndian-Form, also auch D3DFMT_A8R8G8B8. Wenn ich dagegen nun pro Komponente 16 anstatt 8 Bit haben will, verdreht sich die Komponentenreihenfolge zu RGBA. Ich sehe gerade, dass ich in meinem Framework das bereits antizipiert habe und D3DFMT_A16B16G16R16 nehme. Ok, jetzt bin ich völlig verwirrt.

Heißt das jetzt, dass Direct3D9 seine Format-Konstanten nach Ganzer-Pixel-In-BigEndian benannt hat, die Daten dann aber im Speicher in Ganzer-Pixel-In-LittleEndian liegen und die GPU daraus dann Einzel-Komponente-In-LittleEndian liest?
Mit D3D 10 wurde das geändert und RGBA gibt nun die Speicherreihenfolge an; pass da also später auf.
Danke für die Warnung. Bedeutet das nach obiger Logik, dass D3D10 einfach seine Konstanten "korrekter" benannt hat und jetzt immer nach "Einzel-Komponente-In-LittleEndian" heißt?
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Benutzeravatar
Krishty
Establishment
Beiträge: 8229
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Endianness und Layout von GPU-Daten

Beitrag von Krishty »

Schrompf hat geschrieben:
Krishty hat geschrieben:Ja; passt. Alle D3D9-Formate sind in Little Endian gegeben -- RGBA ist im Speicher also A-B-G-R.
Watt? Du schreibst "Ja, passt", aber schreibst dann das Gegenteil von dem, was ich oben geschrieben habe? Jetzt hab ich ernsthaft Angst.

Nochmal: wenn ich eine Textur mit D3DFMT_A16B16G16R16 aufmache, ist jeder Pixel 8 Byte groß.

Ist ein D3DFMT_A16B16G16R16-Pixel im Speicher also so rum:

Code: Alles auswählen

RedLow RedHigh GreenLow GreenHigh BlueLow BlueHigh AlphaLow AlphaHigh
wie ich oben schrieb, oder ist es

Code: Alles auswählen

AlphaLow AlphaHigh BlueLow BlueHigh GreenLow GreenHigh RedLow RedHigh
wie Du in Deinem letzten Beitrag geschrieben hast?
Missverständnis! FMT_ABGR ergibt Speicherreihenfolge R-G-B-A weil D3DFMT Big Endian ist. Oben meinte ich mit "RGBA" sowas wie FMT_R8G8B8A8, das entsprechend als A-B-G-R im Speicher liegt.
Das Ganze ist in der Hinsicht halt recht spannend, weil ein 4Byte-ARGB ja klassisch als Little Endian Integer gespeichert wird, im Speicher also in Reihenfolge Blue Green Red Alpha steht. Daher heißt der bei D3D in BigEndian-Form, also auch D3DFMT_A8R8G8B8.
Korrekt.
Wenn ich dagegen nun pro Komponente 16 anstatt 8 Bit haben will, verdreht sich die Komponentenreihenfolge zu RGBA.
Nein, das darf eigentlich nicht sein.
Ich sehe gerade, dass ich in meinem Framework das bereits antizipiert habe und D3DFMT_A16B16G16R16 nehme. Ok, jetzt bin ich völlig verwirrt.
Ich auch. FÜr D3DFMT_A16B16G16R16 wäre R-G-B-A zu erwarten. Kriegst du auch:
Schrompf hat geschrieben:

Code: Alles auswählen

 Rot Grün Blau Alpha - Low/High
RL RH GL GH BL BH AL AH
und als uint64_t Little Endian demzufolge

Code: Alles auswählen

 0xAHALBHBLGHGLRHRL
Heißt das jetzt, dass Direct3D9 seine Format-Konstanten nach Ganzer-Pixel-In-BigEndian benannt hat, die Daten dann aber im Speicher in Ganzer-Pixel-In-LittleEndian liegen und die GPU daraus dann Einzel-Komponente-In-LittleEndian liest?
Ja genau. Die Komponentenreihenfolge ist Big Endian, aber die Komponenten selber sind Little Endian.
Mit D3D 10 wurde das geändert und RGBA gibt nun die Speicherreihenfolge an; pass da also später auf.
Danke für die Warnung. Bedeutet das nach obiger Logik, dass D3D10 einfach seine Konstanten "korrekter" benannt hat und jetzt immer nach "Einzel-Komponente-In-LittleEndian" heißt?
Für D3D 10 haben sie Endianness einfach komplett aufgegeben. Wenn ein Format dort FORMAT_RGBA heißt, liegen die Komponenten auch tatsächlich als R-G-B-A im Speicher, egal ob Big Endian oder Little Endian. Nur das Makro, das z.B. eine Farbe in ein 32-Bit-Int packt, wird auf den jeweiligen Plattformen angepasst. (Jörg, erzähle ich Quatsch?)

Die Komponenten liegen falls sie mehr als ein Byte groß sind, in Host Byte Order vor, mutmaße ich. Alles andere wäre ein katastrophales Durcheinander beim Erzeugen und Lesen der Texturen. Und das bedeutet wohl auch, dass man 64-Bit-Texturen zwischen x86- und ARM-Version eines Spiels nicht einfach austauschen kann.
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Antworten