GLSL:为什么const int数组比普通数组慢很多?

14

我有一个使用GLSL编写的OpenGL着色器。在头部顶部,我有一个全局定义的数组:

const int permutations[256] = int[256](
    64 ,  34 ,  36 , 137 , 120 , 122 , 246 ,  46 ,  79 ,  10 ,  37 , 181,
    ...
    );

当我启动程序时,使用着色器显示一个简单的茶壶时,它非常缓慢,即我每秒只有1帧。

然而,一旦我从以上声明中删除“const”,一切都正常了,我又可以交互式地控制帧率了。

所以,“问题”实际上已经解决了...但是我想知道,为什么会出现这种情况?这非常反直觉,在我的经验中,使用const通常可以使程序更快。


更新

我实际上尝试先使用Uniform而不是const int数组,在其他地方完全相同的代码。但是,在这种情况下,编译着色器会崩溃:

Internal error: assembly compile error for fragment shader at offset
34609:
-- error message -- line 651, column 22:  error: invalid local parameter number

1
我想知道的是,为什么你最终要将这么长的数组放入着色器源代码中。这听起来像是一个数组统一变量的工作。 - datenwolf
@datenwolf:这是有争议的。如果它是const,那么它就是const,把它放到外部缓冲区中没有意义(如果更高效,则GL应在内部处理它作为统一数组)。Jan:你的问题可能与IHV和驱动程序有关。你尝试在不同的硬件上运行它了吗(最好是不同的供应商)? - Bahbar
3
听起来有点像驱动程序切换到软件仿真,因为一个 const int 数组不能那么大。这只是一个猜测,但 1 FPS 真的很慢。也许当它不是 const 时,它使用类似于 uniform 数组的东西,而如果它是 const,则尝试将其放入一些本地寄存器中,但它无法适应。 - Christian Rau
看到了我为什么没有使用uniform的更新……实际上,驱动似乎真的有点buggy。我在linux上使用nvidia显卡和官方驱动程序,但是由于缺少一些扩展,我无法在其他(intel)卡上进行测试。 - Jan Rüegg
如果数组uniform速度慢或无法使用,请尝试使用1D纹理(在将值传递到着色器之前将其缩放为[0..1])。 - appas
那个装配错误看起来像是我在某些旧版Nvidia驱动程序上见过的一个已知问题--你可能可以通过升级到新版本的驱动程序来解决它(以及你所看到的减速问题)。 - Chris Dodd
1个回答

2
这很奇怪。很可能是驱动程序问题。我在Windows下的Nvidia 540M上运行了包含的着色器代码,并让它在循环中运行。在这个循环中,我调用了着色器程序一次,并测量了时间(同时我还通过变换反馈检查了着色器是否正常工作)。大多数循环在2-3毫秒内结束,有些峰值达到25毫秒。然而,删除const标识符对性能没有影响。虽然这些值很小,但从您的描述中,即使在这里也应该观察到const的性能损失。
#version 150
const int permutations[256] = int[256](
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
...
246, 247, 248, 249, 250, 251, 252, 253, 254, 255
);

flat out int num1[32];

void main(){
    for(int i = 0; i < 32; i++){
        num1[i] = (permutations[2*i]+permutations[2*i+1])*(permutations[2*i+2]+permutations[2*i+3]);
    }
}

也许您不介意的话,我可以在我的硬件上尝试运行您的程序,但它必须编译为Windows版本,并请包含所有动态库。

毕竟可能是驱动程序问题。无论如何,我现在已经完成了这个项目,也不再重要了。我只是想知道为什么会发生这样的事情。但还是感谢你的帮助! - Jan Rüegg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接