Tag: Coregraphics

通过共享资源内存来结合CoreGraphics和Metal的功能

Metal API很棒,它为移动设备和台式设备打开了很多可能性。 但是, GPU有时可能有点笨拙,尤其是在诸如字体渲染或曲线绘制之类的高精度项目中,因此有时您确实会错过旧的CPU优秀项目。 我经常碰巧会想使用CoreGraphics的一些功能,但是保持我的GPU管道快速高效,而没有多余的转换或CPU / GPU同步中断 。 启发我写这篇文章的情况是,使用户能够绘制遮罩覆盖图,以识别希望显示某些效果的区域。 当然可以用Metal来实现绘图,但这需要大量工作:保持路径数据,三角剖分和渲染逻辑。 对于快速原型,仅使用CoreGraphics会容易得多,但是最直接的方法是从UI画布创建CGImage ,然后转换为MTLTexture以将其作为遮罩提供给某些着色器。 多维门户 但是,如果我们希望避免不必要的转换并将CoreGraphics路径直接绘制到MTLTexture中怎么办 ? 这似乎完全有可能! 为了实现这一点,我们必须在某些CGContext和MTLTexture之间共享一个内存缓冲区。 Metal可以从MTLBuffer对象创建纹理,而MTLBuffer则有机会指向已分配的内存。 因此,我们需要执行以下操作: 为CGContext分配内存 创建指向相同内存的MTLBuffer 从MTLBuffer创建MTLTexture 瞧! 实施 免责声明#1:在此演示中,我使用Alloy ,这是我在Apple平台上所有GPU项目中使用的Metal库。 它在香草金属上提供了一个很小的Swifty API 免责声明2:我既不在演示中也不做任何分解,也没有错误处理。 一切都在视图控制器中完成,无论是强制展开还是致命错误。 本文用作参考片段。 当为MTLBuffer分配无副本内存时,事情有些棘手。 为了使其快乐,它必须完美对齐 ,通常为4096字节。 在创建MTLBuffer时, MTLTextures也很麻烦 :我们必须对齐每个纹理行 ,并且对齐方式取决于我们要使用的像素格式 。 幸运的是,这两个任务都是可行的! 为了演示起见,我们将为MTKView上的可绘制单通道蒙版分配共享资源。 每当我们的MTKView更改大小时,我们都会重新分配掩码。 当然不是必须的,但这是最简单的方法。 首先,我们需要从系统中了解RAM页面大小,因此,我们将使用getpagesize()函数。 现在我们必须计算每行对齐的字节数和总分配大小。 为了分配对齐的内存,我们将使用posix_memalign(_,_,_)系统函数。 请注意,从这一点来看,我们负责分配此内存,但是稍后我们将对其进行处理 现在我们准备从此内存创建CGContext ,您可能已经完成了很多次,因此这应该非常简单: 我在这里使用CGImageAlphaInfo.no​​ne表示这是灰度图像,但是您也可以使用.alphaOnly 使用完全相同的内存,我们现在可以创建一个无副本MTLBuffer ,使其负责释放内存。 但是,您当然可以通过将nil传递给最后一个参数来自行管理。 现在,最后一步:我们正在从此缓冲区创建纹理。 纹理的存储模式必须与缓冲区相同。 […]