2

我有一个片段着色器,它使用图像加载/存储操作对 imageBuffer 执行处理。我只关心以下情况:

  • 我有一个片段着色器(没有多阶段(例如顶点然后片段着色器)考虑因素,也没有多通道渲染)
  • imageBuffer 变量被声明为一致的。只对连贯的 imageBuffers 感兴趣。

为了清楚起见,我的情况如下:

// Source code of my sole and unique fragment shader:
coherent layout(1x32) uniform uimageBuffer data;

void main()
{
  ...
  various calls to imageLoad(data, ..., ...);
  ...
  various calls to imageStore(data, ..., ...);
  ...
}

我主要查看了规范

ARB_shader_image_load_store

尤其是这一段:

“使用声明为“连贯”的变量可以保证存储的结果将立即对使用类似声明的变量的着色器调用可见;调用 MemoryBarrier 是为了确保存储对其他操作可见。”

注意:我的“连贯统一的 imageBuffer 数据;” 声明正是一个“类似声明”的变量。我的场景是单通道、单阶段(片段着色器)。

现在,我查看了各种网站并偶然发现(就像我认为的大多数人一样)stackoverflow.com 上的这个线程:

GPU驱动程序如何解释GLSL的“连贯”内存限定符以进行多遍渲染?

更具体地说,本段:

“你的着色器甚至不能假设在存储之后立即发出负载将获得刚刚存储在这个着色器中的内存(是的,真的。你必须放入一个 memoryBarrier 才能将它拉下来)。”

我的问题如下:

使用指定的连贯限定符,在我的单着色器、单通道处理场景中,我是否可以确定 imageStore() 将立即对我的片段着色器的所有调用可见(例如,当前调用也是如此)与其他并发调用一样)?

通过阅读 ARB_shader_image_load_store 规范,在我看来:

  • 这个问题的答案是肯定的,
  • 我不需要任何类型的 memoryBarrier(),
  • stackoverflow 中上述引用的线程中引用的句子可能确实具有误导性和错误性。

感谢您的洞察力。

4

2 回答 2

0

使用那个内存屏障。

一方面,GPU 可以优化并获取整个内存块以读取 FROM,并具有单独的内存来写入 TO。

换句话说,如果您的着色器总是只修改一次位置,那么它就可以了,但是如果它在应用了一些计算之后中继邻居值,那么您需要内存屏障。

于 2014-05-22T08:38:48.787 回答
0

使用指定的连贯限定符,在我的单着色器、单通道处理场景中,我是否可以确定 imageStore() 将立即对我的片段着色器的所有调用可见(例如,当前调用也是如此)与其他并发调用一样)?

如果每个片段着色器写入图像中的不同位置,并且每个片段着色器只读取它写入的位置,那么您甚至不需要coherent. 但是,如果片段着色器实例想要读取其他片段着色器实例写入的数据,那么您就是 SOL。你对此无能为力

如果它是一个计算着色器,您可以发出barrier调用以同步工作组内的操作。这将确保您想要读取的写入发生(您仍然需要memoryBarrier调用以使它们可见)。但这只会确保来自该工作组内的实例的写入已经发生。来自其他实例的写入仍未定义。

更具体地说,本段:

顺便说一句,那段是错误的。非常非常错误。太糟糕了,写那段的人永远不会被发现;)

于 2015-12-29T00:45:00.810 回答