【问题标题】:How does glClear() improve performance?glClear() 如何提高性能?
【发布时间】:2025-12-25 08:30:06
【问题描述】:

Apple's Technical Q&A on addressing flickering (QA1650) 包括以下段落。 (强调我的。)

您必须为屏幕上的每个像素提供一种颜色。在绘图代码的开头,最好使用 glClear() 来初始化颜色缓冲区。在帧开始时全屏清除每个颜色、深度和模板缓冲区(如果您正在使用它们)通常也可以提高您的应用程序的性能。

在其他平台上,我一直发现它是一种优化,如果您要绘制到每个像素,清除颜色缓冲区。 (如果您只是要覆盖清晰的颜色,为什么要浪费时间填充颜色缓冲区?)

调用 glClear() 如何提高性能?

【问题讨论】:

  • 多年来,忽略清除颜色/深度/模板缓冲区的性能优化并非如此。正如我在其他答案中的一些 cmets 中所解释的,它与现代 GPU 中的缓冲区压缩有关。通过现代 GPU,我可以追溯到 Radeon 9xxx 系列。清除这些缓冲区实际上是对几乎所有 GPU 架构的性能提升。

标签: iphone opengl-es


【解决方案1】:

这很可能与基于图块的渲染有关,它将整个视口划分为图块(较小的窗口,通常大小为 32x32),这些图块保存在更快的内存中。这个较小的内存和实际帧缓冲区之间的复制操作可能需要一些时间(内存操作比算术操作慢很多)。通过发出 glClear 命令,您是在告诉硬件您不需要以前的缓冲区内容,因此它不需要将颜色/深度/任何内容从帧缓冲区复制到较小的图块内存。

【讨论】:

  • 如果您需要更多详细信息,请查看以下参考资料: - developer.amd.com/gpu_assets/… - beyond3d.com/content/articles/38
  • 它也与颜色/深度/模板压缩有关。简而言之,通过适当的方式清除缓冲区将使每个图块(这也适用于常规 GPU,而不仅仅是 PowerVR 中的基于图块的延迟渲染)更容易压缩并提高吞吐量。压缩这些缓冲区不是为了节省存储空间,而是为了减少必须传输的数据量。清除瓦片是在每个瓦片中设置几个位的小事,一旦完成,清除瓦片从内存中获取非常便宜。
【解决方案2】:

从官方 cmet 在 iOS 4 上的长远观点来看,这比接受的答案晚...

我认为应该与 Apple 的 cmets 一起阅读关于 GL_EXT_discard_framebuffer 扩展名的内容,如果可能(实际上在其他地方),应该始终在帧的末尾使用它。当您丢弃帧缓冲区时,会将其内容置于未定义状态。这样做的好处是,当你下次绑定其他帧缓冲区时,永远不需要将缓冲区的当前内容存储到某个地方,同样,当你下次恢复缓冲区时,也不需要检索它们。这些都应该是 GPU 内存副本,因此非常便宜,但它们远非免费,而且 iPhone 的共享内存架构可能意味着可能会出现更复杂的考虑。

基于 iOS 的合成模型,可以合理地假设即使您的应用没有在其上下文中绑定和取消绑定帧缓冲区,GPU 也必须为您的每个帧隐式地执行这些任务至少一次。

我敢猜测驱动程序足够聪明,如果你做的第一件事是清除,你可以在没有实际使用的情况下获得丢弃扩展的一半好处。

【讨论】:

    【解决方案3】:

    尝试在传递给 ChooseConfig 的 glSurface 属性中减小帧缓冲区的大小。

    例如,将属性设置为 0 为最小值或完全忽略它们以使用默认值,除非您有特定要求。

    【讨论】:

      【解决方案4】:

      我可以肯定地确认您必须为屏幕上的每个像素提供一种颜色

      我已经在基于 XCode 的 iPhone OpenGL 模板构建的基本测试应用程序中验证了这一点:

      [context presentRenderbuffer:GL_RENDERBUFFER];  
      glClear( GL_COLOR_BUFFER_BIT );
      

      如果我省略了 glClear 行(或在循环中进一步向下移动,在其他一些 OpenGL 调用之后),线程(通过 CADisplayLink 运行)几乎不会再获得任何更新。似乎 CPU/GPU 同步出了问题,线程被阻塞了。 如果你问我,这很可怕,完全不符合我的期望。

      顺便说一句,您不一定非要使用 glClear(),只是绘制一个全屏四边形似乎也有相同的效果(显然,带纹理的四边形更昂贵)。看来您只需要使所有图块无效。

      【讨论】:

      • -1:您应该使用glClear (...),现代 GPU 使用颜色缓冲、深度缓冲和模板缓冲压缩。清除缓冲区非常便宜,因为这些缓冲区通常是分层平铺的,清除缓冲区的过程相当于翻转每个平铺中的一个或两个位。如果您定期清除缓冲区,它甚至有助于许多早期片段测试和一般帧缓冲区吞吐量。在基于 Tile 的延迟渲染 GPU(例如 PowerVR SGX - 所有 iOS 设备)上,出于类似原因,它同样重要。