我的other post打算收集有關GLSL自旋鎖的種類的一般信息,但不幸的是沒有它的結果,也沒有解決我的問題。因此,一個具體的問題。我將問題簡化爲一個簡單的例子,如下所示:GLSL原子圖像訪問
這個微不足道的問題使得屏幕尺寸的紋理顏色和鎖定紋理。在第一遍中,顏色全部設置爲零(着色器1)。在第二遍中,繪製了兩個三角形,其中幾何着色器四倍和稍微偏移(着色器2)。片段着色器以原子方式遞增紋理的顏色。在通過三時,顏色被可視化(着色器3)。
着色器1:
//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;
}
着色器2:
//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;
}
着色器3:
//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
}
主循環:
- 啓用着色器1
- 渲染全屏四
glMemoryBarrier(GL_ALL_BARRIER_BITS);
啓用着色器2
- 渲染的兩個小三角形
glMemoryBarrier(GL_ALL_BARRIER_BITS);
啓用的Shader 3
- 呈現全屏四
注意,在步驟3和6 I [想我]可能有使用GL_SHADER_IMAGE_ACCESS_BARRIER_BIT。以防萬一,我保守。
可視化的顏色隨着時間的抖動,而且大都相當小。這表明原子沒有發生。有人可以檢查這個程序嗎?我錯過了什麼?
編輯:從this page,我發現使用discard
可以使圖片加載/存儲未定義的片段。我刪除了丟棄物,但問題仍然存在。我還發現layout(early_fragment_tests) in;
,這迫使早期片段測試(它也沒有幫助)。
的緩衝代碼不起作用(第一個版本渲染任何東西之前給出了GL錯誤,我報告,並鏈接的一個崩潰)。在查找其他示例代碼的同時,我還發現http://soconne.blogspot.com/p/demos.html,其中各種由於內部編譯器錯誤而崩潰。我也嘗試了for循環。必須有更好的方法,比試圖將製造商的代碼用於廣告宣傳。 – imallett