Opengl 在GLSL 4.1中使用switch语句

Opengl 在GLSL 4.1中使用switch语句,opengl,switch-statement,glsl,Opengl,Switch Statement,Glsl,我最近读了一篇可怕的帖子,有人声称GLSL中的switch语句没有使用条件分支,事实上每次输入switch时都会运行所有可能的结果。这让我很担心,因为我目前正在开发一个延迟渲染引擎,它使用一些嵌套的switch语句 有人知道这件事是否属实吗?有没有证据可以证明 谢谢 我最近读了一篇可怕的帖子,有人声称GLSL中的switch语句没有使用条件分支,事实上每次输入switch时都会运行所有可能的结果 这两种说法都不一定正确。至少在今天的硬件上没有 发生的情况非常依赖于编译器和底层硬件体系结构。所以没

我最近读了一篇可怕的帖子,有人声称GLSL中的switch语句没有使用条件分支,事实上每次输入switch时都会运行所有可能的结果。这让我很担心,因为我目前正在开发一个延迟渲染引擎,它使用一些嵌套的switch语句

有人知道这件事是否属实吗?有没有证据可以证明

谢谢

我最近读了一篇可怕的帖子,有人声称GLSL中的switch语句没有使用条件分支,事实上每次输入switch时都会运行所有可能的结果

这两种说法都不一定正确。至少在今天的硬件上没有

发生的情况非常依赖于编译器和底层硬件体系结构。所以没有一个答案。但它也非常依赖于另一件事:实际情况是什么

请看,编译器执行条件两侧的原因与GPU的工作方式有关。GPU通过将线程分组在一起并在锁定步骤中执行它们来获得性能,每个线程组执行完全相同的步骤序列。对于条件分支,这是不可能的。因此,要执行一个真正的分支,您必须根据执行哪个分支的各个线程来分解一个组

因此,如果这两个分支相当短,它将同时执行这两个分支,并放弃未执行分支中的特定值。由于专门的操作码等原因,特定的值丢弃不需要断开线程组

好的,如果条件是基于ie的:一个表达式,它在绘图调用/上下文中总是相同的,那么编译器很有可能不会同时执行这两个方面。它将做一个真实的条件

因为条件是动态统一的,所以组中的所有线程都将执行相同的代码。因此,不需要中断一组线程来执行适当的条件

因此,如果您有一个基于统一变量的switch语句,或者表达式只涉及统一常量变量和编译时常量变量,那么就没有理由期望它同时执行多个分支


还应该注意的是,即使表达式不是动态统一的,编译器也不会总是同时执行这两个分支。如果分支太长或差异太大或其他情况,它可以选择拆分线程组。这可能会降低性能,但可能不如同时执行两个组。真正由编译器来决定如何执行。

按照我的理解,现代硬件不仅仅是为了避免在动态统一的条件下执行两个分支。只要线程组、扭曲、波前或供应商使用的任何术语中的所有线程将条件计算为相同的值,则只执行一个分支。仅当条件在扭曲/波前内发散时,它才会开始执行两个分支。这是动态发生的,因此它不必提前知道条件是否会偏离。@RetoKoradi:这是硬件的功能还是编译器与硬件协同工作的功能?也就是说,如果编译器可以静态地确定特定条件在波前内永远不会发散,那么编译器是否能够告诉硬件不要费心考虑发散?如果是这样的话,那么只有在绝对必要的时候才使用非动态统一分支还是值得的。这必须是硬件特性。我相信在有效处理分行方面已经取得了很大的进展。除了更复杂的图形用例之外,我认为计算机(通常有更复杂的控制流)在这方面发挥了重要作用。如果您提前知道将使用哪个分支,那么可以优化执行。甚至可以在消除一个分支的位置构建着色器。但我不知道这些是否有益,是否被使用。@RetoKoradi谢谢,这非常有用,也非常有趣。在我的例子中,我在片段着色器中为全屏四元体使用嵌套的switch语句,打开在前面的过程中写入的缓冲区中的值。我发现在我正在开发的较新的NVidia卡上,速度非常快,但在我不得不测试卡的ATI/AMD上,速度非常慢——就像在18秒内绘制50幅24x24大小的图像一样慢!我修改了代码,改为使用子例程,这似乎大大改善了情况。干杯@DasLouis:哪款AMD硬件?它是基于GCN的吗?此外,如果您可以切换到子例程,这意味着您可以一直使用基于统一表达式的switch语句。那么,如果这样做而不是使用从缓冲区获取的值,会发生什么呢?