如何将现有的 OpenGL 纹理转换为金属纹理

How to Convert Existing OpenGL Texture to Metal Texture

我正在为 Motion 和 FCP X 开发一些 FxPlug 插件。最终,我想让它们在 Metal 中呈现,因为 Apple 正在弃用 OpenGL。

我目前正在使用 CoreImage,虽然我已经能够使用 CoreImage 功能在 FxPlug SDK 之外进行 Metal 处理,但 FxPlug 仅向我提供作为 OpenGL 纹理的帧。我试过将它传递给 CoreImage 过滤器,但我最终得到了这个错误:

Cannot render image (with an input GL texture) using a metal-DG context.

经过一段时间的 research,我发现我可以使用 CVPixelBuffers 在两者之间共享纹理,但是在尝试使用这种方法编写代码一段时间后,我开始相信这是一种将(如从头开始创建)写入共享缓冲区的方式,但不能在两者之间进行转换。虽然这可能不正确,但我找不到让现有 GL 纹理存在于 CVPixelBuffer 中的方法。

TL;DR:我找到了从 CVPixelBuffer 获取结果 Metal 或 OpenGL 纹理的方法,但我找不到从现有 OpenGL 纹理创建 CVPixelBuffer 的方法。我不喜欢这种方法,因为我的最终目标是简单地从 OpenGL 转换为 Metal,然后再转换回 OpenGL(理想情况下以一种有效的方式)。

有没有其他人找到将 FxPlug 与 Metal 一起使用的方法?有什么好的方法可以将 OpenGL 纹理转换为 Metal/CVPixelBuffer?

我编写了一个同时使用 OpenGL 纹理和金属纹理的 FxPlug。您要查找的是 IOSurface。它们是可以与 Metal 或 OpenGL 一起使用的纹理,尽管它们有一些限制。因此,如果您已经拥有 Metal 或 OpenGL 纹理,则必须将其复制到 IOSurface 中以用于其他系统。

要创建一个 IOSurface,您可以使用 CVPixelBuffers(通过包含 kCVPixelBufferIOSurfacePropertiesKey)或者您可以直接使用 IOSurface class 在 <IOSurface/IOSurfaceObjC.h> 中定义。

一旦你有了 IOSurface,你可以通过 CGLTexImageIOSurface2D()IOSurface 获取 OpenGL 纹理(在 <OpenGL/CGLIOSurface.h> 中定义),将你的 OpenGL 纹理复制到其中.然后,您获取该纹理并将其用作 FBO 的背景纹理。例如,您可以使用输入 FxTexture 作为纹理在其中绘制一个带纹理的四边形。确保调用 glFlush() 完成!

接下来获取 IOSurface 并通过 -[MTLDevice newTextureWithDescriptor:ioSurface:plane:] 从中创建一个 MTLTexture(描述为 here)。您需要创建一个输出 IOSurface 来绘制并从中创建一个 MTLTexture。将 Metal 渲染到输出中 MTLTexture。接下来,获取输出 IOSurface 并通过 CGLTexImageIOSurface2D() 从中创建一个 OpenGL 纹理。现在将该 OpenGL 纹理复制到输出 FxTexture 中,方法是将其用作纹理支持的 FBO 的支持或您喜欢的任何其他方法。

如您所见,这样做的缺点是每次渲染都需要 2 个副本 - 1 个输入到 IOSurface 和 1 个输出 IOSurface 到应用程序提供的输出纹理你。另一个缺点是,这可能完全没有实际意义,因为 Apple 公开宣布他们将终止对 OpenGL 的支持,他们可能已经在研究基于 Metal 的解决方案。自己做这一切可能是额外的工作。 (虽然好处是您可以在其他仅支持 OpenGL 的主机应用程序中使用相同的代码。)