GLSL SpinLock solo funciona principalmente

He implementado un algoritmo de pelado en profundidad utilizando un spinlock GLSL (inspirado poresta). En la siguiente visualización, observe cómo funciona correctamente el algoritmo de pelado en profundidad (primera capa superior izquierda, segunda capa superior derecha, tercera capa inferior izquierda, cuarta capa inferior derecha). Las cuatro capas de profundidad se almacenan en una sola textura RGBA.

Desafortunadamente, el spinlock a veces no logra evitar errores: puede ver pequeñas manchas blancas, especialmente en la cuarta capa. También hay uno en el ala de la nave espacial en la segunda capa. Estas manchas varían cada cuadro.

En mi GLSL spinlock, cuando se debe dibujar un fragmento, el programa del fragmento lee y escribe un valor de bloqueo en una textura de bloqueo separada de forma atómica, esperando hasta que aparezca un 0, lo que indica que el bloqueo está abierto.En la práctica, Encontré que el programa debe ser paralelo, porque si dos subprocesos están en el mismo píxel, la deformación no puede continuar (uno debe esperar, mientras que el otro continúa, y todos los subprocesos en una deformación de subproceso de GPU deben ejecutarse simultáneamente).

Mi programa de fragmentos se ve así (comentarios y espacios añadidos):

#version 420 core

//locking texture
layout(r32ui) coherent uniform uimage2D img2D_0;
//data texture, also render target
layout(RGBA32F) coherent uniform image2D img2D_1;

//Inserts "new_data" into "data", a sorted list
vec4 insert(vec4 data, float new_data) {
    if      (new_data<data.x) return vec4(      new_data,data.xyz);
    else if (new_data<data.y) return vec4(data.x,new_data,data.yz);
    else if (new_data<data.z) return vec4(data.xy,new_data,data.z);
    else if (new_data<data.w) return vec4(data.xyz,new_data      );
    else                      return data;
}

void main() {
    ivec2 coord = ivec2(gl_FragCoord.xy);

    //The idea here is to keep looping over a pixel until a value is written.
    //By looping over the entire logic, threads in the same warp aren't stalled
    //by other waiting threads.  The first imageAtomicExchange call sets the
    //locking value to 1.  If the locking value was already 1, then someone
    //else has the lock, and can_write is false.   If the locking value was 0,
    //then the lock is free, and can_write is true.  The depth is then read,
    //the new value inserted, but only written if can_write is true (the
    //locking texture was free).  The second imageAtomicExchange call resets
    //the lock back to 0.

    bool have_written = false;
    while (!have_written) {
        bool can_write = (imageAtomicExchange(img2D_0,coord,1u) != 1u);

        memoryBarrier();

        vec4 depths = imageLoad(img2D_1,coord);
        depths = insert(depths,gl_FragCoord.z);

        if (can_write) {
            imageStore(img2D_1,coord,depths);
            have_written = true;
        }

        memoryBarrier();

        imageAtomicExchange(img2D_0,coord,0);

        memoryBarrier();
    }
    discard; //Already wrote to render target with imageStore
}

Mi pregunta es ¿por qué ocurre este comportamiento de moteado? ¡Quiero que el spinlock funcione el 100% del tiempo! ¿Podría relacionarse con mi ubicación de memoryBarrier ()?