男孩,这是一个很大的话题。
首先,我将从显而易见的开始:由于您从 CPU 调用函数(任何函数),它必须至少部分在 CPU 上运行。所以真正的问题是,有多少工作是在 CPU 上完成的,有多少是在 GPU 上完成的。
其次,为了让GPU能够执行一些命令,CPU必须准备一个命令描述来传递。这里的最小集合是一个命令令牌,描述要做什么,以及要执行的操作的数据。CPU 如何触发 GPU 执行命令也有些重要。由于大多数时候,这很昂贵,CPU 并不经常这样做,而是将命令批处理到命令缓冲区中,并简单地将整个缓冲区发送给 GPU 处理。
所有这一切都表明,将工作传递给 GPU 并不是一项自由活动。该成本必须与仅在 CPU 上运行该功能相提并论(无论我们在谈论什么)。
退后一步,你必须问问自己为什么需要 GPU。事实是,纯 CPU 实现可以完成这项工作(正如 AshleysBrain 提到的)。GPU 的强大之处在于它的设计可以处理:
- 专门的任务(光栅化、混合、纹理过滤、blitting ......)
- 高度并行的工作负载(DeadMG 在他的回答中指出了这一点),当 CPU 更多地设计为处理单线程工作时。
这些是决定芯片内容的指导原则。任何可以从中受益的东西都应该在 GPU 上运行。其他任何东西都应该在 CPU 上。
顺便说一句,这很有趣。GL 的某些功能(主要是在弃用之前)实际上并没有明确描述。显示列表可能是此类功能的最佳示例。只要保留 GL 显示列表的语义(这在一般的)。所以一些实现只选择将显示列表中有限的调用子集推送到计算格式,并选择简单地在 CPU 上重放命令流的其余部分。
选择是另一个不清楚在 GPU 上执行是否有价值的问题。
最后,我不得不说,API 调用与 CPU 或 GPU 上的工作量之间几乎没有相关性。状态设置 API 倾向于只修改驱动程序数据中某处的结构。它的效果只有在调用 Draw 或类似的东西时才可见。
很多 GL API 都是这样工作的。到那时,询问glEnable(GL_BLEND)是在 CPU 还是 GPU 上执行是没有意义的。重要的是调用 Draw 时是否会在 GPU 上进行混合。因此,从这个意义上说,大多数GL 入口点根本没有加速。
我还可以稍微扩展一下数据传输,但 Danvil 谈到了它。
我将以小“软件路径”结束。从历史上看,无论硬件特殊情况是什么,GL 都必须努力规范。这意味着如果硬件没有处理特定的 GL 功能,那么它必须模拟它,或者在软件中完全实现它。这种情况有很多,但让很多人印象深刻的是GLSL开始出现的时候。
由于没有实用的方法来估计 GLSL 着色器的代码大小,因此决定 GL 应该将任何着色器长度视为有效。含义很明确:要么实现可以采用任意长度着色器的 h/w(当时不现实),要么实现 as/w 着色器仿真(或者,正如一些供应商选择的那样,根本不符合要求)。所以,如果你在片段着色器上触发了这个条件,你的整个GL 很可能最终都在 CPU 上执行,即使你有一个空闲的 GPU,至少对于那个绘图来说。