|
Textprobe:
Kapitel 5.3, Realisierung: Die Implementierung besteht aus zwei Teilbereichen. Zum Einen hält die Grafikbibliothek OpenGL die Kontrolle über alle Vorgänge. Sie regelt den Datentransfer, d.h. den Transfer von Texturen, zwischen Grafikkarte und Hauptspeicher sowie die Berechnung von Bildpunkten in der Zieltextur. Zum Anderen werden die eigentlichen Berechnungen mit GPU-Programmen durchgeführt. Eine klare Aufgabentrennung ist gegeben. Eine Multiplikation von zwei langen Integer-Zahlen ist auf folgende Weise umgesetzt worden:
1. Es wird im Hauptspeicher ein (zweidimensionales) Array für eine Textur von 128x128 Bildpunkten gebildet, die die beiden Faktoren von je 128 Byte in den ersten beiden Texturzeilen enthält. Diese und eine leere Textur werden durch OpenGL auf die Grafikkarte transferiert.
2. Es wird ein Frame Buffer Object erzeugt, an das (nur) die Ausgabetextur angehängt wird. Nach jedem Berechnungsvorgang eines der GPU-Programme wird die letzte Zieltextur als Eingabetextur gebunden und umgekehrt.
3. Es werden durch ein Fragment-Programm alle Partialprodukte gebildet. Die zweite leere Textur wird als Zieltextur gebunden und nimmt alle Partialprodukte auf, d.h. alle Ergebnisse des Rendervorgangs.
4. Aus den Partialprodukten werden die Spaltensummen mit einem weiteren GPU-Programm berechnet.
5. Die Verrechnung aller Überträge ist der letzte notwendige Rechenschritt. Er besteht aus vielen sequentiellen Schritten und ist mittels GPU-Programmierung nur aufwendig realisierbar. Der Algorithmus besteht aus vielen Vertauschungen von Eingabe- und Ausgabetextur mit kleinen Rechenphasen.
6. Die letzte Ausgabetextur wird durch OpenGL in den Hauptspeicher gelesen. Sie enthält das Produkt der Eingabe-Multiplikanden. OpenGL legt den Koordinatenursprung immer auf den linken unteren Bildpunkt einer Textur. Wird das ganze System imaginär um die y-Achse gedreht, dann steht die Textur ‚auf dem Kopf’, d.h. alle Zeilen sind in umgekehrter Reihenfolge und das Texel mit den Koordinaten (0.5, 0.5) befindet sich in der linken oberen Ecke der Textur. Mit dieser Betrachtungsweise wurde gearbeitet, weil sich die Übertragung der schriftlichen Multiplikation auf Operationen mit Texturen intuitiver nachvollziehen lässt. In allen eigenen Cg-Programmen ist die Variable inputTexture vom Typ samplerRECT (d.h. rechteckige Textur) eine Referenz auf die jeweils gesetzte Eingabetextur. Der Eingabeparameter float w wird immer konsistent auf den Wert der Texturbreite gesetzt. Die Variable texcoord wird stets der Cg-Variable TEXCOORD0 zugewiesen. Sie enthält die interpolierten Koordinaten des aktuellen Fragments, das berechnet wird.
Die folgenden Kapitel beschreiben die Realisierung einzelner Teilimplementierungen im Detail. Kapitel 5.3.1 beschreibt die verwendeten Datenformate und wie die Faktoren und das Ergebnis in einer Textur abgelegt werden. Kapitel 5.3.2 erläutert Frame Buffer Objects, eine im Frühjahr 2005 verabschiedete Erweiterung für OpenGL. Sie findet in der Implementierung Verwendung. Die weiteren Unterkapitel beschreiben die Umsetzung einzelner Rechenschritte. Sie erläutern die Erzeugung von Texturen (Kapitel 5.3.3), die Berechnung der Partialprodukte (Kapitel 5.3.5), die Summenbildung über die Spalten (Kapitel 5.3.6) und die Verarbeitung der Überträge (Kapitel 5.3.7). Punkt 1 und 6 der oben stehenden Aufzählung beinhalten den Transfer von Texturdaten von und zur Grafikkarte und sind in Kapitel 5.3.4 zusammengefasst.
Kapitel 5.3.1, Datenformate: Zur Multiplikation werden die beiden Faktoren a und b in einem festgelegten Format in der primären Eingabetextur abgelegt. Die GPU-Programme erwarten dieses Format und können nur so korrekt arbeiten. Faktor a befindet sich beginnend mit dem höchstwertigen der N Byte in den Texeln mit den Texturkoordinaten (0.5, 0.5) (N 0.5, 0.5) (siehe Abbildung 5.4). Faktor b wird analog in der zweiten Texturzeile abgelegt, d.h. in die Bildpunkte mit den Koordinaten (0.5, 1.5) (N 0.5, 1.5).
Die restliche Textur darf beliebig belegt sein; sie wird nicht ausgewertet und hat keinen Einfluss auf die Berechnungen. Das Ergebnis p belegt maximal so viele Byte wie beide Faktoren a und b zusammen belegen. Das letzte Fragment-Programm legt das Ergebnis beginnend mit dem höchstwertigen Byte p2N in der zweiten Texturzeile ab. Die letzten 128 Byte befinden sich in der ersten Zeile. Wird die Textur in ein Array im Hauptspeicher ausgelesen, muss beachtet werden, dass in dem Feld die Ergebnisbyte in der Reihenfolge pn p1, p2N pN+1 vorliegen.
Kapitel 5.3.2, Frame Buffer Objects: Frame Buffer Objects (FBOs) sind eine Erweiterung (Extension) für OpenGL, die im Februar 2005 verabschiedet wurde. Sie ermöglicht so genanntes off-screen rendering, d.h. die Verwendung des Grafikprozessors für Berechnungen, deren Resultate nicht zwangsweise auf den Bildschirm ausgegeben werden. FBOs werden in dieser Implementierung eingesetzt. Die Ergebnisse einer Berechnung mit einem GPU-Programm werden stets in einen Frame Buffer geschrieben. FBOs ermöglichen, diesen Puffer wie eine Textur sofort auszulesen. Dies war vor Einführung der Erweiterung nicht direkt möglich. Der Frame Buffer musste in eine Textur kopiert und dann ausgelesen werden. Wenn Berechnungsergebnisse aus dem Grafikspeicher gelesen werden sollen, ersparen Frame Buffer Objects eine Kopieroperation im Grafikspeicher.
Gleichzeitig wird auch Speicherplatz gespart, weil die Informationen nicht mehr doppelt im Speicher abgelegt sind. Insbesondere der Bereich des GPGPU (GPG) profitiert sehr von der FBO Extension.
Kapitel 5.3.3, Erzeugung von Texturen: Eine Textur muss in OpenGL erzeugt werden, bevor sie mit Texturdaten belegt und verwendet werden kann. OpenGL kann als eine Zustandsmaschine betrachtet werden, deren Zustand über globale Parameter festgelegt ist. Die Parameter haben z.B. Einfluss auf die Abbildung von Texturen und das verwendete Koordinatensystem. In dieser Implementierung werden konsequent rechteckige Texturen (GL_TEXTURE_RECTANGLE_ARB) verwendet. Die Koordinaten haben eine Spanne von (0, Texturbreite])x (0, Texturhöhe) und Texel werden ‚mittig adressiert’, d.h. der linke untere Bildpunkt hat die Koordinaten (0.5, 0.5). Die sonst üblichen quadratischen Texturen haben eine Koordinatenspanne von (0,1) x (0,1), die entsprechend über alle Texel interpoliert.
Algorithmus 4 zeigt die Funktion create_texture(), die eine neue Textur erzeugt, die zunächst leer ist. An die Funktion wird der Parameter textureID übergeben, der mit einer eindeutigen Identifikationsnummer belegt wird, über den die Textur angesprochen werden kann. Mit glEnable (GL_TEXTURE_RECTANGLE_ARB)wird die Unterstützung für rechteckige Texturen aktiviert.
|