【问题标题】:If Core Graphics uses Metal under the hood, can a Metal implementation run faster than a CG one? Why?如果 Core Graphics 在后台使用 Metal,Metal 实现能比 CG 运行得更快吗?为什么?
【发布时间】:2019-02-07 08:12:27
【问题描述】:

假设我想开发一个画图应用并需要实现一个画笔引擎。对于光栅画笔,您基本上需要在具有给定间距的触摸位置上标记纹理。

-- 任务:将小图像(画笔笔尖)合成到大图像上。

我决定首先在 CG 中构建一个原型,使用 CGContext 来渲染图章,结果发现即使在合并触摸和合适大小的画布(CGContext 输出大小)的情况下,它的性能也相当不错。

但是,由于我需要在非常大的纹理上绘画(8000x6000 会很棒),所以我决定给金属一个机会。我知道这个任务对于有金属背景的人来说可能是微不足道的,但我是这个领域的新手。因此,我尝试使用 CIFilters(Metal backed)在画布上合成画笔并将其显示在自定义 MetalImageView:GTKView 中。

我认为将画布和画笔作为 CIImages 并在金属层中显示它们已经比简单的 CG 实现更高效。但事实并非如此。 CIFilter 方法渲染整个画布的每个印章(在:点),无论在 CG 中我只是在该点周围刷新一个小矩形。

现在,如果我可以更改计算的范围,我想我可以使用 CIFilter 完成此操作。我不知道 Core Image 是否可以做到这一点,但我敢肯定,对于有经验的人来说,使用金属真的很容易。

-- 问题:考虑到 CG 在引擎盖下运行 Metal,纯金属实现能否比 CG 更快地冲压图像?如果是这样,多快?是否值得学习如何去做,还是我应该更好地花时间改进 CG 实现?

请注意,我要求的是光栅画笔,而不是带有 Bezier 路径的矢量画笔,它更容易编码并且运行速度更快,但不能使用纹理画笔。

非常感谢任何帮助。

【问题讨论】:

  • CoreImage 不是 Metal,您描述的实现完全取决于核心图像过滤器的实现方式。 Metal 是一个低级的绘图 API,我可以告诉你它比其他方法快得多。但是,您是在将苹果与橙子进行比较。
  • 感谢您的回复。核心图像过滤器是用金属着色语言编写的核心图像内核的包装器。如果我错了,请纠正我,但是在 Metal 中编写自定义 CIKernel 并从子类 CIFilter 调用它,获取生成的 CIImage,然后使用 CIContext 渲染到子类 MTKView 不被视为“Metal”?
  • 是的,CoreImage API 与 Metal 不同。区别很容易看出,因为您可以在 Metal 中实现低级方法,并且即使是巨大的缓冲区也能正常工作。但是,在 CoreImage 之上实施相同的方法,您可能会看到大量的性能问题。这是一个示例,它在您描述的 Metal 类型的调用之上显示了确切 CoreImage 的源代码,并且性能很糟糕。 stackoverflow.com/questions/54431826/…
  • 当然,“直接”Metal 方法应该更快,但我认为与同样基于 Metal 并在 GPU 上工作的其他 API 不会有很大的不同。我必须同意你的观点,如果我想要获得最佳性能,无论如何我都应该使用最好的工具来完成这项工作。我想是时候正确地学习金属了。你能为我的任务指出任何相关的金属教程吗?我见过他们中的大多数人试图用 3D 完成事情。我只想将空白画布或图像加载到 MTLTexture 上,并在其上标记另一个纹理。谢谢!!

标签: performance core-graphics metal


【解决方案1】:

实际上有一个chapter in the Core Image Programming Guide 关于那个。他们使用CIImageAccumulator 类将连续绘制到相同的纹理中。您也可以下载sample app

我认为在性能方面应该不会有太大差异。您应该能够通过告诉 Core Image 画笔描边过滤器的region of interest 和定义域 (extent) 来进行大量优化。然后它应该能够只渲染图像的必要部分,而不是每一帧中的全部内容。

【讨论】:

  • 那个实现非常接近我想要做的,没有 CIImageAccumulator,我不知道它存在。我仍然需要深入阅读它,但听起来很有希望,谢谢!到目前为止,我一直在尝试在 Metal 中将纹理标记到四边形,虽然它可以正常工作,但正如预期的那样,它比使用 Core Image 要复杂得多。现在,当谈到在金属中实现投资回报率时,有没有办法做到这一点?因为片段着色器将在图像/四边形的每个像素中计算。如果我只想更新一个小矩形怎么办?也许只是在 ROI 之外的像素中进行直通?
猜你喜欢
  • 1970-01-01
  • 2012-07-13
  • 2019-11-01
  • 2020-11-24
  • 2021-10-14
  • 2019-05-08
  • 1970-01-01
  • 2014-03-12
  • 2019-06-28
相关资源
最近更新 更多