我正在使用最新版本的Chrome(和火狐)为WebGL编写一个片段着色器(GLSLes1.0),我还编写了一个迭代算法。
因此,首先,我发现循环的长度是非常有限的(doc说在编译时它必须是可猜测的,这意味着它必须是一个常数或非常接近)。
此外,我还必须编写一个(for,因为它是唯一必须按照标准实现的)循环,这个循环可能很长,但在结束之前几乎每次都会中断。
现在,我已经注意到,如果我设置一个更高的最大数目,编译和链接着色器需要更多的时间。所以,除非我错了,否则编译器会进行循环展开。
我不确定是否可以做任何事情,但我尝试了一些事情,编译器似乎也会内联函数,即使在调用循环时也是如此。
我觉得一个着色器花上整整一分钟的时间来编译一个循环的大约100次迭代是不正常的。还是我做错了什么?一个片段着色器中的100个迭代对于GPU来说是不是太过了?因为在编译之后,它似乎运行得很好。
发布于 2012-04-26 18:35:05
这是GLSL的不幸现实之一。如果我们能够进行脱机编译并发送字节码,或者我们有能力在编译时指定标志等等,那就太好了,但这不是规范的工作方式。你完全任由司机制造商摆布。如果NVIDIA/ATI认为循环展开对您有好处,那么您的循环将被展开。
不过,我确实怀疑你所做的事情需要如此多的循环。着色器不是真正适合做超复杂的循环或分支计算的地方。你肯定会因此而受到一场演出的打击。如果您不担心实时性能,那么在您的程序开始时的一次大的编译命中可能并不是那么糟糕。如果您关心您的应用程序的渲染速度,那么您可能需要重新评估您的着色器的复杂性。
发布于 2012-04-27 19:23:11
您提到的着色器需要超过一分钟的时间来编译一个循环,最多只需要100次迭代,这使我认为您的问题可能与夹角有关。
角是一个嵌入在Windows上支持WebGL的浏览器中的软件,它使用GLSL着色器并在运行时将其转换为Direct3D HLSL着色器。人们认为,与OpenGL驱动程序相比,大多数Windows机器都有较新的OpenGL驱动程序,因此默认行为是将所有内容转换为D3D。根据我的经验,这可能是缓慢的,特别是长循环,正如您所描述的,虽然它是许多Windows用户所需要的,特别是那些基于Intel的图形用户。
如果您运行的是Windows,并且您有高质量的OpenGL驱动程序,比如来自nVidia或AMD的相当新的驱动程序,您可以尝试禁用角度来查看它是否解决了您的问题。在Google上,这是通过编辑Chrome图标来添加--use-gl=desktop作为命令行参数(在图标的“目标”字段中)并重新启动浏览器来完成的。对于火狐,您可以访问about:config并在搜索框中键入webgl,然后查找webgl.prefer-native-gl并将其设置为true。
再次尝试您的着色器与角度禁用,编译时间可能会有所改善。请记住,这只是Windows问题,因此在其他平台上编辑这些设置没有任何效果,但我相信所有其他平台都直接使用本机OpenGL。
发布于 2016-10-21 05:39:33
遗憾的是,AMD可能不支持这一点,但我认为NVidia有一个不错的实用主义展开指令。对于有相反问题的人,您可以在GLSL中调用它为“#实用化optionNV (unroll all)”,但我认为以下内容将阻止展开。我引用DenisR 2008年在NVidia论坛上的文章的话
默认情况下,编译器使用已知的trip计数展开小循环。然而,# used unroll指令可以用来控制任何给定循环的展开。它必须紧接在循环之前,并且只适用于该循环。它可选地后面跟着一个数字,它指定必须展开循环多少次。 例如,在此代码示例中: #务实展开5用于(int i= 0;i< n;++i) 循环将展开5次。程序员应该确保展开不会影响程序的正确性(在上面的例子中,如果n小于5,它可能影响程序的正确性)。 #务实展开1 将防止编译器永远展开循环。 如果在#实用化展开后没有指定任何数字,则如果其trip计数为常数,则循环将完全展开,否则将根本不展开它。
所以我可以想象
#pragma optionNV (unroll 1)可能在GLSL (和WebGL?)中工作。(例如,StackOverflow问题选择-nvidia-实用主义-选择-全部似乎暗示这可能在GLSL中起作用,至少在某些平台下是这样。)
似乎有一种暗示,在最近几年,AMD可能支持展开的实用主义(虽然在GLSL中不支持),但我不熟悉,也没有尝试过:AMD OpenCL内核中的展开循环
(如果在Chrome/Firefox甚至其他场景中通过WebGL使用GLSL,请记住GLSL编译可以通过夹角进行管道传输
https://stackoverflow.com/questions/10334555
复制相似问题