SSBO 可以在同一个着色器中读/写吗?

问题描述

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

tessellation Control 着色器的主要部分:

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

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

这是 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,但这没有帮助。
  • 我还插入了一个barrier();在 SSBO 数据的写入和读取之间,它也没有帮助。

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

解决方法

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

这不会对您的用例有用,您实际需要的是 glMemoryBarrierBuffer()

,

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

  1. 您正在阅读它的同一个实例进行写作。
  2. 只有那个实例写入了正在读取的内存。

#2 保持即使所有实例都写入相同的值。违反 #2 会产生竞争条件(同样,无论写入的值如何),即 UB。