[Tutorial] GameOfLife OpenGL/OpenCL

Um was gehts?

OpenGL kennen die meisten ja aus dem Kontext der Spieleentwicklung. OpenCL dagegen ist eher weniger bekannt. OpenCL ist vergleichbar mit OpenGL, man verwendet die Grafikkarte für Berechnungen. Anders als bei OpenGL ist OpenCL aber nicht auf Grafik an sich ausgelegt, sondern kann alle Art Berechnungen ausführen. (Ein bisschen wie ComputeShader)

Da ich gerade mitten in meiner Thesis stecke, die sich um OpenCL dreht, und außerdem eine Veranstaltung an der Hochschule über Paralleles Rechnen besuche, dachte ich mir ich verbinde die beiden Dinge miteinander. Wie so oft wird in der Veranstaltung GameOfLife als Beispiel verwendet und mit MPI parallelisiert, was eher etwas für Supercomputer ist. GPU Programmierung kommt gar nicht vor. Außerdem wollte ich OpenCL und OpenGL  sowieso immer mal in Kombination verwenden.

Verwenden, was schon existiert

Ich bin kein Freund davon alles von Scratch zu machen, also hab ich im Netz nach GameOfLife Implementierungen in OpenCL gesucht un so einige gefunden. Relativ zügig zum Laufen gebracht habe ich diese hier: Conways-Game-of-Life-Parallelized. Also geforked und hier ist das Ergebnis auf GitHub(Code here!).

Der Code auf Github enthält Globals, Hacks und ist generell unglaublich hässlich. Also bitte nur zum nachvollziehen verwenden.

Context Sharing

Nachdem OpenGL mit Glut ein Fenster erzeugt kann es los gehn. Der erste Schritt ist den Kontext von OpenGL zum erzeugen des openCL Kontextes zu verwenden. Dafür gibt es betriebssystemabhängig Funktionen um den aktuellen Kontext zu bekommen. Bei Windows so:

Entgegen anderer Infos aus dem Internet, muss bei GLUT folgendes vor dem erzeugen des Kontextes aufgerufen werden, da der Kontext sonst nicht current ist.
glutInitWindowSize(800, 600);
glutCreateWindow(„Test“);

Texturen erzeugen:

Als nächstes werden zwei Texturen in OpenGL erzeugt. Also das ganze zwei mal.

Da wir nur Grauwerte haben reicht uns GL_LUMINANCE aus. glTexImage2D läd dann die Daten hoch und texture ist unser TexturHandle.

OpenCL Textur erzeugen

Als nächstes wird das Handle für OpenCL erzeugt:

Die Objekte anfordern

Damit OpenCL auf die Objekte zugreifen kann müssen diese vorher angefordert werden.

So jetzt ist alles vorbereitet und dem Kernel können die Argumente zugewiesen werden.

Kernel ausführen

Jetzt wird der Kernel ausgeführt und die Objekte werden anschließend wieder freigegeben.

Wenn man mit Texturen arbeitet muss man das natürlich im Kernel so definieren. Eine OpenGL2D Texture hat den Typ image2d_t und eine Textur kann niemals gleichzeitig gelesen und beschrieben werden.

Außerdem wird zum lesen ein Sampler benötigt. Dieser fängt allerdings auch OutOfBounds Zugriffe ab und kann Interpolieren etc.

Zeichnen

Jetzt ist die Ausführung beendet und die Daten in der Textur wurden verändert. Die Textur wird nun in ein Quad gezeichnet.

Das ganze läuft bei einer Auflösung von 4k (3840×2160) mit ~44 FPS mit einer Geforce GTX 970.

Related Posts

Leave a reply