2

我试图了解 memoryBarrier() 在 OpenGL 4.4 中的工作原理,我尝试了以下一次使用纹理图像和一次使用着色器存储缓冲区对象 (SSBO)。基本思想是为需要在我的场景中渲染的许多对象创建一个标志数组,然后在几何着色器中执行一个简单的测试。

  1. 对于 GS 中的每个图元,如果至少有一个顶点通过了测试,它会在数组中由该图元的对象 ID 指定的位置设置相应的标志(对象 ID 作为顶点属性传递给 GS)。

  2. 然后我执行 memoryBarrier() 以确保所有线程都写入了它们的值。

  3. 接下来,我从 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(),但所有着色器调用都不能连贯地看到写入,什么是最有效的解决方法来让它工作?

谢谢。

4

0 回答 0