【问题标题】:iOS: why does overriding drawRect resort to software rendering?iOS:为什么覆盖 drawRect 诉诸软件渲染?
【发布时间】:2014-06-10 19:51:26
【问题描述】:

我不是 iOS 图形 API 及其文档的忠实拥护者,并且已经尝试了一段时间来形成 高级视图 和渲染过程的结构,但只有零碎的信息.本质上,我试图理解(再次,高水平);

1) Coregraphics 和 CoreAnimation API 在从 CGContext 到前端帧缓冲区的渲染管道中的作用。

2) 在此过程中(这是文档中最令人困惑和最不详细的),哪些任务由 CPU 和 GPU 执行。

随着 Swift 和 Metal 的推出,我希望 API 能够被重新审视。

【问题讨论】:

  • 当您覆盖 drawRect: 时,它不会切换到软件渲染。您在实现中调用的所有绘图函数仍然使用您的图形硬件。但是,在某些类的设计中,一个方法并没有在基类中实现(我假设drawRect没有在UIView中实现)。当您的视图被绘制时,库代码可以检查您的类是否实现了该方法,如果没有,它可以跳过该步骤。这是一种技术含量低的优化。
  • 我一直不确定这部分,并假设基础视图对象(视图、控件等)不使用 drawRect 绘制自己,而是隐藏了一些优化。这些都是我能找到的;
  • “系统视图通常实现私有绘图方法来呈现它们的内容。” developer.apple.com/library/ios/documentation/windowsviews/… 所以我认为当它们绘制自己时必须有一些隐藏的优化,而不是覆盖强制软件绘制的 drawRect。跨度>

标签: ios opengl-es core-graphics core-animation gpu


【解决方案1】:

您是否开始使用WWDC videos?它们广泛地涵盖了许多细节。例如,今年的 iOS 应用程序高级图形和动画就是一个很好的起点。 Core Image 演讲通常也很有用(我今年还没有看过)。我强烈建议回到前几年。他们在前几年就 CPU/GPU 管道进行了精彩的讨论。 WWDC 2012 Core Image Techniques 非常有帮助。当然,学习有效地使用 Instruments 与理解实现同样重要。

Apple 通常不会在主文档中提供低级实现细节。实现细节不是接口承诺,Apple 会不时更改它们以提高大多数应用程序的性能。这有时会降低极端情况下的性能,这是您应该避免巧妙利用性能技巧的原因之一。

但是 WWDC 视频中包含您所描述的内容,并将引导您了解渲染管道以及如何对其进行优化。他们提出的建议在不同版本和不同设备之间往往非常稳定。

【讨论】:

【解决方案2】:

1) Coregraphics 和 CoreAnimation API 在从 CGContext 到前帧缓冲区的整个渲染管道中的作用。

Core Graphics 是一个绘图库,它实现了与 PDF 或 PostScript 相同的原语。所以你给它提供位图和各种类型的路径,它就会产生像素。

Core Animation 是一个合成器。它通过合成来自视频内存的缓冲区(称为图层)来生成屏幕显示。在合成时,它可以对每一层应用变换、移动、旋转、添加透视或做其他事情。它还有一个定时动画子系统,可以对变换的任何部分进行定时调整,而无需进一步的程序干预。

UIKit 连接起来,这样每当内容本身发生变化时,您就可以使用 CoreGraphics 将视图的内容绘制到图层上。这主要涉及CPU。对于动画和过渡之类的东西,您通常最终会应用或安排合成调整。所以这主要涉及 GPU。

2) 在此过程中(这是文档中最令人困惑和最不详细的),哪些任务由 CPU 和 GPU 执行。

单层绘制:CPU

转换和合成层以构建显示:GPU

iOS:为什么覆盖 drawRect 求助于软件渲染?

它不“求助于”任何东西。无论您编写相关的 drawRect: 还是 Apple 编写的,都会应用完全相同的管道。

随着 Swift 和 Metal 的推出,我希望 API 能够被重新审视。

Swift 和 Metal 与这个问题完全正交。 API 的格式非常好,并且备受推崇。你与他们的问题——正如你所承认的——缺乏理解。没有必要重新审视它们,Apple 也没有表示会这样做。

【讨论】:

  • 谢谢。如果我错了,请纠正我。 CG 使用 CPU 进行光栅化(屏幕外或屏幕上下文),随后的图层由 GPU 合成到后帧缓冲区中,在下一次扫描时交换并显示。所以在第一次绘制调用之后,这些图层被缓存(在iOS),除非它们被标记为脏(例如:setNeedsDisplay),否则不会再次调用drawRect,否则需要将缓存层发送回CPU进行重绘并上传回GPU进行缓存和合成?另外,如果我必须每秒重绘怎么办?
  • 没有理由假设双缓冲区,但另外一个观察结果是正确的:只有一个 RAM 芯片。这是一个共享内存架构。 CPU 可以直接绘制到纹理 RAM 中,如果 Core Graphics 不这样做,我会感到惊讶。您可以通过 Core Video / OpenGL 桥自行完成。每秒重绘一次绝对不是问题。您可能每秒重绘数千次。当然,这取决于您进行 Core Graphics 调用的复杂程度,但是例如当您输入文本时,它会光栅化、缓存并在每次输入时显示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-13
  • 2017-08-28
  • 2019-09-25
  • 2013-06-22
  • 2020-09-30
  • 2012-09-10
相关资源
最近更新 更多