glUseProgram()如何在硬件级别工作?

nil*_*pin 2 opengl

  1. 我想(我不确定),每当我们调用glUseProgram()时,顶点着色器,frag着色器,几何着色器等都被加载到GPU中相应类型处理器的程序存储器中(例如顶点着色器 - >顶点着色器处理器) .
    但我也发现这种"装载"发生的速度令人惊讶.尽管拥有复杂的渲染管道和多个着色器,但游戏通常能够提供非常好的FPS(1),这意味着程序加载可能每秒发生数千次.
    我是否正确地思考这是如何运作的?如果是的话,我真的低估了GPU的功能吗?
  2. (与(1)相关的迷你问题)在哪里可以找到有关内部GPU总线带宽与性能(或FPS)之间相关性的更多信息?
  3. 另一个迷你问题)是在客户端还是在设备上编译着色器?
  4. 后编译,是存储在GPU(共享)内存中的着色器程序,还是大到足以容纳许多着色器的处理器缓存?

Bar*_*icz 6

加载到GPU中相应类型处理器的程序存储器中

我很确定已编译的着色器与着色单元保持"足够接近",以使加载本身非常有效.指令缓存包含必要的数据,并且很容易用VRAM中的数据重写它们.毕竟,不需要CPU同步,一切都完全在GPU内完成.

这里要注意的一件重要事情是,现代GPU不再具有"相应类型处理器"; 它们实际上只使用可以运行各种计算的通用着色单元,包括但不限于片段和顶点着色.

尽管拥有复杂的渲染管道和多个着色器,但游戏通常能够提供非常好的FPS(1),这意味着程序加载可能每秒发生数千次.

是的,现代游戏可以有数千个管道设置来绘制框架.GPU的快.现代OpenGL使得更多程序更容易使用Separate Shader Objects扩展,这有助于使渲染更加模块化.

  1. (与(1)相关的迷你问题)在哪里可以找到有关内部GPU总线带宽与性能(或FPS)之间相关性的更多信息?

这太宽泛了,无法回答并严重依赖于工作量.不过,这是一份有趣的文件,可能会对您的问题有所启发,并可能激励您进一步研究.

总而言之,glUseProgram它本身通常会在现代驱动程序上做任何事情(就性能而言).这是因为驱动程序使用一种惰性求值形式,并且只有在确定drawcall将使用它们时才实际提交状态更改.现在,驱动程序在优化不必要的调用,重新排序等方面的效率完全取决于实现.

  1. 着色器是在客户端还是在设备上编译的?

它们以OpenGL的术语在服务器上编译,但这并不一定意味着物理设备.通常,它是执行着色器编译的驱动程序的OS驻留部分.

  1. 后编译,是存储在GPU(共享)内存中的着色器程序,还是大到足以容纳许多着色器的处理器缓存?

都.程序存储在全局存储器中,如果可能,存储在每个处理器的指令缓存中,这是几千字节.这取决于着色器的大小和缓存的大小,但通常应该适合几个.缓存在运行时以LRU方式填充.