为什么抽奖电话很贵?

时间:2011-01-31 17:16:09

标签: performance optimization graphics 3d gpu

假设纹理,顶点和着色器数据已经在显卡上,您不需要向卡发送大量数据。有几个字节可以识别数据,可能是4x4矩阵,还有一些其他参数。

那么所有的开销都来自哪里?操作是否需要与gpu进行某种握手?

为什么发送一个包含一堆小模型的网格,在CPU上计算,通常比发送顶点id和转换矩阵更快? (第二个选项看起来应该发送的数据更少,除非模型小于4x4矩阵)

3 个答案:

答案 0 :(得分:55)

首先,我假设使用“绘制调用”,这意味着命令告诉GPU将某组顶点渲染为具有特定状态的三角形(着色器,混合状态等)。 / p>

绘制电话不一定很贵。在早期版本的Direct3D中,许多调用需要上下文切换,这很昂贵,但在较新版本中并非如此。

减少绘制调用的主要原因是图形硬件可以比提交三角形更快地变换和渲染三角形。如果每次调用都提交几个三角形,则完全受限于CPU和GPU将大部分空闲。 CPU将无法足够快地提供GPU。

使用两个三角形进行单次绘制调用很便宜,但如果每次调用提交的数据太少,则没有足够的CPU时间来向GPU提交尽可能多的几何体。

制作绘图调用有一些实际成本,它需要设置一堆状态(要使用哪组顶点,使用什么着色器等等),并且状态更改在硬件方面都有成本(更新一堆寄存器)和驱动程序端(验证和转换设置状态的调用)。

绘制调用的主要成本仅适用于每个调用提交的数据太少,因为这会导致您受CPU限制,并阻止您完全使用硬件。

就像Josh所说,绘制调用也可以导致命令缓冲区被刷新,但根据我的经验,这通常发生在调用SwapBuffers时,而不是在提交几何体时。视频驱动程序通常会尝试尽可能多地缓冲(有时是几帧!)以尽可能多地挤出GPU的并行性。

你应该阅读nVidia演示文稿Batch Batch Batch!,它已经相当陈旧但完全涵盖了这个主题。

答案 1 :(得分:12)

Direct3D等图形API将其API级别的调用转换为与设备无关的命令,并将它们排入缓冲区。刷新该缓冲区以执行实际工作是非常昂贵的 - 因为它意味着现在正在执行实际工作,并且因为它可能导致芯片上的用户切换到内核模式(并且再次返回),这不是便宜。

在刷新缓冲区之前,只要CPU没有发出阻塞请求(例如将数据映射回CPU),GPU就能够与CPU并行完成一些准备工作。但GPU不会 - 也不能 - 准备好所有东西,直到它需要实际绘制。仅仅因为卡上的某些顶点或纹理数据并不意味着它已经被适当地排列,并且在设置顶点布局或绑定着色器之后可能无法排列等等。大部分实际工作发生在命令刷新和绘制调用期间。

DirectX SDK有一个section on accurately profiling D3D performance,虽然与您的问题没有直接关系,但可以提供一些关于什么是昂贵和(在某些情况下)原因的提示。

更相关的是this blog post(以及后续帖子herehere),它们可以很好地概述GPU的逻辑低级操作流程。< / p>

但是,基本上(尝试直接回答你的问题),调用费用昂贵的原因并不是必然要传输大量数据,而是存在大量数据工作主体超越只是在整个总线上传输数据,这些数据会被延迟,直到命令缓冲区被刷新为止。

答案 2 :(得分:2)

简答:驱动程序缓冲部分或全部实际工作,直到您调用draw。这将显示为在绘制调用中花费的相对可预测的时间量,具体取决于状态的变化。

这样做有几个原因:

  • 避免做不必要的工作:如果您(不必要地)在绘制之前多次设置相同的状态,则可以避免每次发生这种情况时都要做昂贵的工作。这实际上在大型代码库中变得相当普遍,例如生产游戏引擎。
  • 能够协调内部相互依赖的状态,而不是立即用不完整的信息处理它们

替代答案:

  • 驱动程序用于存储渲染命令的缓冲区已满,应用程序正在等待GPU处理某些早期工作。这通常会在帧内的随机绘制调用中显示为非常大的时间阻塞块。
  • 已达到允许驱动程序缓冲的帧数,并且应用程序正在等待GPU处理其中一个。这通常会在一帧中的第一个绘制调用中显示为大块时间阻塞,或者在前一帧结束时显示为Present。