Matrix 是否应在CPU上预乘(顶点着色器,mat4)均匀矩阵?

Matrix 是否应在CPU上预乘(顶点着色器,mat4)均匀矩阵?,matrix,glsl,vertex-shader,Matrix,Glsl,Vertex Shader,考虑典型的“朴素”顶点着色器: in vec3 aPos; uniform mat4 uMatCam; uniform mat4 uMatModelView; uniform mat4 uMatProj; void main () { gl_Position = uMatProj * uMatCam * uMatModelView * vec4(aPos, 1.0); } 当然,传统智慧会建议“每个顶点有三个Mat4相乘,其中两个即使在当前着色器程序中的多个后续glDrawX()调

考虑典型的“朴素”顶点着色器:

in vec3 aPos;

uniform mat4 uMatCam;
uniform mat4 uMatModelView;
uniform mat4 uMatProj;

void main () {
    gl_Position = uMatProj * uMatCam * uMatModelView * vec4(aPos, 1.0);
}
当然,传统智慧会建议“每个顶点有三个Mat4相乘,其中两个即使在当前着色器程序中的多个后续glDrawX()调用中也是一致的,至少这两个应该在CPU端预先相乘,甚至可能是所有三个。”

我想知道现代的GPU是否已经将这个用例优化到CPU端预乘不再是性能优势的程度。当然,纯粹主义者可能会说“这取决于最终用户的OpenGL实现”,但对于这个用例,我们可以放心地假设它将是当前一代支持OpenGL 4.2的nVidia或ATI驱动程序,提供该实现

根据您的经验,考虑到我们可能会在每个UseProgram()过程中“绘制”一百万个左右的顶点——将每个UseProgram()的前两个顶点(透视投影和摄影机变换矩阵)预乘是否会将性能提升到任何显著程度?每个Draw()调用三个函数怎么样

当然,这都是关于基准测试。。。但我希望有人有一些基本的、基于当前一代硬件实现的见解,我错过了这些见解,这些见解可能会建议“不值得一试,不要浪费时间”或“尽一切努力,因为当前没有预乘法的着色器将是完全疯狂的”。。。想法

我想知道现代的GPU是否已经将这个用例优化到CPU端预乘不再是性能优势的程度

GPU在并行操作中工作得最好。“GPU”可以优化三个连续向量/矩阵乘法的唯一方法是,如果着色器编译器检测到它们是一致的,并且在发出绘制调用时在某个位置执行乘法,并将结果传递给着色器

因此,无论哪种情况,3个矩阵的倍数在着色器中都变为1。你可以自己做,也可以不做。驱动程序可以实现这种优化,也可以不实现。下面是一张可能性图:

            | GPU optimizes  | GPU doesn't optimize
------------|----------------|---------------------
You send 3  |   Case A       |        Case B
matrices    |                |
---------------------------------------------------
You multiply|   Case C       |        Case D
on the CPU  |                |
------------|----------------|---------------------
在案例A中,您获得了比代码所建议的更好的性能。在案例B中,您不会获得更好的性能

案例C和案例D都能保证为您提供与案例A相同的性能

问题不在于驱动程序是否会实现这种优化。问题是,“那场演出对你来说值多少钱?”如果你想要那场演出,那你就应该自己去做;这是可靠实现该性能的唯一方法。如果你不在乎表演。。。这有什么关系

简言之,如果您关心此优化,请自己进行

根据您的经验,考虑到我们可能会在每个UseProgram()过程中“绘制”一百万个左右的顶点——将每个UseProgram()的前两个顶点(透视投影和摄影机变换矩阵)预乘是否会显著提高性能?每个Draw()调用三个函数怎么样

有可能;可能不会。这完全取决于顶点变换如何制约渲染系统。如果不在实际渲染环境中进行测试,就无法知道

此外,将投影矩阵和摄影机矩阵结合起来并不是最好的主意,因为这意味着在世界空间而不是摄影机空间中进行照明。这也使得延迟渲染变得更加困难,因为您没有一个纯粹的投影矩阵来提取值