我试图了解 memoryBarrier() 在 OpenGL 4.4 中的工作原理,我尝试了以下一次使用纹理图像和一次使用着色器存储缓冲区对象 (SSBO)。基本思想是为需要在我的场景中渲染的许多对象创建一个标志数组,然后在几何着色器中执行一个简单的测试。
对于 GS 中的每个图元,如果至少有一个顶点通过了测试,它会在数组中由该图元的对象 ID 指定的位置设置相应的标志(对象 ID 作为顶点属性传递给 GS)。
然后我执行 memoryBarrier() 以确保所有线程都写入了它们的值。
- 接下来,我从 flags 数组中读取所有基元,如果设置了标志,则只发出一个顶点。
这是我的着色器中的一些代码来解释:
// Vertex Shader:
#version 440
uniform mat4 model_view;
uniform mat4 projection;
layout(location = 0) in vec3 in_pos;
layout(location = 1) in vec3 in_color;
layout(location = 2) in int lineID;
out VS_GS_INTERFACE
{
vec4 position;
vec4 color;
int lineID;
} vs_out;
void main(void) {
vec4 pos = vec4(in_pos, 1.0);
vs_out.position = pos;
vs_out.color = vec4(in_colo, 1.0);
vs_out.lineID = lineID;
gl_Position = projection * model_view * pos;
}
这是一个简单的几何着色器,其中我只使用了一个基于 lineID 的简单测试(我意识到这个测试不需要共享数据结构,但这只是为了测试程序行为)
#version 440
layout (lines) in;
layout (line_strip, max_vertices = 2) out;
layout (std430, binding = 0) buffer BO {
int IDs[];
};
in VS_GS_INTERFACE
{
vec4 position;
vec4 color;
int lineID;
} gs_in[];
out vec4 f_color;
void main()
{
if(gs_in[0].lineID < 500)
{
IDs[gs_in[0].lineID] = 1;
}
else
{
IDs[gs_in[0].lineID] = -1;
}
memoryBarrier();
// read back the flag value
int flag = IDs[gs_in[0].lineID];
if ( flag > 0)
{
int n;
for( n = 0; n < gl_in.length(), n++)
{
f_color = gs_in[n].color;
gl_Position = gl_in[n].gl_Position;
emitVertex();
}
}
}
无论我输入什么值而不是 500,这段代码总是只渲染 2 个对象。如果我将 GS 中的渲染条件更改为 if(flag > = 0),在我看来,所有对象都已渲染,这意味着在着色器读回这些 ID 时永远不会写入 -1。有人可以解释为什么尽管有 memoryBarrier(),但所有着色器调用都不能连贯地看到写入,什么是最有效的解决方法来让它工作?
谢谢。