[英]GLSL Atomic Image Access
我的另一篇文章打算收集有關GLSL自旋鎖種類的一般信息,但是不幸的是,它沒有任何進展,也沒有解決我的問題。 因此,有一個具體的問題。 我將問題簡化為一個最小的示例,如下所示:
瑣碎的問題使屏幕大小的鎖紋理和顏色紋理成為可能。 在第一遍中,所有顏色均設置為零(着色器1)。 在第二遍中,繪制了兩個三角形,幾何着色器四倍並且略有偏移(着色器2)。 片段着色器原子地增加紋理的顏色。 在第三遍中,顏色是可見的(着色器3)。
//Vertex
#version 440
uniform mat4 mat_P;
in vec4 _vec_vert_a;
void main(void) {
gl_Position = mat_P*_vec_vert_a;
}
//Fragment
#version 440
layout(rgba32f) coherent uniform image2D img0;
void main(void) {
imageStore(img0,ivec2(gl_FragCoord.xy),vec4(0.0,0.0,0.0,1.0));
discard;
}
//Vertex
#version 440
in vec4 _vec_vert_a;
out vec4 vert_vg;
void main(void) {
vert_vg = _vec_vert_a;
}
//Geometry
#version 440
#define REPS 4
layout(triangles) in;
layout(triangle_strip,max_vertices=3*REPS) out;
uniform mat4 mat_P;
in vec4 vert_vg[3];
void main(void) {
for (int rep=0;rep<REPS;++rep) {
for (int i=0;i<3;++i) {
vec4 vert = vert_vg[i];
vert.xy += vec2(5.0*rep);
gl_Position = mat_P*vert; EmitVertex();
}
EndPrimitive();
}
}
//Fragment
#version 440
layout(rgba32f) coherent uniform image2D img0;
layout(r32ui) coherent uniform uimage2D img1;
void main(void) {
ivec2 coord = ivec2(gl_FragCoord.xy);
bool have_written = false;
do {
bool can_write = (imageAtomicExchange(img1,coord,1u)!=1u);
if (can_write) {
vec4 data = imageLoad(img0,coord);
data.xyz += vec3(1.0,0.0,0.0);
imageStore(img0,coord,data);
memoryBarrier();
imageAtomicExchange(img1,coord,0);
have_written = true;
}
} while (!have_written);
discard;
}
//Vertex
#version 440
uniform mat4 mat_P;
in vec4 _vec_vert_a;
void main(void) {
gl_Position = mat_P*_vec_vert_a;
}
#version 440
layout(rgba32f) coherent uniform image2D img0;
void main(void) {
vec4 data = imageLoad(img0,ivec2(gl_FragCoord.xy));
gl_FragData[0] = vec4(data.rgb/4.0, 1.0); //tonemap
}
glMemoryBarrier(GL_ALL_BARRIER_BITS);
啟用着色器2
glMemoryBarrier(GL_ALL_BARRIER_BITS);
啟用着色器3
請注意,在第3步和第6步中,我[認為我]本可以使用GL_SHADER_IMAGE_ACCESS_BARRIER_BIT。 以防萬一,我很保守。
可視化的顏色會隨着時間而抖動,並且通常很小。 這表明原子性沒有發生。 有人可以檢查這個程序嗎? 我有什么想念的嗎?
編輯:從此頁面 ,我發現使用discard
可以使圖像加載/存儲在片段中未定義。 我刪除了丟棄物,但問題仍然存在。 我還發現了layout(early_fragment_tests) in;
,這會強制進行早期片段測試(也沒有幫助)。
上次我測試它時有效的一些自旋鎖代碼(幾年前授予):
http://blog.icare3d.org/2010/07/opengl-40-abuffer-v20-linked-lists-of.html
在以上鏈接中,使用了一條金絲雀,這絕對是重要的,甚至可能仍然如此。 coherent
很重要,但是你有。 幾年前, memoryBarrier()
根本沒有實現,什么也沒做。 我希望不是這種情況,但是它可能是自旋鎖工作得很好,並且不會按照隨后的讀取順序對img0
進行寫操作。
GLSL編譯器有時可能會有些bug。 以下是一些示例,以展示奇怪的GLSL編碼如何獲得。 重點是,嘗試使用多種不同的方式編寫相同的代碼會有所幫助。 我已經看到了while循環失敗時函數作為條件的問題。 就我所知,.. while與典型的while編譯有很大不同。 將盡可能多的條件組合到循環條件中有時也會有所幫助。 有時, else break
無法達到預期效果,或者使編譯器無法展開某些循環,因此您必須使用以下命令:
for (...)
{
if (...)
{
...
continue;
}
break;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.