GLSL是否真的使用统一(非每顶点)值进行不必要的计算?

时间:2013-03-17 14:44:04

标签: opengl optimization glsl compiler-optimization

例如,如果我使用如下的顶点着色器:

#version 400 core

uniform mat4 projM;
uniform mat4 viewM;
uniform mat4 modelM;

in vec4 in_Position;

out vec4 pass_position_model;

void main(void) {
    gl_Position = projM * viewM * modelM * in_Position;
    pass_position_model = modelM * in_Position;
}

它是否会为每个顶点进行projM * viewM * modelM矩阵乘法,或者它是否足够智能计算是否一次并且在重新计算统一变量之前不重新计算? 如果它不足够智能",那么除了计算CPU上所有与统一相关的值并将它们作为统一变量发送到GPU之外,还有其他优化方法吗? 此外,我对可以在没有问题的情况下移植到OpenGL ES 2.0的解决方案感兴趣。

4 个答案:

答案 0 :(得分:10)

据我所知,没有一般答案。不过,我对我的硬件进行了一些测试。我的广告资源中有2个GPU,Intel HD Graphics 3000NVidia GeForce GT 555M。我在顶点着色器中使用矩阵乘法测试了我的程序(程序本身是用java / scala编写的),然后将乘法移动到CPU程序并再次测试。

(sphereN - 它是一个连续旋转的球体,有2 * N ^ 2个四边形,用glDrawElements(GL_QUADS,...)绘制,带有1个纹理,没有任何光照/其他效果)

顶点着色器中的矩阵乘法:

intel:
    sphere400: 57.17552887364208 fps
    sphere40: 128.1394156842645 fps
nvidia:
    sphere400: 134.9527665317139 fps
    sphere40: 242.0135527589545 fps

cpu上的矩阵乘法:

intel:
    sphere400: 57.37234652897303 fps
    sphere40: 128.2051282051282 fps
nvidia:
    sphere400: 142.28799089356858 fps
    sphere40: 247.1576866040534 fps

测试表明,在顶点着色器中乘法(均匀)矩阵是个坏主意,至少在这个硬件上是这样。所以一般情况下,可能不依赖于相应的GLSL编译器优化。

答案 1 :(得分:3)

  

它是否会为每个顶点执行projM * viewM * modelM矩阵乘法,或者它是否足够聪明以计算是否一次并且在重新计算统一变量之前不重新计算?

向开发人员询问有问题的OpenGL实现。 OpenGL规范对此无话可说,但驱动程序和GLSL编译器编写者可能已经为此实现了优化。

  

如果它不够“足够智能”,那么有没有办法优化它 其他 ,而不是计算CPU上所有与统一相关的值并将它们作为统一发送变量到GPU?

没有。你必须自己做腿部工作。

答案 2 :(得分:1)

所有OpenGL和GLSL优化都是特定于供应商的。很难说glsl编译器的最终输出是什么。

您可以在此处查看供应商特定信息: http://renderingpipeline.com/graphics-literature/low-level-gpu-documentation/

对于您的代码,您始终可以打包'将矩阵转换为新的统一:matModelViewProjection,将其乘以应用程序并将其发送到顶点着色器。

答案 3 :(得分:0)

这完全取决于司机。 OpenGL是一个规范,如果你付钱给他们的权利,他们会给你一个样本的使用,但就是这样。

除此之外,您需要考虑矩阵乘法限制,执行projM * viewM * modelM * vertex与执行vertex * projM * viewM * modelM不同。那是因为矩阵从右到左相乘,顺序对此很重要。因此,着色器无法预先计算projM * viewM * modelM以在顶点之间共享,因为这会给您带来伪造的结果。