问题
是否允许在发散流控制之后但在发散流控制之外使用 barrier()
?
详细信息
在兼容 OpenGL 4.00 的计算着色器中,我正在做一些涉及发散(即非动态统一)分支语句的工作。稍后在同一个着色器中,我需要同步该工作组内所有调用的执行,以便进行内存访问。这也有利于提高效率,因为我希望它们都能彼此保持同步。然而,在查阅了 khronos.org wiki 和 refpages 后,我不清楚我想做的事情是否符合标准(无论它在实践中是否有效)。
来自this page ,我们看到:
Calls to barrier may not be placed within any control flow.
来自this page ,我们看到:
barrier()
can be called from flow-control, but it can only be called from uniform flow control. All expressions that lead to the evaluation of abarrier()
must be dynamically uniform.
首先,流量控制方面存在明显的矛盾。我假设它只是不允许的发散(工作组内)流量控制?
其次,在我看来,关于在发散流量控制之后发生的对 barrier()
的调用存在一些歧义。重要的是,请再次注意“所有导致对barrier()求值的表达式必须是动态统一的”这一断言。这是否意味着导致,或者……?一些例子可以帮助说明我的困惑。
示例 1,有效:
void main() {
// ... do some work here ...
barrier(); // valid use case
// ... do some more work ...
}
示例 2,有效:
void main() {
if (IS_BEST_WORK_GROUP) { // dynamically uniform within work group
// ... do some work here ...
barrier(); // valid use case
// ... do some more work ...
}
}
示例3,无效:
void main() {
if (IS_BEST_INVOCATION) { // divergent within work group
// ... do some work here ...
barrier(); // this is illegal
// ... do some more work ...
}
}
示例 4,不明确:
void main() {
if (IS_BEST_INVOCATION) { // divergent within work group
// ... do some work here ...
}
barrier(); // is this allowed?
// it occurs after, but outside of, a divergent branch statement
// ... do some more work ...
}
- 如果示例 4 确实有效,我应该在哪里找到明确形式的此信息?
- 或者,如果它无效,是否有其他机制可以让我的所有调用在发散分支条件后恢复锁步状态?
- 如果上述两项都不是,这可以在 Vulkan 中实现吗?
最佳答案
唯一的声明来源是 GLSL Specification .
第 8.16 节规定:
For tessellation control shaders, the barrier() function may only be placed inside the function main() of the tessellation control shader and may not be called within any control flow. [...]
For compute shaders, the barrier() function may be placed within flow control, but that flow control must be uniform flow control.
您的示例 4 非常好,因为对 barrier
的调用不在任何控制流中。只要确保所有着色器调用都到达相同的障碍,在障碍之前做什么并不重要。
关于OpenGL Barrier() 函数和发散流控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48657248/