OpenGL barrier()函数和Divergent Flow Control

时间:2018-02-07 06:22:56

标签: opengl shader gpgpu

问题

是否允许使用barrier()跟随但不同的流量控制?

详细

在符合OpenGL 4.00标准的计算着色器中,我做了一些涉及分歧(即非动态统一)分支语句的工作。稍后在同一个着色器中,我需要同步执行该工作组中的所有调用以进行内存访问。这对提高效率也有好处,因为我希望他们都能互相锁定。但是,在咨询了khronos.org wiki和refpages之后,我不清楚我想要做的事情是否符合标准(无论它是否在实践中有效)。

this page,我们看到:

  

屏障的调用可能不会放在任何控制流程中。

this page,我们看到:

  

barrier()可以从流控制中调用,但只能从统一流控制中调用。所有导致评估barrier()的表达式必须是动态统一的。

首先,关于流量控制的明显矛盾。我假设只有不同的(在工作组内)流量控制是不允许的?

其次,在我看来,对于在发散流量控制之后发生barrier()的调用存在一些歧义。重要的是,请再次注意“导致评估屏障()的所有表达式必须是动态统一的。”#34;这是否意味着导致,或......?一些例子可以帮助说明我的困惑。

示例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中完成的吗?

2 个答案:

答案 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指令的执行结果是不确定的,如果发出该指令,则可能导致应用程序挂起和/或程序终止:

  • 在任何IF / ELSE / ENDIF块中,其中IF指令评估的条件的结果在整个工作组中都不相同;

  • 在REP / ENDREP块的任何迭代中的
  • 中,其中工作组中的至少一个调用已使用CONT指令跳过了下一个迭代,使用BRK或RET指令退出了循环,或退出了循环,因为已完成了请求的循环迭代次数;或

  • 在任何子例程(包括main)中,其中工作组中至少有一个调用已使用RET指令退出了该子例程。