是否允许使用barrier()
跟随但不同的流量控制?
在符合OpenGL 4.00标准的计算着色器中,我做了一些涉及分歧(即非动态统一)分支语句的工作。稍后在同一个着色器中,我需要同步执行该工作组中的所有调用以进行内存访问。这对提高效率也有好处,因为我希望他们都能互相锁定。但是,在咨询了khronos.org wiki和refpages之后,我不清楚我想要做的事情是否符合标准(无论它是否在实践中有效)。
从this page,我们看到:
对屏障的调用可能不会放在任何控制流程中。
从this page,我们看到:
barrier()
可以从流控制中调用,但只能从统一流控制中调用。所有导致评估barrier()
的表达式必须是动态统一的。
首先,关于流量控制的明显矛盾。我假设只有不同的(在工作组内)流量控制是不允许的?
其次,在我看来,对于在发散流量控制之后发生的barrier()
的调用存在一些歧义。重要的是,请再次注意“导致评估屏障()的所有表达式必须是动态统一的。”#34;这是否意味着导致,或......?一些例子可以帮助说明我的困惑。
void main() {
// ... do some work here ...
barrier(); // valid use case
// ... do some more work ...
}
void main() {
if (IS_BEST_WORK_GROUP) { // dynamically uniform within work group
// ... do some work here ...
barrier(); // valid use case
// ... do some more work ...
}
}
void main() {
if (IS_BEST_INVOCATION) { // divergent within work group
// ... do some work here ...
barrier(); // this is illegal
// ... do some more work ...
}
}
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 ...
}
答案 0 :(得分:3)
唯一的声明来源是GLSL Specification。
第8.16节规定:
对于曲面细分控制着色器,barrier()函数可能只放在曲面细分控制着色器的函数main()内,并且可能不会在任何控制流中调用。 [...]
对于计算着色器,barrier()函数可以放在流控制中,但该流控制必须是统一的流控制。
您的示例4非常好,因为对barrier
的调用不在任何控制流程中。只要确保所有着色器调用达到相同的屏障,在屏障之前执行的操作无关紧要。
答案 1 :(得分:1)
NV_compute_program5扩展中的某些其他Nvidia特定信息:
第2.X.8.Z节,酒吧:执行壁垒
BAR指令在本地工作组内同步执行计算着色器调用。当计算着色器调用执行BAR指令时,它将暂停直到当前本地工作组中的所有调用都执行了相同的BAR指令。一旦所有调用都执行了BAR指令,就继续执行BAR指令之后的指令。
程序中允许BAR的位置没有编译时限制。但是,在分流控制中不允许使用BAR指令。如果工作组中的任何计算着色器调用执行了BAR指令,则所有计算着色器调用都必须执行该指令。 BAR指令的执行结果是不确定的,如果发出该指令,则可能导致应用程序挂起和/或程序终止:
- 在REP / ENDREP块的任何迭代中的
在任何IF / ELSE / ENDIF块中,其中IF指令评估的条件的结果在整个工作组中都不相同;
中,其中工作组中的至少一个调用已使用CONT指令跳过了下一个迭代,使用BRK或RET指令退出了循环,或退出了循环,因为已完成了请求的循环迭代次数;或
在任何子例程(包括main)中,其中工作组中至少有一个调用已使用RET指令退出了该子例程。