OpenGL/OpenCL: glDrawPixels
-
ich empfehle dir andersrum anzufangen, lade eine datei, uebergib sie opencl, mache deine berechnungen, lad sie von opencl runter und speicher dir dein bild (oder raw daten).
spaeter kannst du opengl zur visualisierung einbauen, aber fuer dein eigentliches vorhaben ist opengl doch nicht noetig. zudem kannst du opencl die float daten als array uebergeben, so wie du das ja moechtest.
-
Naja, ich brauch jetzt erst mal was zum vorzeigen, daher hab ich mit dem OpenGL Teil angefangen, zumal das eventuell als Vorlage dienen soll, um das Studenten in die Hand zu drücken, damit man sich nicht mit QT etc. rum schlagen muss.
Wichtig ist mir eigentlich nur, was ich mir das expliziete kopieren der Daten zwischen OpenGL und OpenCL spare. Ohne diese Anforderung wüsste ich ja genau was ich tun kann, bzw. hätte ich halt deutlich mehr Freiheiten, was die Sache dann trivial macht.
PS: Dot
Das glPixelDraw ist noch im OpenGL drin
Wenn ich das Ding aber in ne Textur speichere, dann kann ich nicht mehr beliebig drauf zugreifen. Das ist scheise.
Irgendwelche Filter etc. will ich auch nicht drauf anwenden in OpenGL.
Mehr als zoomen, verschieben und Kanäle auswählen muss in OpenGL nicht möglich sein.
Eventuell später noch, das man mit der Maus rein zeichnet, aber das ist erst mal egal.
EDIT:
Ihr habt mich grad noch auf eine Idee gebracht!Ich hab jetzt die zwei Funktionen gefunden:
clEnqueueCopyImageToBuffer und clEnqueueCopyBuffertoImageWenn ich dann noch die CL<->GL Austauschfunktionen für Images nutze, sollte es eigentlich funktionieren, oder was meint ihr?
Da sollten dann ja auch hauptsächlich pointer ausgetauscht werden, bzw für die Darstellung muss ich halt einmal hin und her kopieren...
-
Ok Leute, ich verzweifle hier noch
Ich bin von GLubyte auf GLfloat umgestiegen, jetzt muss ich nur einmal unsigned char in float umwandeln, wenn ich das BMP einlese, und das wars dann auch.
Es funktioniert auch alles. Sprich ich kann einzelne Farbkanäle an und aus machen, ich lad meine BMPs der Reihe nach, der OpenCL-Part läuft auch fehlerfrei durch. Sprich alles sieht gut aus.
Jetzt kommt aber der Hacken -.- Der OpenCL Kernel wird ausgeführt, ich setz auch alles, ich hab auch READ_WRITE für die Buffer usw. usw. Ich kopier auch das Ergebnis erfolgreich aus dem GPU-RAM in den RAM der CPU zurück.
Nur mein Kernel macht nichts :ugly: Bzw. der Kernel wird ausgeführt, aber wenn ich die Daten zurück kopiere aus der GPU, dann ändert sich nichts auf dem Bildschirm...
Hier mal einige Programmteile:
EDIT CODE ENTFERNT:
Eigentlich stimmt jeder einzelne Programmteil.... Irgendwo muss da der Wurm drin sein -.-
Kann doch nicht sein, das sich das Bild nicht verändert, obwohl ich die Sachen ja im Kernel berechne...
Was auch verwunderlich ist, ist, das ich unter GLuByte noch ein sich änderndes Bild gesehen habe, wenn ich +1 im Kernel gerechnet habe auf jeden Wert. Das funktioniert jetzt nicht mehr. Egal was ich im Kernel mache, es hat keine Auswirkung mehr -.-
Irgendwo muss da der Wurm drin sein...
EDIT:
Wenn ichout[gid0+size_x+3+gid1*(size_x+2)]=0.1;
In meinen Kernel einfüge, dann wird das dargestellte Bild grau, je nach dem welchen Wert ich nehme....
Der Kernel funktioniert also, nur rechne ich irgendwie nichts aus :ugly:
-
Ok, wie es scheint, klappt irgendwas mit dem Update nicht.....
Die Daten werden aus irgend einem Grund nicht dargestellt -.-
Ich glaub ich muss am Ende doch noch den BMP writer fertig schreiben, und meine Ergebnisse raus schreiben, um zu sehen, wo denn jetzt der Hacken genau liegt...
Wäre echt nett, wenn mal noch jemand drüber schauen könnte. Ich find den Fehler einfach nicht
-
Ok, ich habs jetzt fast. Die Sache funktioniert. Aus irgend einem Grund, hat er mir einen Parameter meines OpenCL Kernels immer auf 0 gesetzt, obwohl sonst alles ging... -.-
Ich hab noch keinen Schimmer, warum er da rum zickt. eigentlich sollte es funktionieren
Naja, wird sich sicherlich auch bald noch herausstellen, was los ist. Daher hat es auch funktioniert, wenn ich +1 gerechnet habe.
Was leider blöd war, und mir einiges an Zeit gekostet hat, um den Fehlr zu finden, und alles am Ende zum laufen zu bekommen, war beim Umstieg auf Float. Ich hab die Skalierung auf 0-255 nicht raus genommen, weil ich dachte, ok, normierste den größten float wert auf 1...
Schlechte idee. Ich hab die Ränder nicht expliziet initialisiert. Ergo waren da SEHR hohe Werte dabei. Meist was mit 10^x mit x>5 Da wurde das Bild dann natürlich sofort schwarz, weil die anderen Werte ja im Bereich 0-1 lagen -.-
Das war ein blöder Fehler, der mich sehr viel Zeit gekostet hat
Ich muss die mal noch auf 1 oder 0 initialisieren...
Naja, was willste machen. Jetzt funktionierts auf jeden Fall, bis auf die Übergabe eines Kernel-Parameters, wo ich noch immer rätsel.
Ich schaff jetzt bei 448x448 Bildpunkten und 10 Iterationen pro Bildausgabe ca 340 FPS und bei 896*896 sind es noch immer 150 FPS.
Leider hab ich nur eine Auslastung von rund 40%. Nutze im Moment aber auch noch keinen local Memory, und keine Vektor-Datentypen. Da geht also noch einiges.
-
Du kanst ein OpenGL Texturobjekt auch mit OpenCL verwenden (vorher umwandeln).
Dann kanst du die Textur mit OpenCl bearbeiten und mit OpenGL einfach mit den üblichen Mechanismen zum Zeichnen von Texturen darstellen.Dann brauchst du kein extrem langsames Pixeldraw.
Du brauchst die Ergebnisse nicht mal über den Bus schicken.
Mir kommt gerade ne Idee
Ich baue mir ein nur GPU Game of Life
-
Skysnake schrieb:
Das glPixelDraw ist noch im OpenGL drin
Nicht in aktuellen Versionen von OpenGL. Natürlich wird es aus Gründen der Abwärtskompatibilität noch unterstützt.
Skysnake schrieb:
Wenn ich das Ding aber in ne Textur speichere, dann kann ich nicht mehr beliebig drauf zugreifen. Das ist scheise.
Was genau meinst du damit?
-
dot schrieb:
Skysnake schrieb:
Das glPixelDraw ist noch im OpenGL drin
Nicht in aktuellen Versionen von OpenGL. Natürlich wird es aus Gründen der Abwärtskompatibilität noch unterstützt.
Also ist es noch drin :ugly:
Ich kann es verwenden, in der aktuellsten Version, also ist es noch drin.
Skysnake schrieb:
Wenn ich das Ding aber in ne Textur speichere, dann kann ich nicht mehr beliebig drauf zugreifen. Das ist scheise.
Was genau meinst du damit?
Du kannst in einem OpenCL kernel entweder lesend, oder schreibend auf ein Image zugreifen, aber nicht beides. Das ist schlecht, wobei es hier sogar noch gehen würde in der aktuellen Implementierung, die ich verwende. Wenn ich dann aber zu einer anderen Methode wechsle, dann muss ich ein LGS lösen, und dann hilft mir das kein Stück weiter.
Aber nochmal kurz zu glDrawPixels. Was könnte ich denn ansonsten noch verwenden? Klar ne Textur, aber würde das einen Performanceunterschied machen, wenn ich da so oft die Textur ändern muss?
Wäre wirklich gut zu wissen, wie man das elegant und performant lösen kann. Die >>100 FPS sind zwar ok, aber mehr ist immer besser
EDIT:
Andreas XXL schrieb:
Du kanst ein OpenGL Texturobjekt auch mit OpenCL verwenden (vorher umwandeln).
Dann kanst du die Textur mit OpenCl bearbeiten und mit OpenGL einfach mit den üblichen Mechanismen zum Zeichnen von Texturen darstellen.Dann brauchst du kein extrem langsames Pixeldraw.
Du brauchst die Ergebnisse nicht mal über den Bus schicken.
Mir kommt gerade ne Idee
Ich baue mir ein nur GPU Game of LifeBtw. das umwandeln geht nicht -.- laut der OpenCL DeviceInfo wird diese Erweiterung von meiner 5870 nicht unterstützt. Ich sollte aber diese Woche zum programmieren/testen ne 7970 bekommen. Vielleicht kann die das dann.
Wobei ich mich schon frag, in wie weit das am Ende alles noch schneller ist.
-
Skysnake schrieb:
dot schrieb:
Skysnake schrieb:
Das glPixelDraw ist noch im OpenGL drin
Nicht in aktuellen Versionen von OpenGL. Natürlich wird es aus Gründen der Abwärtskompatibilität noch unterstützt.
Also ist es noch drin :ugly:
Ich kann es verwenden, in der aktuellsten Version, also ist es noch drin.
Im Compatibility Profile wird es noch unterstützt. Im Core Profile ist es nichtmehr drin und auf einem entsprechenden OpenGL Context ist es damit auch nichtmehr verfügbar. glDrawPixels() ist seit OpenGL 3.0 deprecated und mit OpenGL 3.2 offiziell removed (eine aktuelle OpenGL Version wäre 3.3 bzw. 4.2, was in etwa Direct3D 10 bzw. 11 entspricht).
Skysnake schrieb:
Skysnake schrieb:
Wenn ich das Ding aber in ne Textur speichere, dann kann ich nicht mehr beliebig drauf zugreifen. Das ist scheise.
Was genau meinst du damit?
Du kannst in einem OpenCL kernel entweder lesend, oder schreibend auf ein Image zugreifen, aber nicht beides. Das ist schlecht, wobei es hier sogar noch gehen würde in der aktuellen Implementierung, die ich verwende. Wenn ich dann aber zu einer anderen Methode wechsle, dann muss ich ein LGS lösen, und dann hilft mir das kein Stück weiter.
Ich weiß nicht was genau du da machen möchtest, aber wäre vielleicht Double Buffering eine Lösung? Also zwei Buffer, wobei in jeder Iteration eben immer aus einem Werte gelesen, in den anderen Werte geschrieben und dann die Buffer geswapped werden?
Skysnake schrieb:
Aber nochmal kurz zu glDrawPixels. Was könnte ich denn ansonsten noch verwenden? Klar ne Textur, aber würde das einen Performanceunterschied machen, wenn ich da so oft die Textur ändern muss?
Der einzige Weg um das sicher rauszufinden ist, es auszuprobieren. Ich kann dir nur sagen dass der moderne Weg afaik ein Fullscreen Quad mit Textur drauf ist.
-
Danke für die Info.
Für die Studenten ist das mit dem glDrawPixels halt recht schön und anschaulich, wie ich finde. Daher lass ich es dafür wahrscheinlich drin.
Wie sähe denn die Version mit der Textur aus? Kannste da kurz paar Codeschnipsel hin schreiben bzgl allocation, befüllen und Darstellung?
Das mit dem Double-Buffer kannste knicken, weil dem Lösen eines LGS machste das normal inPlace.
Wäre auch sinnfrei so was in eine Textur zu packen, einfach weil der Sinn dahinter ja nicht mehr stimmt, und auch die Form eine ganz andere ist. Das sind ja teils nur noch Bandmatrizen.
Wichtig ist, das ich zumindest schon mal was hab, was läuft und recht einfach zu verwenden ist.
Montag schreib ich dann mal den Writer für 24Bit Farbtiefe BMPs und dann muss ich mal schauen, ob ich das noch auf die anderen möglichen BMP Farbtiefen beim einlesen erweitere.
Falls es interessiert, kann ich ja auch mal paar Screens hoch laden. Sagt einfach Bescheid.
Btw. mit Glut sollte man doch Textfeld und Buttons auch erstellen können. Kannt das sein, dass das in der ganz normalen GLUT nicht drin ist? Hab mal danach gesucht aber nichts gefunden.
-
Ok, wenn ich das recht verstehe hast du folgenden Ablauf:
- Zeug auf die Graka laden
- Gleichungssystem lösen
- Darstellen
Dann arbeit in OpenCL einfach mit normalen Buffern, kopier das Ergebnis am Ende in eine OpenGL Textur und render die.
Dazu müssen deine Daten die Graka nie verlassen. Du hast deine OpenGL Texture, baust dir per clCreateFromGLTexture2D() ein OpenCL Image dazu und kopierst dann per clEnqueueCopyBufferToImage() die Daten auf der Grafikkarte.
Das ist auf jeden Fall effizienter als die Daten von der Grafikkarte in den RAM zu kopieren, nur um sie dann von dort wieder zurück auf die Grafikkarte zu kopieren...
-
Muss ich aber im Moment aber leider eh machen
Wie gesagt, laut dem clDeviceInfo unterstützt meine 5870 nicht den Extension für CL/GL Interoperabilität -.-
Also zumindest sagt mir die Abfrage, dass die Karte das nicht kann. Ich sollte es vielleicht doch einfach noch mal testen.
Muss ich eventuell irgendwelche Compilerflags angeben um das zu nutzen?
-
Du kannst in einem OpenCL kernel entweder lesend, oder schreibend auf ein Image zugreifen, aber nicht beides.
Dann übergib das Image einfach zweimal an den Kernel.
Einmal lesend und einmal schreibend. Das funktioniert. Habs gerade ausprobiert.
-
MisterX schrieb:
Du kannst in einem OpenCL kernel entweder lesend, oder schreibend auf ein Image zugreifen, aber nicht beides.
Dann übergib das Image einfach zweimal an den Kernel.
Einmal lesend und einmal schreibend. Das funktioniert. Habs gerade ausprobiert.Dann hast du Glück gehabt, denn das ist laut OpenCL Spezifikation undefiniert....
-
Dann mach halt nen zweiertausch.
Textur (A) lesend. Textur (B) schreibend.
Dann textur (B) lesend und Textur (A) schreibend.
usw.Das ist dann definiert.
-
Genau darüber haben wir hier aber schon auf der letzten Seite diskutiert oder so...
-
Ja, aber für was den Heck Meck machen, wenn man einfach ganz stink normale Buffer verwenden kann, auf denen man auch ganz stink normal rechnet.
Images sind manchmal ganz nett, aber das wars auch.