【发布时间】:2014-08-12 19:48:13
【问题描述】:
是不是 GLSL 中的 memoryBarrier 对单个着色器调用中的内存事务进行排序,而 OpenGL API 中的 glMemoryBarrier 对多个着色器调用(不一定属于同一程序)的内存事务进行排序。
【问题讨论】:
-
没人愿意回答这个问题吗?
是不是 GLSL 中的 memoryBarrier 对单个着色器调用中的内存事务进行排序,而 OpenGL API 中的 glMemoryBarrier 对多个着色器调用(不一定属于同一程序)的内存事务进行排序。
【问题讨论】:
是不是 GLSL 中的 memoryBarrier 对内存中的事务进行排序? 单个着色器调用和 OpenGL API 中的 glMemoryBarrier 跨多个着色器调用(其中 不一定属于同一个程序)。
不完全是。您应该首先明确什么是着色器调用:它是处理单个输入实体的着色器代码的执行。因此,对于您进行的绘制调用的每个顶点都有一个顶点着色器调用,并且对于光栅化产生的每个片段至少有一次片段着色器调用(在某些类型的多重采样中它将不止一个)。不同绘制调用(可能不同)的着色器调用当然也是不同的调用。但通常情况下,当谈到“多次调用”时,指的是同一个着色器,在同一个绘图调用期间(所有这些调用都可能并行执行)。
GLSL spec (version 4.40)(第 8.17 节)对内存屏障有这样的说法:
所有类型的着色器都可以读取和写入纹理的内容和 使用图像变量缓冲对象。而读取的顺序和 在单个着色器调用中写入是明确定义的,相对 对单个共享内存地址的读取和写入顺序 多个单独的着色器调用在很大程度上是未定义的。命令 由一个着色器调用执行的内存访问,如观察到 其他着色器调用,也很大程度上是未定义的,但可以 通过内存控制函数控制。
因此,这可能是也可能不是您对上述语句的含义,具体取决于您对“单个调用”的含义。但前提是您将其解释为“单个绘图调用的所有调用”。
来自OpenGL 4.4 core profile specification,第 7.12.2 节
需要显式同步以确保 着色器执行的缓冲区和纹理数据存储将对 后续操作使用相同的对象并且不会覆盖 数据仍需由先前请求的操作读取。没有 手动同步,“新”原语的着色器存储可能 在“旧”原语的处理完成之前完成。 此外,“旧”原语的存储可能无法完成 在开始处理“新”原语之前。
所以这也不仅仅是关于后续绘制调用的着色器调用。它甚至根本不需要新的着色器调用:如果以下 GL 命令使用或覆盖了着色器写入的数据,则必须手动同步它。请注意,这仅在您的着色器写入缓冲区或纹理时才相关,它与通过管道写入的“普通”帧缓冲区无关:
同一着色器类型的调用的相对顺序是 不明确的。在处理图元 B 时由着色器发出的存储 可能在存储原始 A 之前完成,即使原始 A 在原语 B 之前指定。这甚至适用于片段 着色器;而片段着色器输出被写入帧缓冲区 在原始顺序中,片段着色器调用执行的存储是 不是。
我建议您阅读完整的第 7.12 节,此处太长,无法粘贴,但对于理解 GL 的内存屏障功能至关重要。
【讨论】: