我正在使用最新版本的Chrome(和Firefox)为WebGL(GLSL ES 1.0)编写片段着色器,我编写了一个迭代算法。
首先,我发现循环的长度受到严格限制的困难方式(doc说它必须在编译时可猜测,这意味着它必须是常量或非常接近)。
另外,我必须写一个(for
,因为它是必须根据标准实现的唯一一个)循环,它可能很长但几乎每次都会中断端。
现在,我注意到如果我设置了更高的最大数量,则着色器的编译和链接需要更多时间。所以,除非我错了,否则编译器会循环展开。
我不确定是否可以做任何事情,但我已经尝试了一些东西,编译器似乎也内联函数,即使在循环中调用。
我不觉得着色器花费一分钟来编译一个循环的大约一百次迭代是正常的。或者我做错了什么?片段着色器中的一百次迭代对于GPU来说太过分了吗?因为它在编译之后似乎运行得很好。
答案 0 :(得分:4)
这是GLSL不幸的现实之一。如果我们可以进行离线编译并发送字节码,或者如果我们能够在编译时指定标志等,那将是很好的,但这不是规范的工作方式。你完全受驾驶员制造商的支配。如果NVIDIA / ATI认为循环展开对你有好处,你的循环就会被展开。
我确实怀疑你正在做什么,这需要如此多的循环。着色器并不是进行超复杂循环或分支计算的正确位置。你肯定会受到性能的打击。如果你不担心实时性能,那么在程序开始时可能会出现大量编译并不是那么糟糕。如果您担心应用程序的渲染速度,那么您可能需要重新评估着色器的复杂性。
答案 1 :(得分:4)
你提到着色器花了一分多钟来编译一个最多只有大约100次迭代的循环,这让我觉得你的问题可能与ANGLE有关。
ANGLE是一个嵌入在Windows操作系统上支持WebGL的浏览器中的软件,可以将您的GLSL着色器在运行时转换为Direct3D HLSL着色器。我们认为大多数Windows机器与其OpenGL驱动程序相比具有更新的Direct3D驱动程序,因此默认行为是将所有内容转换为D3D。根据我的经验,这可能很慢,特别是对于你所描述的长循环,尽管很多Windows用户都需要它,特别是那些基于英特尔图形的用户。
如果您运行的是Windows并且拥有高质量的OpenGL驱动程序,例如来自nVidia或AMD的合理新驱动程序,您可以尝试禁用ANGLE以查看它是否能解决您的问题。在Google Chrome上,可以通过编辑Chrome图标将--use-gl=desktop
添加为命令行参数(在图标的“目标”字段中)并重新启动浏览器来完成此操作。对于Firefox,您可以访问about:config
并在搜索框中输入webgl
,然后查找webgl.prefer-native-gl
并将其设置为true。
在禁用ANGLE的情况下再次尝试着色器,并且可以改进编译时间。请记住,这只是一个Windows问题,因此在其他平台上编辑这些设置无效,但我相信所有其他平台都直接使用本机OpenGL。
答案 2 :(得分:1)
可悲的是AMD 可能不支持这个,但我认为NVidia有一个很好的pragma unroll指令。对于遇到相反问题的人,您可以将其作为" #pragma optionNV(展开全部)"在GLSL中,但我认为以下内容将阻止展开。我引用DenisR's 2008 post on the NVidia forums:
默认情况下,编译器以已知的行程计数展开小循环。但是,#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 question selective-nvidia-pragma-optionnvunroll-all似乎暗示这可能在GLSL中起作用,至少在某些平台下是这样。)
似乎有一种暗示,近年来,AMD可能支持展开的pragma(虽然可能不在GLSL中),但我不熟悉并且没有尝试过它:unroll loops in an AMD OpenCL kernel
(如果在Chrome / Firefox或其他场景中通过WebGL使用GLSL,请记住,GLSL编译可能会通过ANGLE管道传输,这可能会在Windows上呈现为HLSL后端。我有一个对此的理解非常有限,并且不希望传播信息,所以绝对不要引用它;我只是觉得有必要分享我迄今为止收集的关于这个问题的信息,并乐意编辑这个答案(或者人们可以随时编辑此答案),因为有更多确认信息可供使用。)