防止片段着色器中的循环展开

Man*_*nux 5 loops glsl webgl

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

首先,我发现循环的长度受到严格限制的困难方式(doc说它必须在编译时可猜测,这意味着它必须是常数或非常接近).

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

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

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

我不觉得着色器花费一分钟来编译循环的大约一百次迭代是正常的.或者我做错了什么?片段着色器中的一百次迭代对于GPU来说太过分了吗?因为它在编译之后似乎运行得很好.

Toj*_*oji 6

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

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


ema*_*key 5

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

ANGLE 是一款嵌入在 Windows 操作系统上支持 WebGL 的浏览器中的软件,它使用您的 GLSL 着色器并在运行时将其转换为 Direct3D HLSL 着色器。其想法是,与 OpenGL 驱动程序相比,大多数 Windows 机器具有更新的 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。