考虑典型的“天真”顶点着色器:
in vec3 aPos;
uniform mat4 uMatCam;
uniform mat4 uMatModelView;
uniform mat4 uMatProj;
void main () {
gl_Position = uMatProj * uMatCam * uMatModelView * vec4(aPos, 1.0);
}
当然,传统观点认为“每个顶点有三个mat4s,其中两个在当前着色器程序中的多个后续glDrawX()调用中是均匀的,至少这两个应该是预乘的CPU-一边,甚至可能都是三个。“
我想知道现代GPU是否已经优化了这个用例,其CPU端面预乘不再是性能优势。当然,纯粹主义者可能会说“这取决于最终用户的OpenGL实现”,但对于这个用例,我们可以安全地假设它将是当前一代支持OpenGL 4.2的nVidia或ATI驱动程序,提供该实现。
根据您的经验,考虑到每个UseProgram()传递可能“绘制”一百万左右的顶点 - 每个UseProgram()boost会预先乘以前两个(透视投影和相机变换矩阵)表现为任何重要度?那么每个Draw()调用三个呢?
当然,这都是关于基准测试......但是我希望有人有基本的,当前基于硬件实现的见解我错过了可能暗示“甚至不值得一试,不要浪费你的时间“或”一定要做到这一点,因为没有预先乘法的当前着色器将是纯粹的疯狂“ ......思想?
答案 0 :(得分:3)
我想知道现代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()boost会预先乘以前两个(透视投影和相机变换矩阵)表现到任何重要程度?那么每个Draw()调用三个呢?
可能;它可能不会。这完全取决于顶点变换如何瓶颈你的渲染系统。没有在实际渲染环境中进行测试就无法知道。
此外,组合投影和相机矩阵并不是最好的主意,因为这意味着在世界空间而不是相机空间进行照明。它还使延迟渲染变得更加困难,因为你没有纯粹的投影矩阵来拉出值。