2016-04-08 4 views
0

Ich spiele ein paar Tricks auf IOS, um einen CPU-GPU-Hybrid-JPEG-Encoder zu bauen. Von meinen Tests mit der CPU glaube ich, dass die Verwendung von GPU zur Durchführung der DCT- und Quantisierungsschritte sinnvoll ist und die Überleistung deutlich steigern sollte (das Komprimieren einer großen Anzahl von JPEGs ist der Flaschenhals in meiner App). Mit Transformationsfeedback sollte dies machbar sein, da ich das verwendet habe, um großartige Ergebnisse beim GPGPU-Computing zu erzielen. Der schwierige Teil ist, wie man die Daten (unsigned int8's von RGBA) effizient erhält.Abrufen von Integer/Byte-Texturdaten "wie es ist" in OpenGL ES 3.0

Wie bereits erwähnt, habe ich OpenGL ES 3.0 zu tun GPGPU-Computing zu verwenden, so dass ich nur Erfahrung mit float-Punkt Texturen, welches Set-up von

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,WIDTH,HEIGHT,0,GL_RGBA,GL_GLOAT,data); 

und von

an den Shadern geliefert

Aber jetzt sind meine Eingabedaten als ein Array von unsigned Bytes (oder Uint8) gespeichert und ich muss nacheinander 64 von ihnen jedes Mal abrufen. Ich denke, ich kann sie entweder als eine Textur von Bytes ohne Vorzeichen oder effizienter abrufen, da eine Textur von Ganzzahlen ohne Vorzeichen sie dann durch Bitverschiebungen trennt.

Meine Frage ist, wie mache ich eigentlich beide? Genauer gesagt, wie soll ich die internalFormat, Format und Typ für glTexImage2D()? Ich habe viele Kombinationen ausprobiert, aber alle liefern nur 0 in den Shadern (und ich habe die Datenquelle doppelt überprüft, dass sie keine Null sind).

+0

Für ein normales RGBA haben Sie bereits 4 Bytes pro Pixel. Die glTexImage2D() kann verwendet werden, um Byte für Byte abzurufen, da jede der Komponenten vec4 eines dieser Bytes darstellt.Die Werte sind normalisiert, daher müssen Sie sie mit 255 multiplizieren, um einen Ganzzahlwert zu erhalten, der ein Byte darstellt. Sie können also 64 Bytes erhalten, indem Sie 16 (64/4) Aufrufe an glTexImage2D() vornehmen. Oder verpasse ich hier etwas? –

+0

Entschuldigung, nicht die glTexImage2D(). Ich meine das Texel im Shader holen. –

+0

Ja, das war mein Plan-B. Das Problem, das ich mit diesem habe, ist, dass ich nicht weiß, wie man Texturen holt, die als unsigned Bytes gespeichert werden (oder wie man glTexImage2D dafür konfiguriert). Ich würde gerne nach Plan-A springen, wenn möglich, in dem ich eine ganze Zahl (von vier Bytes) anstelle eines einzelnen Bytes als "Pixel" abrufe, was die Anzahl der Aufrufe auf 64/4/4 = 4 reduzieren würde. –

Antwort

0

In ES 3 sollten Sie ernsthaft einen Pixel-Entpackpuffer erstellen und ihn zuordnen, um einen Speicherort für Ihre Pixeldaten zu erhalten. Das wird zumindest einen treiberinternen memcpy speichern und kann erheblich zur Verringerung der Synchronisation genutzt werden. Siehe GL_PIXEL_UNPACK_BUFFER auf glBindBuffer und gl[Un]MapBuffer[Range]; Am Ende steht glTexImage2D(..., (void *)0);, um den Pixel-Entpackpuffer als Quelle anzugeben, analog zur Art, in der gebundene Puffer als Quelle für Attribute, Elemente usw. angegeben werden. Siehe glFenceSync für die Synchronisation unter der Annahme, dass Sie GL_MAP_UNSYNCHRONIZED_BIT verwenden und damit umgehen möchten Synchronisiere dich selbst.

Für ganzzahlige RGBA (keine Skalierung) verwenden Sie GL_RGBA8UI als das interne Format, GL_RGBA_INTEGER als das Format, GL_UNSIGNED_BYTE als den Typ; Deklarieren Sie dann usampler2d ('u' für unsigned, implicitly integer) und verwenden Sie einen Standard texture(sampler, coordinate) zum Abtasten.

Sie möchten auch GL_CLAMP_TO_EDGE und GL_NEAREST Textur-Parameter.

EDIT: auch potenziell erwähnenswert, die Werte von usampler2d sind vom Typ uvec4, so dass sie integral sind. Im Gegensatz zu ES 2 hat ES 3 echte ganze Zahlen, einschließlich bitweiser Operatoren - ES 2 erlaubt ihnen, durch Floats emuliert zu werden (für diejenigen von uns aus den 90er Jahren ist dies wirklich eine unerwartete Zukunft). So wird ein vereinfachtes und ausreichend trivial sein werter Schnipsel aus einem aktuellen Emulation Projekt von mir zu erwähnen:

vec4 rgb_sample(usampler2D sampler, vec2 coordinate) 
{ 
    uint texValue = texture(sampler, coordinate).r; 
    return vec4(texValue & 4u, texValue & 2u, texValue & 1u, 1.0); 
} 

Was natürlich ist das Auspacken einen TTL-Stils RGB-in-One-Byte-Einkanal-Textur ein Format, das für gl_FragColor geeignet ist (basierend auf Sättigung).

+0

Vielen Dank für die vielen Details! Es macht Sinn für mich und ich werde aktualisieren, wie es nach dem Ausprobieren funktionierte. :) –