Metal 如何在 GPU 上执行指令

创建指令队列

在初始化的时候创建的一些 Metal 对象,如指令队列和管道对象,通常会长久地保留它们。因为创建一次消耗较大,但是一旦初始化,可以快速重复使用。

创建一个指令队列
为了创建指令队列,调用设备的makeCommandQueue 函数:

 commandQueue = device.makeCommandQueue()

因为您通常会重用命令队列,所以请对其进行强引用。您可以使用命令队列来保存命令缓冲区,如下所示:

创建一个或多个管道对象

管道对象告诉 Metal 如何处理命令。管道对象封装了您使用 Metal 着色语言编写的函数。以下是管道如何适合您的Metal工作流程:

  • 编写处理数据的 Metal 着色器函数
  • 创建包含着色器的管道对象
  • 当您准备好使用它时,启用管道
  • 进行绘制,计算或 blit 调用

Metal 不会立即执行绘制,计算或 blit 调用;相反,使用编码器对象将对象存储在指令缓存区。提交命令缓冲区后,Metal 将其发送到 GPU 并使用活动管道对象处理其命令。

设置指令队列和管道后,就可以向GPU发出命令了。以下是您遵循的流程:

  • 创建一个指令缓存区
  • 使用命令填充缓存区
  • 提交指令缓存区到 GPU

创建指令缓存区

在指令队列上,使用 makeCommandBuffer()创建指令缓存区

guard let commandBuffer = commandQueue.makeCommandBuffer() else { 
    return 
}

对于单线程应用程序,您可以创建单个命令缓冲区。下图展示了命令与命令缓冲区之间的关系:

要使命令能够运行,请将命令缓冲区提交给GPU

commandBuffer.commit()

提交命令缓冲区不会立即运行其命令。相反,Metal 会调度缓冲区的命令,使其仅在您提交在队列中等待的先前命令缓冲区之后才能运行。如果您没有明确地将命令缓冲区排入队列,则在您提交缓冲区后,Metal会为您执行此操作。

提交后不再重用缓冲区,但可以选择通知其调度,完成或查询其状态。

指令编码

指令编码器将指令(如绘制,计算)编码并放到指令缓存区。

可以使MTLCommandEncoder的具体子类对实际命令进行编码,具体取决于你的任务:

  • 使用 MTLRenderCommandEncoder发出渲染命令
  • 使用MTLComputeCommandEncoder发出并行计算命令
  • 使用MTLBlitCommandEncoder发出资源管理命令

你可能感兴趣的:(Metal 如何在 GPU 上执行指令)