Metal框架详细解析(三十八) —— Metal编程指南之命令组织和执行模型(三)

版本记录

版本号 时间
V1.0 2018.11.04 星期日

前言

很多做视频和图像的,相信对这个框架都不是很陌生,它渲染高级3D图形,并使用GPU执行数据并行计算。接下来的几篇我们就详细的解析这个框架。感兴趣的看下面几篇文章。
1. Metal框架详细解析(一)—— 基本概览
2. Metal框架详细解析(二) —— 器件和命令(一)
3. Metal框架详细解析(三) —— 渲染简单的2D三角形(一)
4. Metal框架详细解析(四) —— 关于GPU Family 4(一)
5. Metal框架详细解析(五) —— 关于GPU Family 4之关于Imageblocks(二)
6. Metal框架详细解析(六) —— 关于GPU Family 4之关于Tile Shading(三)
7. Metal框架详细解析(七) —— 关于GPU Family 4之关于光栅顺序组(四)
8. Metal框架详细解析(八) —— 关于GPU Family 4之关于增强的MSAA和Imageblock采样覆盖控制(五)
9. Metal框架详细解析(九) —— 关于GPU Family 4之关于线程组共享(六)
10. Metal框架详细解析(十) —— 基本组件(一)
11. Metal框架详细解析(十一) —— 基本组件之器件选择 - 图形渲染的器件选择(二)
12. Metal框架详细解析(十二) —— 基本组件之器件选择 - 计算处理的设备选择(三)
13. Metal框架详细解析(十三) —— 计算处理(一)
14. Metal框架详细解析(十四) —— 计算处理之你好,计算(二)
15. Metal框架详细解析(十五) —— 计算处理之关于线程和线程组(三)
16. Metal框架详细解析(十六) —— 计算处理之计算线程组和网格大小(四)
17. Metal框架详细解析(十七) —— 工具、分析和调试(一)
18. Metal框架详细解析(十八) —— 工具、分析和调试之Metal GPU Capture(二)
19. Metal框架详细解析(十九) —— 工具、分析和调试之GPU活动监视器(三)
20. Metal框架详细解析(二十) —— 工具、分析和调试之关于Metal着色语言文件名扩展名、使用Metal的命令行工具构建库和标记Metal对象和命令(四)
21. Metal框架详细解析(二十一) —— 基本课程之基本缓冲区(一)
22. Metal框架详细解析(二十二) —— 基本课程之基本纹理(二)
23. Metal框架详细解析(二十三) —— 基本课程之CPU和GPU同步(三)
24. Metal框架详细解析(二十四) —— 基本课程之参数缓冲 - 基本参数缓冲(四)
25. Metal框架详细解析(二十五) —— 基本课程之参数缓冲 - 带有数组和资源堆的参数缓冲区(五)
26. Metal框架详细解析(二十六) —— 基本课程之参数缓冲 - 具有GPU编码的参数缓冲区(六)
27. Metal框架详细解析(二十七) —— 高级技术之图层选择的反射(一)
28. Metal框架详细解析(二十八) —— 高级技术之使用专用函数的LOD(一)
29. Metal框架详细解析(二十九) —— 高级技术之具有参数缓冲区的动态地形(一)
30. Metal框架详细解析(三十) —— 延迟照明(一)
31. Metal框架详细解析(三十一) —— 在视图中混合Metal和OpenGL渲染(一)
32. Metal框架详细解析(三十二) —— Metal渲染管道教程(一)
33. Metal框架详细解析(三十三) —— Metal渲染管道教程(二)
34. Metal框架详细解析(三十四) —— Hello Metal! 一个简单的三角形的实现(一)
35. Metal框架详细解析(三十五) —— Hello Metal! 一个简单的三角形的实现(二)
36. Metal框架详细解析(三十六) —— Metal编程指南之概览(一)
37. Metal框架详细解析(三十七) —— Metal编程指南之基本Metal概念(二)

Command Organization and Execution Model - 命令组织和执行模型

在Metal架构中,MTLDevice协议定义了代表单个GPU的接口。 MTLDevice协议支持询问设备属性的方法,用于创建其他特定于设备的对象(如缓冲区和纹理),以及用于编码和排队渲染和计算命令以提交给GPU执行。

命令队列由命令缓冲区队列组成,命令队列组织这些命令缓冲区的执行顺序。命令缓冲区包含用于在特定设备上执行的编码命令。命令编码器将渲染,计算和blitting命令附加到命令缓冲区,并且最终提交那些命令缓冲区以在设备上执行。

MTLCommandQueue协议定义了命令队列的接口,主要支持创建命令缓冲区对象的方法。 MTLCommandBuffer协议定义了命令缓冲区的接口,并提供了创建命令编码器,排队命令缓冲区以执行,检查状态和其他操作的方法。MTLCommandBuffer协议支持以下命令编码器类型,这些接口用于将不同类型的GPU工作负载编码到命令缓冲区中:

在任何时间点,只有一个命令编码器可以处于活动状态,并将命令附加到命令缓冲区中。必须先结束每个命令编码器,然后才能创建另一个命令编码器以与同一命令缓冲区一起使用。 “每个命令缓冲区的一个活动命令编码器”规则的一个例外是MTLParallelRenderCommandEncoder协议,在 Encoding a Single Rendering Pass Using Multiple Threads中讨论。

完成所有编码后,您将提交MTLCommandBuffer对象本身,该对象将命令缓冲区标记为可供GPU执行。相对于已在命令队列中的其他MTLCommandBuffer对象,MTLCommandQueue协议控制何时执行提交的MTLCommandBuffer对象中的命令。

图2-1显示了命令队列,命令缓冲区和命令编码器对象如何密切相关。图顶部的每列组件(缓冲区,纹理,采样器,深度和模板状态,管道状态)表示特定于命令编码器的资源和状态。


The Device Object Represents a GPU - 代表GPU的设备对象

MTLDevice对象表示可以执行命令的GPU。 MTLDevice协议具有创建新命令队列,从内存分配缓冲区,创建纹理以及查询设备功能的方法。 要在系统上获取首选系统设备,请调用MTLCreateSystemDefaultDevice函数。


Transient and Non-transient Objects in Metal - Metal中的瞬态和非瞬态对象

Metal中的一些对象设计为瞬态且极轻量级,而其他对象则更昂贵且可能持续很长时间,可能是应用程序的生命周期。

命令缓冲区和命令编码器对象是瞬态的,仅供单次使用。 分配和释放它们非常便宜,因此它们的创建方法返回自动释放的对象。

以下对象不是瞬态的。 在性能敏感的代码中重用这些对象,并避免重复创建它们。

  • Command queues
  • Data buffers
  • Textures
  • Sampler states
  • Libraries
  • Compute states
  • Render pipeline states
  • Depth/stencil states

Command Queue - 命令队列

命令队列接受GPU将执行的命令缓冲区的有序列表。 发送到单个队列的所有命令缓冲区都保证按命令缓冲区入队的顺序执行。 通常,命令队列是线程安全的,允许同时编码多个活动命令缓冲区。

要创建命令队列,请调用MTLDevice对象的newCommandQueue方法或newCommandQueueWithMaxCommandBufferCount:方法。 通常,命令队列应该是长寿命的,因此不应重复创建和销毁它们。


Command Buffer - 命令缓冲区

命令缓冲区存储编码的命令,直到缓冲区被提交以供GPU执行。单个命令缓冲区可以包含许多不同类型的编码命令,具体取决于用于构建它的编码器的数量和类型。在典型的应用程序中,整个渲染帧被编码到单个命令缓冲区中,即使渲染该帧涉及多个渲染过程,计算处理函数或blit操作。

命令缓冲区是瞬态一次性对象,不支持重用。一旦命令缓冲区被提交执行,唯一有效的操作是等待命令缓冲区被调度或完成 - 通过在Registering Handler Blocks for Command Buffer Execution中讨论的同步调用或处理程序块 - 并检查命令缓冲区执行状态。

命令缓冲区也是应用程序唯一可独立跟踪的工作单元,它们定义了由Metal Memory模型建立的一致性边界,详见Resource Objects: Buffers and Textures

1. Creating a Command Buffer - 创建命令缓冲区

要创建MTLCommandBuffer对象,请调用MTLCommandQueuecommandBuffer方法。 MTLCommandBuffer对象只能提交到创建它的MTLCommandQueue对象中。

commandBuffer方法创建的命令缓冲区保留执行所需的数据。 对于某些情况,如果在执行MTLCommandBuffer对象期间在其他位置保留这些对象,则可以通过调用MTLCommandQueuecommandBufferWithUnretainedReferences方法来创建命令缓冲区。 仅对极其性能关键的应用程序使用commandBufferWithUnretainedReferences方法,这些应用程序可以保证关键对象在应用程序的其他位置具有引用,直到命令缓冲区执行完成。 否则,可能会过早释放不再具有其他引用的对象,并且未定义命令缓冲区执行的结果。

2. Executing Commands - 执行命令

MTLCommandBuffer协议使用以下方法在命令队列中建立命令缓冲区的执行顺序。 命令缓冲区在提交之前不会开始执行。 一旦提交,命令缓冲区按它们入队的顺序执行。

  • enqueue方法为命令队列上的命令缓冲区保留一个位置,但不提交命令缓冲区以供执行。 最终提交此命令缓冲区时,将在相关命令队列中任何先前排队的命令缓冲区之后执行该命令缓冲区。
  • commit方法使命令缓冲区尽快执行,但是在提交了同一命令队列中的任何先前排队的命令缓冲区之后。 如果先前没有将命令缓冲区入队,则commit会进行隐含的enqueue调用。

有关使用多线程入队的示例,请参阅Multiple Threads, Command Buffers, and Command Encoders

3. Registering Handler Blocks for Command Buffer Execution - 为命令缓冲区执行注册处理块

下面列出的MTLCommandBuffer方法监视命令执行。计划和完成的处理程序在未定义的线程上按执行顺序调用。您在这些处理程序中执行的任何代码都应该快速完成;如果需要进行昂贵或阻塞工作,请将该工作推迟到另一个线程。

  • addScheduledHandler:方法注册在调度命令缓冲区时要调用的代码块。当满足其他MTLCommandBuffer对象或系统中的其他API提交的工作之间的任何依赖关系时,将考虑调度命令缓冲区。您可以为命令缓冲区注册多个预定处理程序。
  • waitUntilScheduled方法在调度命令缓冲区之后同步等待并返回,并且addScheduledHandler:方法注册的所有处理程序都已完成。
  • addCompletedHandler:方法在设备完成命令缓冲区的执行后立即注册要调用的代码块。您可以为命令缓冲区注册多个已完成的处理程序。
  • waitUntilCompleted方法在设备完成命令缓冲区的执行后同步等待并返回,并且addCompletedHandler:方法注册的所有处理程序都已返回。

presentDrawable:方法是已完成处理程序的特例。这种便捷方法在调度命令缓冲区时呈现可显示资源(CAMetalDrawable对象)的内容。有关presentDrawable:方法的详细信息,请参阅Integration with Core Animation: CAMetalLayer

4. Monitoring Command Buffer Execution Status - 检测命令缓冲区执行状态

只读status属性包含Command Buffer Status Codes中列出的MTLCommandBufferStatus枚举值,该值反映了此命令缓冲区生命周期中的当前调度阶段。

如果执行成功完成,则只读error属性的值为nil。 如果执行失败,则status设置为MTLCommandBufferStatusErrorerror属性可能包含Command Buffer Error Codes中列出的值,指示失败的原因。


Command Encoder - 命令编码器

命令编码器是一个瞬态对象,您可以使用该对象以GPU可以执行的格式将命令和状态写入单个命令缓冲区。 许多命令编码器对象方法将命令附加到命令缓冲区。 命令编码器处于活动状态时,它具有为其命令缓冲区附加命令的专有权。 完成编码命令后,调用endEncoding方法。 要编写更多命令,请创建一个新的命令编码器。

1. Creating a Command Encoder Object - 创建命令编码器对象

由于命令编码器将命令附加到特定命令缓冲区,因此您可以通过从要使用它的MTLCommandBuffer对象中请求命令来创建命令编码器。 使用以下MTLCommandBuffer方法创建每种类型的命令编码器:

2. Render Command Encoder - 渲染命令编码器

可以根据rendering pass来描述图形渲染。 MTLRenderCommandEncoder对象表示与单个渲染过程关联的渲染状态和绘制命令。 MTLRenderCommandEncoder需要关联的MTLRenderPassDescriptor(在Creating a Render Pass Descriptor中描述),其包括用作渲染命令的目标的颜色,深度和模板附件。MTLRenderCommandEncoder具有以下方法:

  • 指定包含顶点,片段或纹理图像数据的图形资源,例如缓冲区和纹理对象
  • 指定包含已编译渲染状态的MTLRenderPipelineState对象,包括顶点和片段着色器
  • 指定固定功能状态,包括视口,三角形填充模式,剪刀矩形,深度和模板测试以及其他值
  • 绘制3D基元

有关MTLRenderCommandEncoder协议的详细信息,请参阅Graphics Rendering: Render Command Encoder

3. Compute Command Encoder - 计算命令编码器

对于数据并行计算,MTLComputeCommandEncoder协议提供了对命令缓冲区中的命令进行编码的方法,该命令缓冲区可以指定计算函数及其参数(例如,纹理,缓冲区和采样器状态)并调度计算函数以供执行。 要创建计算命令编码器对象,请使用MTLCommandBuffercomputeCommandEncoder方法。 有关MTLComputeCommandEncoder方法和属性的详细信息,请参阅Data-Parallel Compute Processing: Compute Command Encoder

4. Blit Command Encoder - Blit命令编码器

MTLBlitCommandEncoder协议具有为缓冲区(MTLBuffer)和纹理(MTLTexture)之间的内存复制操作附加命令的方法。 MTLBlitCommandEncoder协议还提供了使用纯色填充纹理并生成mipmap的方法。 要创建blit命令编码器对象,请使用MTLCommandBufferblitCommandEncoder方法。 有关MTLBlitCommandEncoder方法和属性的详细信息,请参阅Buffer and Texture Operations: Blit Command Encoder

5. Multiple Threads, Command Buffers, and Command Encoders - 多线程,命令缓冲区和命令编码器

大多数应用程序使用单个线程在单个命令缓冲区中为单个帧编码渲染命令。在每个帧的末尾,您提交命令缓冲区,它既调度又开始执行命令。

如果要并行化命令缓冲区编码,则可以同时创建多个命令缓冲区,并使用单独的线程对每个命令缓冲区进行编码。如果事先知道命令缓冲区应该以什么顺序执行,那么MTLCommandBufferenqueue方法可以在命令队列中声明执行顺序,而无需等待命令被编码和提交。否则,当提交命令缓冲区时,它将在命令队列中任何先前排队的命令缓冲区之后分配一个位置。

只有一个CPU线程可以访问命令缓冲区。多线程应用程序可以使用每个命令缓冲区一个线程来并行创建多个命令缓冲区。

图2-2显示了一个包含三个线程的示例。每个线程都有自己的命令缓冲区。对于每个线程,一次一个命令编码器可以访问其相关的命令缓冲区。图2-2还显示了每个命令缓冲区接收来自不同命令编码器的命令。完成编码后,调用命令编码器的endEncoding方法,然后新的命令编码器对象可以开始将命令编码到命令缓冲区。

MTLParallelRenderCommandEncoder对象允许在多个命令编码器之间分解单个渲染过程并将其分配给单独的线程。 有关MTLParallelRenderCommandEncoder的更多信息,请参阅Encoding a Single Rendering Pass Using Multiple Threads

后记

本篇主要讲述了Metal编程指南之命令组织和执行模型,感兴趣的给个赞或者关注~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容