GLSL Spinlock永不终止

时间:2012-08-04 14:37:11

标签: glsl

我正在尝试实现GLSL自旋锁,以便能够实现单遍深度剥离。我遇到了麻烦,因为锁定纹理使用的例子很少。我不得不承认,我真的不知道我在做什么,在这里,所以为了安全起见,我描述的内容可能比必要的更多。

我写了一个片段程序,它应该没有任何效果:

#version 420 core

//The lock texture holds either 0 or 1.
//0 means that the texture is available.
//1 means that the texture is locked.  
layout(r32ui) coherent uniform uimage2D img2D_0; //locking texture

layout(RGBA32F) coherent uniform image2D img2D_1; //data texture (currently unused)

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

    //The loop's exchange function swaps out the old value with 1.

    //If the locking texture was 0, 0 will be returned, terminating the loop;
    //the locking texture will now contain 1, indicating that the locking
    //texture is now locked.

    //Conversely, if the locking texture contains 1, then the exchange function
    //will write a 1 (so the texture is still locked), and return 1, indicating
    //that the texture is locked and unavailable.
    while (imageAtomicExchange(img2D_0,coord,1u)==1u);

    //The locking texture is locked.  More code would go here

    //This unlocks the texture.
    imageAtomicExchange(img2D_0,coord,0);
}

锁定纹理的创建方式如下:

//data is an array initialized to all 0.
glTexImage2D(GL_TEXTURE_2D,0,GL_R32UI,size_x,size_y,0,GL_RED_INTEGER,GL_UNSIGNED_INT,data);

为了执行算法,我带了一个带有RGBA F32颜色渲染附件的FBO并启用它。我绑定上面的着色器,然后使用以下代码将锁定纹理传递给img2D_0并将颜色附件传递给img2D_1:

glBindImageTextureEXT(
    /* 0, 1, respectively */,
    texture_id, 0,GL_FALSE,0, GL_READ_WRITE,
    /* GL_R32UI, GL_RGBA32F, respectively */
);

然后使用VBO渲染对象,并且一些辅助传递显示数据的内容。

问题是给定的片段程序会崩溃视频驱动程序(因为它永远不会终止)。我的问题是为什么?纹理初始化为0,我很确定我的交换函数的逻辑是有效的。我的设置和方法基本上是否正确?

1 个答案:

答案 0 :(得分:3)

一个问题是,如果同一warp中的两个线程命中相同的锁定位置,则该warp将死锁,因为一个线程将获取锁定而另一个线程将循环,并且warp将继续执行循环线程,这可以防止带锁的线程从未取得任何进展。

修改

根据你修改过的pastebin,我会建议像:

bool done = false;
while (!done) {
    if ((done = (imageAtomicExchange(img2D_0,coord,1u)==0))) {
        // guarded operations
                 :
        imageStore(img2D_0, coord, 0);
    }
}

这可以避免warp循环死锁,因为线程遗漏的是那些已经完成锁定修改的线程。如果只有一个线程可以获得其锁定,那么该线程将取得进展。