2012-08-04 60 views
2

我試圖實現GLSL自旋鎖,以便能夠實現單程深度剝離。我遇到了麻煩,因爲鎖定紋理使用的例子很少。我不得不承認,我並不真正知道自己在做什麼,所以我只是爲了安全起見而描述可能更多的背景。GLSL Spinlock永不終止

我寫了一個片段程序,它應該做的有效虛無

#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); 

要執行的算法,我拿一個FBO,用色RGBA F32渲染附件並啓用它。我結合以上着色器,然後通過所述鎖定紋理img2D_0和彩色附着到img2D_1,使用此代碼:

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

該目的然後用VBO渲染,和一些第二通行證顯示數據的內容。

問題是給出的片段程序崩潰視頻驅動程序(因爲它永遠不會終止)。我的問題是爲什麼?紋理初始化爲0,我很確定我的交換函數的邏輯是有效的。我的設置和方法基本正確嗎?

+0

通過對紋理進行採樣並將值存儲到另一個紋理,將它們轉儲到主機上,從而確信它已被正確初始化。 – 2012-08-04 15:20:54

+0

這是一個很好的測試。如果鎖定爲0,則移除破碎的代碼並存儲vec4(0.25,0.0,0.0,0.0),如果鎖定爲1,則vec4(0.0,0.50,0.0,0.0),否則存儲vec4(0.0,0.0,0.75,0.0)並且將結果轉儲到數據紋理僅顯示(0.25,0.0,0.0,0.0) - 即(至少在開始時)所有鎖定值均爲0. – imallett 2012-08-04 15:30:23

+0

轉儲着色器反彙編。 – 2012-08-04 15:45:17

回答

3

一個問題是,如果同一個warp中的兩個線程碰到同一個鎖定位置,那個warp將會死鎖,因爲一個線程將獲得鎖定,另一個線程將循環,warp將繼續執行循環線程,阻止帶鎖的線程進行任何進程。

編輯

根據修改後的引擎收錄,我建議是這樣的:

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

這避免了經循環僵局的線程留下了的是那些已經完成其鎖定修改。如果只有一個線程可以獲得其鎖定,那麼該線程將會取得進展。

+0

這怎麼可能?所有線程中的線程應該來自同一個原語,是的? – 2012-08-04 22:31:42

+0

只繪製一個隨機三角形,問題不會發生。繪製兩個隨機三角形,問題最終會發生 - 我懷疑三角形是否重疊。 – imallett 2012-08-05 01:35:11

+0

我重寫了控制流程以考慮到這一點,這使問題消失。如果沒有人有更好的解釋,我會接受這個答案。該算法現在主要工作在http://pastebin.com/WL2SMyrJ。我添加了可最大程度減少工件的memoryBarrier調用,但仍有一些工件。我把它們寫在後面,儘管我似乎回想起在某處他們無法控制流量,我認爲這意味着包括循環 - 這可能是問題嗎? – imallett 2012-08-05 01:51:28