0

我写了一个小的镶嵌程序。我可以写入 SSBO(使用 RenderDoc 检查输出),但在同一个着色器 (TCS) 中立即读取数据似乎不起作用。如果我直接设置细分级别,我可以看到我的代码有效:

在 Tessellation Control 着色器的主体中:

 gl_TessLevelInner[0] = 1;
 gl_TessLevelOuter[0] = 1;
 gl_TessLevelOuter[1] = 2;
 gl_TessLevelOuter[2] = 4;

但是通过SSBO内存,它不起作用。显示为空白,就像在 gl_TessLevelInner 和 gl_TessLevelOuter 输出中放置了 0。

这是 TCS 中的 SSBO:

   struct SSBO_Data {
      float Inside;   // Inside Tessellation factor
      float Edges[3]; // Outside Tessellation factor
   };

   layout(std430, binding=2) volatile buffer Tiling {
      SSBO_Data Tiles[];
   };

在 Tessellation Control 着色器的主体中

   Tiles[0].Inside   = 1;
   Tiles[0].Edges[0] = 1;
   Tiles[0].Edges[1] = 2;
   Tiles[0].Edges[2] = 4;

   gl_TessLevelInner[0] = Tiles[0].Inside;
   gl_TessLevelOuter[0] = Tiles[0].Edges[0];
   gl_TessLevelOuter[1] = Tiles[0].Edges[1];
   gl_TessLevelOuter[2] = Tiles[0].Edges[2];

在 C++ 中,我使用 nVidia 的 ShaderBuffer 类来创建包含数千个图块的数组并将数据传输到 SSBO。我确认使用 RenderDoc 将正确的数据存储在 SSBO 中。

  • 在 ShaderBuffer 类中,我尝试将 glBufferData 用法更改为 GL_DYNAMIC_DRAW 而不是 GL_STATIC_DRAW 但它没有帮助。
  • 我还将 SSBO 设置为 volatile 但这没有帮助。
  • 我还插入了一个屏障();在 SSBO 数据的写入和读取之间,它也没有帮助。

是否可以在同一个着色器中使用 SSBO 进行写和读?

4

2 回答 2

1
  • 我还在barrier();SSBO 数据的写入和读取之间插入了一个,它也没有帮助。

这不会对您的用例有用,您真正需要的是glMemoryBarrierBuffer().

于 2021-08-01T14:13:56.227 回答
1

从单个着色器实例写入任何不连贯的内存位置(SSBO 或图像加载/存储),然后从同一位置读取在同一阶段工作,当且仅当

  1. 您正在以与写作相同的实例阅读它。
  2. 只有实例写入正在读取的内存。

即使所有实例都写入相同的值,#2 也成立。违反 #2 会创建一个竞争条件(同样,无论写入的值如何),即 UB。

于 2021-08-01T18:50:23.657 回答