Apple Metal 2 1.Metal 设备和命令

原文https://developer.apple.com/documentation/metal/devices_and_commands

设备和命令

展示CPU如何访问GPU以及交互
示例代码

概览

Metal 提供底层和低功耗的方式去访问用户设备的图像处理单元(简称GPU).
GPU 高效的APP .
开发一个GPU Metal APP的关键就是 需要理解软件和硬件.

在这个例子中,你将要学习如何写 通过Metal 以及 基础的渲染命令 创建APP.

尤其是 你将学校如何包含一个Metal设备 ,配置MetalKit View 创建和执行GPU命令,显示渲染内容.

Metal 和MetalKit 框架

示例 使用两个框架 显示 渲染内容. Metal 和 MetalKit .
Metal提供访问GPU ,MetalKit 提供一个通用的工具 让开发者更简单的开发Metal APP.

集成在OS 和 其他框架 ,所以你只需要关注GPU 编程.

MetalKit 框架 使用最多的特性之一 就是 MTKView 类, 这个类 是 封装了 UIViewNSView 对象, 已经配置 Metal 特定的 核心动画 功能.

尤其是 一个MetalKit 视图 自动设置和关键 持续渲染循环 为你提供 2D 和显示的资源 ,通用的可绘画对象, 为每一帧.

注意:
你可以直接使用 核心动画 来开发一个Metal app ,但是使用MetlKit 框架 更简单 更快速,更方便.

分割你的渲染循环

当开发一个Metal APP 时候 ,经常 去 分割 你的渲染循环 到自定义类中. 使用分离的类 ,你可以更好的管理你的初始化Metal 设置代码 以及 每一帧 Metal 命令.

这是一个通用架构 展示 AAPLRenderer 类 , 初始化 MetalKit view 和 设置view 的代理.

_renderer = [[AAPLRenderer alloc] initWithMetalKitView:_view];

if(!_renderer)
{
    NSLog(@"Renderer failed initialization");
    return;
}

_view.delegate = _renderer;

响应视图事件

MTKViewDelegate 对象 实现 mtkView:drawableSizeWillChange: and drawInMTKView:方法,这两个方法 通知你的MetalKit 视图大小更改 和 绘画事件.

  • 这个视图调用 mtkView:drawableSizeWillChange: 方法 当Window 尺寸大小 改变时(MacOS), 或者 重新布局操作, 比如 设备方向改变 (主要发生在 iOS 和 TvOS ), 你能响应 视图的新尺寸 和 改变你的渲染分辨率 ,如果你需要的话.
  • 视图调用 drawInMTKView: 方法 当 渲染新的一帧的时候, 可以指定 帧率 60 FPS ,通过 preferredFramesPerSecond 属性.
    回调 通常 是 主要 事件 在 你的渲染循环开始执行.

Metal 命令对象

MTLDevice 对象代表 GPU. 可以 通过调用MTLCreateSystemDefaultDevice () ,包含 一个单一的MTLDevice 对象 代表 默认的GPU 设备.

MacOS 设备 有多个GPU ,调用MTLCopyAllDevices () 返回 设备中所有的GPU 设备数据, 一个MTLDevice 对象 提供关于一个GPU的信息.
但是 主要的目的是 创建其他对象 能够和GPU 互相的.

第一个对象是 所有的app 需要 和 MTLCommandQueue 交互.

_commandQueue = [_device newCommandQueue];

你使用 MTLCommandQueue 对象 去创建和管理MTLCommandBuffer 对象,确保 他们按照正确的顺序 发送指令到GPU

每一帧 , MTLCommandBuffer对象 是 创建 和 填充 命令 被GPU 执行.

id <MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];

这有不同类型的GPU , 每一个接受 和中断命令在自己独一无二的方法.
MTLCommandBuffer对象 合并 这些命令 到单一的提交. 但是他们必须第一个编码设备无关的方法 使用 MTLCommandEncoder对象. 这是少数不同的类型 MTLCommandEncoder类 , 每一个使用不同类型在GPU.
这示例 使用 MTLRenderCommandEncoder子类 指定编码渲染命令到 commandBuffer.

本示例 使用MTLRenderCommandEncoder 对象 编码GPU命令, 渲染像素到MetalKit视图的可绘画对象.
渲染编码器 必须指定 与可绘画对象 相关联.

为了创建 MTLRenderCommandEncoder 你必须创建一个MTLRenderPassDescriptor
MTLRenderPassDescriptor是轻量级,临时对象, 一些配置属性 使用 现存的 MTLCommandBuffer 对象 创建 新的 MTLRenderCommandEncoder .
之后,MTLRenderPassDescriptor 不再需要.

下面的示意插图 表达 Metal 命令对象之间的关系,总结为:

  1. Command Queue 创建 Command buffers

  2. Command encoders 将命令编码后 传入到 Command Buffers

  3. Command buffers 被提交到GPU

  4. GPU 执行编码命令 和将渲染后的结果显示到可绘画对象.

ef21c374-9645-451a-b39b-fe213a6f1668.png

Prepare a Frame

MetalKit视图 创建 新的 MTLRenderPassDescriptor 在每一帧. 提供currentRenderPassDescriptor 属性.
该渲染管道描述 是 预编译的 视图指定属性, 一些起源来自 视图的可绘画对象, 能够使用容易和方便的 去创建 新的 MTLRenderCommandEncoder对象.


// Obtain a renderPassDescriptor generated from the view's drawable textures
MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;

// If we've gotten a renderPassDescriptor we can render to the drawable, otherwise we'll
//   skip any rendering this frame because we have no drawable to draw to
if(renderPassDescriptor != nil)
{

    id <MTLRenderCommandEncoder> renderEncoder =
        [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];

命令编码 到 MTLRenderCommandEncoder 对象渲染 可绘画对象 , 默认情况下 创建MTLRenderCommandEncoder 对象 默认 编码 清除命令(clear command) 到 GPU执行 在 其他渲染命令之前. 清除命令(clear command) 设置 可绘画对象的像素 去 清除颜色 更新 在渲染循环的开始.

view.clearColor = MTLClearColorMake(color.red, color.green, color.blue, color.alpha);

Finalize a Frame

Metal app 调用MTLRenderCommandEncoder 方法 编码明确的渲染命令 到 command buffer. 简单来说 这个案例 不实际编码 渲染命令. 仅仅含蓄的清除命令被编码. 在创建 MTLRenderCommandEncoder 之后 , 本案例简单的调用 endEncoding方法 指示 编码器已经完成编码操作.

因为GPU没有直接绘制在屏幕, 防止2 绘画像素 在完成绘制之前 执行命令. 为了避免糟糕的用户体验 结果 不完全可绘画, 你可以调用 presentDrawable :方法. 该方法告诉Metal 等待 直到 GPU完成渲染可绘画对象 在展示屏幕之前.


[commandBuffer presentDrawable:view.currentDrawable];

GPU 不能立即执行命令, 调用MTLRenderCommandEncoder或者MTLCommandBuffer 对象 执行 在提交方法以后调用. Metal 调度 command buffer 的执行
当GPU 开始执行的时候,可绘画对象 被清理为新的颜色. 当GPU完成执行以后,渲染可绘画对象呗展示到屏幕上.

[commandBuffer commit];

接下来

在本示例中, 你学习了如何利用Metal框架编写一个app以及了解基本的渲染命令到GPU.

你好,三角形示例中, 你将要通过Metal框架学习基本的几何体.

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

推荐阅读更多精彩内容