PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Drei Zahlenwerte in einen float packen?


Simon
2007-02-03, 22:02:27
Hallo,

ich sitze hier gerade vor einem Problem, wo ich nicht mehr weiterweiß ;(
Also: ich hab pro Vertex drei (eigentlich vier, aber mit drei gehts auch) Zahlenwerte im Bereich [-0.5, 0.5]. Diese speicher ich momentan alle als float, nur benötigt das viel zu viel Speicher. Also dachte ich, dass man die drei Zahlen auch irgendwie in einen float packen könnte. Nach einigem Suchen und keinen Ergebnissen, weiß ich nun nicht mehr weiter ;( Das Problem ist, dass das ganze im Vertex/Fragment Program wieder entpackt werden muss...

Ist sowas überhaupt möglich? Wenn ja, wie?
Umwandeln der Werte in einen uint8 ist leider keine Option :redface:

Danke, Enrico

Gast
2007-02-03, 22:12:05
Klar ist das möglich. Ein float hat 24 Bit Mantisse und 8 Bit Zweierexponent.
Wenn du nun drei Zahlen in diesem Datentypen unabhängig voneinander ablegen möchtest heißt das du kannst z.B. 3*10 Bit Festkomma verwenden,
oder 2*11 Bit und 1*10 Bit. Mach dich mal schlau über Fließkommadarstellung
mit 64, 32 bzw. n Bit (WIKIPEDIA). Du kannst wenn nötig ja auch
eine Fließkommadarstellung mit 10 bzw. 11 Bit pro Zahl verwenden.
Das ist dann allerdings nicht mehr so besonders genau aber für
einige Dinge immer noch hinreichend.

Demirug
2007-02-03, 22:14:43
Was spricht gegen die Verwendung von UINT8 bzw. einem Color Wert? Bei einem float hast du eigentlich auch nur die 24 Bit der Mantisse zur Verfügung.

Manche Chips unterstützen neben den UINT8 auch noch ein Format mit 3 10 Bit Werten oder wenn das auch noch zu ungenau ist könnte man FP16 nehmen.

Coda
2007-02-03, 22:14:44
Klar ist das möglich. Ein float hat 24 Bit Mantisse und 8 Bit Zweierexponent.
Wenn du nun drei Zahlen in diesem Datentypen unabhängig voneinander ablegen möchtest heißt das du kannst z.B. 3*10 Bit Festkomma verwenden,
oder 2*11 Bit und 1*10 Bit. Mach dich mal schlau über Fließkommadarstellung
mit 64, 32 bzw. n Bit (WIKIPEDIA). Du kannst wenn nötig ja auch
eine Fließkommadarstellung mit 10 bzw. 11 Bit pro Zahl verwenden.
Das ist dann allerdings nicht mehr so besonders genau aber für
einige Dinge immer noch hinreichend.
Das kann er aber nicht auf der GPU entpacken, außer er verwendet D3D10-Hardware mit Bitmanipulationen.

Gast
2007-02-03, 22:28:10
Das kann er aber nicht auf der GPU entpacken, außer er verwendet D3D10-Hardware mit Bitmanipulationen.

Was hat das ganze mit D3D10 zu tun ? Vielleicht geht es hier gar nicht um
DirectX. Grundsätzlich sollte sich das "Entpacken" auch mit SM 3.0
Hardware machen lassen. Die Frage ist sicher wie "komfortabel" /
performant ist das dann, wenn man evtl. keine Bitmanipulationsbefehle
zur Verfügung hat.

Simon
2007-02-04, 00:29:12
Hallo,

Was spricht gegen die Verwendung von UINT8
Nach reichlicher Überlegung eigentlich nix ;)
Dazu allerdings eine Frage: Wenn ich uint8 als Datentyp für Vertexkomponenten verwende, wird das dann auch so von den GPUs intern verarbeitet und gespeichert oder wird das implizit in einen float umgewandelt?
Der Präzisionsverlust beim Umwandeln in uint8 sollte vertretbar sein, die 256 Werte dürften reichen.

bzw. einem Color Wert?
Es sind eigentlich nicht nur vier Werte pro Vertex, sondern 16 * vier Werte pro Vertex :| Und da komm ich mit der Color nicht weit, auch mit Secondary Color nicht.
Da liegt auch das Problem: 64 floats extra pro Vertex ist einfach zu viel. Falls diese Art von Kompression nicht funktioniert, muss ich sehen, dass ich was anderes finde...

Vielleicht geht es hier gar nicht um
DirectX. Grundsätzlich sollte sich das "Entpacken" auch mit SM 3.0
Hardware machen lassen. Die Frage ist sicher wie "komfortabel" /
performant ist das dann, wenn man evtl. keine Bitmanipulationsbefehle
zur Verfügung hat.
Also ich mach das mit OpenGL, was aber egal sein sollte. Und das ganze sollte auch noch auf ATI R300-Karten laufen, von daher fällt wohl auch SM3 raus ;( Nach Coda funktioniert das ja auch nicht auf Pre-DX10 Hardware...

Coda
2007-02-04, 02:31:04
Was hat das ganze mit D3D10 zu tun ? Vielleicht geht es hier gar nicht um DirectX.

Ich sagte D3D10-Hardware. Von mir aus kann er diese auch mit OpenGL ansprechen, aber das ist nunmal die, die zum ersten mal Bitmanipulationen in den Shadern erlaubt.

Die Direct3D-Spezifikationen bestimmen nunmal das Featureset moderner 3D-Hardware. Finde dich damit ab.

Grundsätzlich sollte sich das "Entpacken" auch mit SM 3.0 Hardware machen lassen. Die Frage ist sicher wie "komfortabel" /
performant ist das dann, wenn man evtl. keine Bitmanipulationsbefehle zur Verfügung hat.
Mit ner FPU? Das will ich sehen.

Dazu allerdings eine Frage: Wenn ich uint8 als Datentyp für Vertexkomponenten verwende, wird das dann auch so von den GPUs intern verarbeitet und gespeichert oder wird das implizit in einen float umgewandelt?
Wird alles in Floats umgewandelt auf D3D9-Hardware.

Gast
2007-02-04, 13:48:44
Ich sagte D3D10-Hardware. Von mir aus kann er diese auch mit OpenGL ansprechen, aber das ist nunmal die, die zum ersten mal Bitmanipulationen in den Shadern erlaubt.

Und alles was die Hardware nicht intrinsisch unterstützt, hältst du für grundsätzlich unmachbar ?

Die Direct3D-Spezifikationen bestimmen nunmal das Featureset moderner 3D-Hardware. Finde dich damit ab.

Mit ner FPU? Das will ich sehen.

Moment einmal. Eine FPU kann prinipiell alles was eine Integer ALU
auch kann. Der alte Zuse wäre froh gewesen, wenn er eine SM3.0 GPU
aus der heutigen Zeit zur Verfügung gehabt hätte. Und ich bin mir sicher
er hätte deutlich mehr daraus gemacht, als alle Leute in diesem Forum
zusammen, wenn man mal den Entertainment Aspekt außen vor läßt.

Coda
2007-02-04, 19:41:27
Moment einmal. Eine FPU kann prinipiell alles was eine Integer ALU auch kann.
Nö. IEEE 754 und so - könnte man sich ansehen. Eine Zerlegung auf Bitebene wäre damit wohl mit mehreren 100 Instructions evtl. möglich, aber wie praxisfern ist das denn bitte?

Ohne Bitshifts oder anderen irgendwie direkten Zugriff auf die einzelnen Bits ist das kaum machbar. Wenn dann kann man nur die Mantisse benützen, aber nicht auch noch den Exponenten.

Und ich bin mir sicher er hätte deutlich mehr daraus gemacht, als alle Leute in diesem Forum zusammen, wenn man mal den Entertainment Aspekt außen vor läßt.
*gähn*

Aber früher war alles besser :rolleyes:

Gast
2007-02-04, 20:32:33
Nö. IEEE 754 und so - könnte man sich ansehen. Eine Zerlegung auf Bitebene wäre damit wohl mit mehreren 100 Instructions evtl. möglich, aber wie praxisfern ist das denn bitte?

Ohne Bitshifts oder anderen irgendwie direkten Zugriff auf die einzelnen Bits ist das kaum machbar. Wenn dann kann man nur die Mantisse benützen, aber nicht auch noch den Exponenten.


*gähn*

Aber früher war alles besser :rolleyes:

Ich denke, es wird das Beste sein, die Diskussion an dieser Stelle zu beenden.
Wenn ich Dir noch einen Rat mit auf den Weg geben darf: Setzt dich vor
Deinen nächsten Prüfungen intensiv mit Floating Point Arithmetik auseinander,
denn da hast du noch ein paar gravierende Lücken.
Am besten schreibst du mal eine eigene Bibliothek für Floating Point
inklusive trigonometrischer, logarithmischer und Potenzfunktionen zur Übung
(natürlich ohne die intrinsischen Prozessorfunktionen zu verwenden).
Vielleicht kann Dich das vor dem Schlimmsten bewahren. Viel Glück !

Coda
2007-02-04, 20:33:27
Was willst du eigentlich? Nenn mir einen vernünftigen Weg eine 32-Bit-Float auf der FPU in 3x10-Bit-Floats zu zerlegen und diese wieder auf 32-Bit zu erweitern ohne Bitmanipulationen zur Verfügung zu haben bevor du hier große Töne spuckst.

Schon klar, dass das auf der CPU ohne weiteres geht, wir reden hier aber von einer reinen FPU. Da gibt's abs, add, mul, pow, log, lrp, exp usw. aber nichts was es ermöglichen würde die Bits übergreifend über Mantisse und Exponent in ein anderes Register zu laden.

Vielleicht kann Dich das vor dem Schlimmsten bewahren. Viel Glück !
Sowas brauch ich mir bestimmt nicht anzuhören. Ich kenne das FP-Format sehr genau.

Xmas
2007-02-04, 21:20:02
Muss dieses Angepflaume sein?

Coda, es würde auch dir einmal gut tun deinen Ton etwas zu mäßigen, und vielleicht einmal deine Meinung als weniger absolut hinstellen wenn du Dinge nur vermutest.
Den Exponenten als Integer zu extrahieren braucht 3 skalare PS-Instruktionen. Einen n-Bit-Integer aus der Mantisse zu Extrahieren dann jeweils 7. In Anbetracht dessen dass es sowieso Integer-Eingabewerte für den VS gibt ist das zwar nicht sinnvoll, aber dennoch problemlos möglich ohne "mehrere 100 Instructions" zu verwenden.

Coda
2007-02-04, 21:26:35
Dann hast's immer noch in sau komischem Format und must's noch weiter verwurschteln. 100 war vielleicht übertrieben, aber dennoch ist's viel zu teuer imho.

Xmas
2007-02-04, 21:32:33
Was ist an vorzeichenlosen Ganzzahlen saukomisch? Da es bessere Wege gibt ist es zu teuer, ja, aber es ist möglich da eine (PS-)FPU tatsächlich prinzipiell alles kann was eine Integer-ALU auch kann.

Gast
2007-02-04, 22:01:05
Dann hast's immer noch in sau komischem Format und must's noch weiter verwurschteln. 100 war vielleicht übertrieben, aber dennoch ist's viel zu teuer imho.

Na Coda, da werden wir uns ja am Ende doch noch einig. :) Ich hatte ja
bereits angemerkt, daß man evtl. Abstriche bei der Performance hinnehmen muß:

Die Frage ist sicher wie "komfortabel" /
performant ist das dann, wenn man evtl. keine Bitmanipulationsbefehle
zur Verfügung hat.

Asmodeus
2007-02-05, 08:58:32
Hallo,


Nach reichlicher Überlegung eigentlich nix ;)
Dazu allerdings eine Frage: Wenn ich uint8 als Datentyp für Vertexkomponenten verwende, wird das dann auch so von den GPUs intern verarbeitet und gespeichert oder wird das implizit in einen float umgewandelt?
Der Präzisionsverlust beim Umwandeln in uint8 sollte vertretbar sein, die 256 Werte dürften reichen.


Es sind eigentlich nicht nur vier Werte pro Vertex, sondern 16 * vier Werte pro Vertex :| Und da komm ich mit der Color nicht weit, auch mit Secondary Color nicht.
Da liegt auch das Problem: 64 floats extra pro Vertex ist einfach zu viel. Falls diese Art von Kompression nicht funktioniert, muss ich sehen, dass ich was anderes finde...


Also ich mach das mit OpenGL, was aber egal sein sollte. Und das ganze sollte auch noch auf ATI R300-Karten laufen, von daher fällt wohl auch SM3 raus ;( Nach Coda funktioniert das ja auch nicht auf Pre-DX10 Hardware...

Das die Sache auch noch auf R300 laufen soll, schränkt Deine Möglichkeiten natürlich ziemlich ein. Im Prinzip hättest Du die Möglichkeit, so viele Parameter pro Vertex als Vertex-Attribute an GLSL zu übergeben, oder diese zusätzlichen Werte in Texturen zu packen und dann unter GLSL darauf zuzugreifen. Probleme gibt es mit den Texturen, wenn Du die darin gespeicherten Daten im VS brauchst. Denn bei den ATI Karten, die Du im Auge hast, kannst Du im VS nicht auf Texturen zugreifen. Und selbst bei NV Karten der älteren Generationen (ab NV40) ist es nicht besonders performant.
Hast Du schon mal probiert, ob Du damit auskommen würdest, wenn Du das größtmöglich nutzbare Vertexdatenformat GL_T4F_C4F_N3F_V4F verwendest? Immerhin kannst Du da schon mal 16 Floatwerte pro Vertex speichern. Mit etwas "Kompression" (wie hier schon besprochen) wären es dann sicher noch ein paar mehr.

Gruss, Carsten.

ollix
2007-02-05, 10:26:06
Hi,

ich habe mich gerade am frühen Morgen gefragt und da es ja in etwa hier reinpaßt ...

Wenn ich in GLSL schreiben würde:
float foo[USELESS_ELEMENTS];
float p = factor();
for( int i = 0; i < USELESS_ELEMENTS; ++i )
{
foo[i] *= p;
} Der Compiler würde doch diese statische Schleife ausrollen. Da die GPU ja (gerne) mit Vektoren rechnet und die floats da reinsteckt, würden die Compiler daraus aber auch gleiche die Multiplikation auf dem Vektor machen:

.... = vec4(foo[0], foo[1], foo[2], foo[3]) * p;
Statt für eine Komponente in einem Vektor?

thx

Xmas
2007-02-05, 14:06:07
Möglicherweise ja, eine Garantie dafür gibts aber nicht.

ollix
2007-02-06, 12:58:54
Danke - habe sowas schon vermutet :) Und außer sich mit dem Asm abzukämpfen gibt es wohl auch keine Möglichkeit, daß für bestimmte Implementationen, Karten und Treiber rauszufinden?

Asmodeus
2007-02-06, 13:36:10
Danke - habe sowas schon vermutet :) Und außer sich mit dem Asm abzukämpfen gibt es wohl auch keine Möglichkeit, daß für bestimmte Implementationen, Karten und Treiber rauszufinden?

So wie Demirug das glaube ich mal darlegte, gibt es neben dem Compiler noch eine Art Optimizer. Und auf dessen Funktions- und Arbeitsweise in Bezug auf Codeoptimierung kann man als Anwender glaube ich sowieso keinerlei Einfluss nehmen.

Gruss, Carsten.

ollix
2007-02-06, 15:13:29
Aha ok. Dann vertraue ich einfach mal, daß da alles gut läuft :) Ist dieser Optimizer eher dafür da generelle Verfahren und Konstrukte von beliebigem Code zu optimieren (also z.B. sowas wie oben) oder eher auf z.B. wichtige Spiele?

Demirug
2007-02-06, 19:32:03
Die Optimizer liegen recht weit unten da sie im Prinzip API unabhängig sind. Ob der Shader nun von einem wichtigen Spiel kommt oder nicht ist erst mal egal. Allerdings werden die Treiberentwickler bei der Weiterentwicklung sich eben die Shader von wichtigen Spielen als Beispiele nehmen.
Bei GLSL hast du allerdings ein Problem das mit diesen Optimizer gar nichts zu tun hat. Scheinbar gibt es nach wie vor große Unstimmigkeiten was die Auslegung des Syntaxes angeht und so kann dir schon der Parser einen Shader ablehnen oder noch schlimmer gründlich falsch verstehen.

ollix
2007-02-06, 23:04:52
Bei GLSL hast du allerdings ein Problem das mit diesen Optimizer gar nichts zu tun hat. Scheinbar gibt es nach wie vor große Unstimmigkeiten was die Auslegung des Syntaxes angeht :eek: Hast Du da evtl. einen Link, wo ich dazu was nachlesen kann, oder allgemein genaure Infos zu? thx