6

我正在使用最新版本的 Chrome(和 Firefox)为 WebGL(GLSL ES 1.0)编写片段着色器,并编写了一个迭代算法。

所以首先,我发现循环的长度非常有限(文档说它在编译时必须是可猜测的,这意味着它必须是一个常数或非常接近)。

此外,我必须编写一个 ( for,因为它是唯一一个必须根据标准实现的) 循环,该循环可能很长,但几乎每次在结束前都会中断。

现在,我注意到如果我设置更高的最大数量,着色器的编译和链接会花费更多时间。所以,除非我错了,否则编译器会循环展开。

我不确定是否可以做任何事情,但我尝试了一些事情,编译器似乎也内联函数,即使在循环中调用也是如此。

我不觉得着色器花费整整一分钟来编译大约一百次循环迭代是不正常的。还是我做错了?对于 GPU 来说,片段着色器中的一百次迭代是否太多了?因为它编译后似乎运行得很好。

4

3 回答 3

6

这是 GLSL 的不幸现实之一。如果我们可以进行离线编译并发送字节码,或者我们能够在编译时指定标志等等,那就太好了,但这不是规范的工作方式。您完全受驱动程序制造商的摆布。如果 NVIDIA/ATI 认为循环展开对您有好处,那么您的循环就会展开。

不过,我确实质疑你在做什么需要如此多的循环。着色器并不是真正适合进行超复杂循环或分支计算的地方。你肯定会因此而受到打击。如果您不担心实时性能,那么程序开始时的大量编译命中可能还不错。如果您担心应用程序的渲染速度,那么您可能需要重新评估着色器的复杂性。

于 2012-04-26T18:35:05.803 回答
5

你提到着色器需要一分钟多的时间来编译一个最多只有大约 100 次迭代的循环,这让我认为你的问题可能与ANGLE有关。

ANGLE 是一款嵌入在 Windows 操作系统上支持 WebGL 的浏览器中的软件,它采用您的 GLSL 着色器并在运行时将其转换为 Direct3D HLSL 着色器。想法是大多数 Windows 机器与它们的 OpenGL 驱动程序相比具有更新的 Direct3D 驱动程序,因此默认行为是将所有内容转换为 D3D。以我的经验,这可能会很慢,尤其是在您描述的长循环中,尽管许多 Windows 用户都需要它,尤其是那些使用基于 Intel 的图形的用户。

如果您运行的是 Windows 并且您拥有高质量的 OpenGL 驱动程序,例如来自 nVidia 或 AMD 的相当新的驱动程序,您可以尝试禁用 ANGLE 以查看它是否能解决您的问题。在 Google Chrome 上,这是通过编辑您的 Chrome 图标以添加--use-gl=desktop为命令行参数(在图标的“目标”字段中)并重新启动浏览器来完成的。对于 Firefox,您可以访问about:configwebgl在搜索框中输入内容,然后查找webgl.prefer-native-gl并将其设置为 true。

在禁用 ANGLE 的情况下再次尝试您的着色器,编译时间可能会得到改善。请记住,这只是一个 Windows 问题,因此在其他平台上编辑这些设置没有效果,但我相信所有其他平台都直接使用原生 OpenGL。

于 2012-04-27T19:23:11.803 回答
1

遗憾的是 AMD可能不支持这一点,但我认为 NVidia 有一个不错的 pragma unroll 指令。对于遇到相反问题的人,您可以在 GLSL 中将其调用为“#pragma optionNV (unroll all)”,但我认为以下内容会阻止展开。我在 NVidia 论坛上引用了 DenisR 2008 年的帖子

默认情况下,编译器展开具有已知行程计数的小循环。然而,#pragma unroll 指令可用于控制任何给定循环的展开。它必须放在紧接在循环之前,并且仅适用于该循环。可选地后跟一个数字,指定循环必须展开多少次。

例如,在此代码示例中:

#pragma unroll 5

for (int i = 0; i < n; ++i)

循环将展开 5 次。程序员有责任确保展开不会影响程序的正确性(在上面的示例中,如果 n 小于 5,它可能会影响程序的正确性)。

#pragma unroll 1 

将阻止编译器展开循环。

如果在#pragma unroll 之后没有指定数字,则如果其行程计数恒定,则循环完全展开,否则根本不展开。

所以我会想象

#pragma optionNV (unroll 1)

可能在 GLSL(和 WebGL?)中工作。(例如,StackOverflow 问题 selected-nvidia-pragma-optionnvunroll-all似乎暗示这可能在 GLSL 中有效,至少在某些平台下是这样。)

似乎暗示近年来,AMD 可能支持展开 pragma(虽然可能不在 GLSL 中),但我不熟悉也没有尝试过:unroll loops in an AMD OpenCL kernel

(如果在 Chrome/Firefox 甚至其他场景中通过 WebGL 使用 GLSL,请记住,GLSL 编译可能通过ANGLE进行管道传输,这可能会渲染到 Windows 上的 HLSL 后端。我对此了解非常有限,请不要'不想传播信息,所以绝对不要引用;我只是觉得有必要分享到目前为止我收集到的关于这个问题的信息,并且很乐意编辑这个答案(或者人们应该随时编辑这个答案)随着更多确认信息的出现。)

于 2016-10-21T05:39:33.653 回答