2016-12-16 5 views
4

Ich habe versucht, einen allgemeinen Compute Shader Gaussian Blur Implementierung zu schreiben.Compute Shader Shared Memory enthält Artefakte

Es funktioniert im Grunde, aber es enthält Artefakte, die jedes Bild ändern, selbst wenn die Szene statisch ist. Ich habe die letzten paar Stunden damit verbracht, das zu debuggen. Ich bin so weit gegangen, die Grenzen nicht zu überschreiten, alle Schleifen abzurollen, Uniformen durch Konstanten zu ersetzen, aber die Artefakte bleiben bestehen.

Ich habe den ursprünglichen Code mit Artefakten auf 3 verschiedenen Maschinen/GPUs (2 nvidia, 1 Intel) getestet und sie alle produzieren die gleichen Ergebnisse. Das Simulieren der entrollten/konstanten Version der Codeausführung mit Arbeitsgruppen, die mit reinem C++ - Code vorwärts und rückwärts ausgeführt werden, erzeugt diese Fehler nicht.

enter image description here

Durch eine gemeinsame Anordnung von [96] [96] anstelle von [16] [48] Zuteilen kann ich die meisten Artefakte vermeiden.

Das brachte mich dazu, zu denken, dass mir ein logischer Fehler fehlte, daher gelang es mir, einen sehr einfachen Shader zu erzeugen, der den Fehler in kleinerem Maßstab erzeugt. Ich würde es schätzen, wenn jemand die Ursache aufzeigen könnte . Ich habe viele Unterlagen überprüft und kann nichts falsch finden.

Ein gemeinsam genutztes Array von 16x48 Floats wird zugewiesen, das sind 3072 Byte, ungefähr 10% des minimalen gemeinsamen Speicherlimits.

Der Shader in 16x16 Arbeitsgruppen gestartet wird, so dass jeder Faden wird auf 3 einzigartige Stellen schreiben und lesen zurück von einer einzigen einzigartigen Lage

Die Textur wird dann als HSV Renderer wobei vals zwischen 0-1 wird abzubilden Farbton 0-360 (rot-cyan-rot), und Werte außerhalb der Grenzen sind rot.

#version 430 
//Execute in 16x16 sized thread blocks 
layout(local_size_x=16,local_size_y=16) in; 
uniform layout (r32f) restrict writeonly image2D _imageOut; 
shared float hoz[16][48]; 
void main() 
{ 
    //Init shared memory with a big out of bounds value we can identify 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 20000.0f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 20000.0f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 20000.0f; 
    //Sync shared memory 
    memoryBarrierShared(); 
    //Write the values we want to actually read back 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y] = 0.5f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+16] = 0.5f; 
    hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+32] = 0.5f; 
    //Sync shared memory 
    memoryBarrierShared(); 
    //i=0,8,16 work 
    //i=1-7,9-5,17 don't work (haven't bothered testing further 
    const int i = 17; 
    imageStore(_imageOut, ivec2(gl_GlobalInvocationID.xy), vec4(hoz[gl_LocalInvocationID.x][gl_LocalInvocationID.y+i])); 
    //Sync shared memory (can't hurt) 
    memoryBarrierShared(); 
} 

Das Starten dieses Shaders mit Startabmessungen größer als 8x8 führt zu Artefakten im betroffenen Bereich des Bildes.

glDispatchCompute(9, 9, 0); glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

Ich musste Frames Breakpoint und Schritt, dies zu erfassen, nahm um 14 Frames enter image description here

glDispatchCompute(512/16, 512/16, 0);//Full image is 512x512 glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);

Wieder musste ich Stopp-und Schritt Rahmen dieses zu erfassen, Beim Ausführen mit 60FPS (vsync) erschienen Artefakte häufiger/gleichzeitig.

enter image description here

Antwort

5
memoryBarrierShared(); 

Nein, das nur schreibt sichtbar anderen Anrufungen macht. Sie müssen sicherstellen, dass alle Schreibvorgänge tatsächlich passiert sind, wenn Sie aus anderen Invocations Daten lesen können.

Das ist mit the barrier function getan. Welches sollte nach die memoryBarrierShared genannt werden.

+0

Danke, das ist es behoben. Nochmals skimming docs zu schnell. – Robadob