当我读到这篇文章(来自OpenGL wiki)时,我感到很震惊:
glTranslate,glRotate,glScale
这些硬件加速了吗?
不,没有已知的GPU 执行此操作。司机计算 CPU上的矩阵并将其上传到 GPU。
所有其他矩阵运算都是 在CPU上完成: glPushMatrix,glPopMatrix, glLoadIdentity,glFrustum,glOrtho。
这就是为什么这些功能 在GL 3.0中被视为已弃用。 你应该有自己的数学库, 建立自己的矩阵,上传你的 着色器的矩阵。
对于非常非常的时间,我认为大多数OpenGL函数都使用GPU来进行计算。我不确定这是否是一种常见的误解,但经过一段时间的思考,这是有道理的。由于状态切换太多,旧的OpenGL函数(2.x及更早版本)实际上不适合实际应用程序。
这让我意识到,很多OpenGL函数可能根本不使用GPU。
所以,问题是:
哪些OpenGL函数调用不使用GPU?
我相信知道上述问题的答案将有助于我成为一名更好的OpenGL程序员。请分享一些您的见解。
修改
我知道这个问题很容易导致优化水平。这很好,但这不是这个问题的意图。
如果有人知道某个流行的实现(如AshleysBrain建议,nVidia / ATI,可能依赖于操作系统)不使用GPU的一组GL功能,那就是我所追求的!
合理的优化指南稍后会出现。让我们关注这个主题的功能。
EDIT2:
答案 0 :(得分:36)
男孩,这是一个很大的主题。
首先,我将从显而易见的开始:因为你从CPU调用函数(任何函数),它必须至少部分地在CPU上运行。所以真正的问题是,在CPU上完成了多少工作以及在GPU上完成了多少工作。
其次,为了让GPU能够执行某些命令,CPU必须准备一个命令描述来传递。这里的最小集合是一个描述要做什么的命令令牌,以及要执行的操作的数据。 CPU如何触发GPU执行命令也很重要。由于大多数情况下,这是昂贵的,CPU不经常这样做,而是在命令缓冲区中批处理命令,并简单地发送整个缓冲区供GPU处理。
所有这一切都表明将工作传递给GPU并不是一项自由练习。这个成本必须与仅在CPU上运行该功能相对应(无论我们在谈论什么)。
退一步,你必须问自己为什么你需要一个GPU。事实是,纯粹的CPU实现完成了这项工作(正如AshleysBrain所提到的)。 GPU的强大功能来自于它的设计:
这些是为了决定筹码中的内容而遵循的指导原则。任何可以从中受益的东西都应该在GPU上运行。其他任何东西都应该在CPU上。
顺便说一下,这很有意思。 GL的一些功能(主要是在弃用之前)实际上没有明确描述。显示列表可能是此类功能的最佳示例。每个驱动程序都可以自由地从显示列表流推送到GPU(通常以某种命令缓冲区形式),以便以后执行,只要保留GL显示列表的语义(并且有点硬一般)。因此,某些实现只选择将显示列表中有限的调用子集推送到计算格式,并选择简单地重放CPU上的其余命令流。选择是另一个不清楚在GPU上执行是否有价值的选择。
最后,我不得不说,一般来说,API调用与CPU或GPU上的工作量之间几乎没有关联。状态设置API倾向于仅修改驱动程序数据中某处的结构。它的效果只有在调用Draw或其他类似的东西时才可见。
很多GL API都是这样的。此时,询问是否在CPU或GPU上执行glEnable(GL_BLEND)
是没有意义的。重要的是调用Draw时是否会在GPU上进行混合。因此,从这个意义上说,大多数 GL入口点都没有加速。
我还可以扩展数据传输,但Danvil触及了它。
我将完成小“s / w路径”。从历史上看,无论硬件特殊情况如何,GL都必须遵守规范。这意味着如果h / w没有处理特定的GL功能,那么它必须模拟它,或者在软件中完全实现它。有很多这样的情况,但很多人都遇到过GLSL开始出现的情况。
由于没有实际的方法来估计GLSL着色器的代码大小,因此决定GL应该将任何着色器长度视为有效。其含义相当明确:要么实现可以采用任意长度着色器的h / w - 当时不现实,要么实现s / w着色器仿真(或者,正如某些供应商选择的那样,根本无法兼容)。因此,如果你在片段着色器上触发了这个条件,那么你的GL的整个最终可能会在CPU上执行,即使你有一个GPU选址空闲,至少对于那个抽奖。 / p>
答案 1 :(得分:7)
问题应该是“哪些功能会占用大量的CPU时间?”
保持投影和视图的矩阵堆栈并不是GPU能够比CPU更好地处理的事情(相反......)。另一个例子是着色器编译。为什么要在GPU上运行?有一个解析器,一个编译器......,它们只是普通的CPU程序,比如C ++编译器。
潜在的“危险”函数调用例如glReadPixels
,因为数据可以通过有限总线从主机(= CPU)内存复制到设备(= GPU)内存。此类别中的功能还包括glTexImage_D
或glBufferData
。
一般来说,如果您想知道OpenGL调用的CPU时间,请尝试了解其功能。并注意所有功能,将数据从主机复制到设备并返回!
答案 2 :(得分:7)
通常情况下,如果操作是per-something,它将在GPU上发生。一个例子是实际转换 - 每个顶点执行一次。另一方面,如果每次大型操作只发生一次,它将在CPU上 - 例如创建变换矩阵,每次对象的状态改变时只执行一次,或每帧一次。
这只是一般性答案,而某些功能将以相反的方式发生 - 以及依赖于实现。但是,通常情况下,程序员对您来说无关紧要。只要你允许GPU有足够的时间来完成游戏模拟或其他任何工作,或者拥有可靠的线程模型,你就不必担心它。
将数据发送到GPU:据我所知(仅使用Direct3D),它都是在着色器中完成的,这就是着色器的用途。
答案 3 :(得分:4)
glTranslate,glRotate和glScale更改当前活动的转换矩阵。这当然是CPU操作。模型视图和投影矩阵仅描述GPU在发出渲染命令时应如何转换顶点。
所以,例如通过调用glTranslate,还没有翻译。在渲染当前投影和模型视图之前,矩阵被乘以(MVP =投影*模型视图),然后将该单个矩阵复制到GPU,然后GPU为每个顶点执行矩阵*顶点乘法(“T& L”)。因此,顶点的平移/缩放/投影是由GPU完成的。
如果你不在某个内部循环中使用这些函数,你真的不应该担心性能。 glTranslate导致三个添加。 glScale和glRotate有点复杂。
我的建议是你应该学习更多关于线性代数的知识。这对于使用3D API至关重要。
答案 4 :(得分:2)
有OpenGL的软件渲染实现,因此有可能在GPU上运行 no OpenGL函数。还有硬件不支持硬件中的某些渲染状态,因此如果设置某个状态,切换到软件渲染,再次,GPU上不会运行任何东西(即使那里有一个)。因此,我认为“GPU加速功能”和“非GPU加速功能”之间没有明显的区别。
为了安全起见,尽量保持简单。直接渲染顶点和Z缓冲等基本功能很可能是硬件加速的,所以如果你坚持使用最小状态变化,你最有可能保留东西硬件加速。这也是最大化硬件加速渲染性能的方法 - 图形卡喜欢保持一个状态而只是处理一堆顶点。