[MetalKit]Introducing Metal 2介绍Metal2

本系列文章是对 http://metalkit.org 上面MetalKit内容的全面翻译和学习.

MetalKit系统文章目录


今年的WWDC可能是有史以来最重要的,至少目前我们 - Metal开发者 - 终于被关注了.我可以诚心诚意地讲这是我生命中最棒的一周!

让我们看看Games and Graphics游戏和图形新闻.最意想不到的是,将Metal重命名为Metal 2.自从它在2014年第一次被发布后,它终于有了最显著的增加和增强,确实,但我们必须承认:没人预见到这一变化的来临.最意想不到的奖品是新的ARKit框架.在keynote演示之后仅仅几周,就已经有了大量大胆有趣的增强现实项目放出来. ARKit融入Metal非常容易.最后,最有影响力的奖品是VR.这是因为虚拟现实现在能够实现更低延迟,更高帧率,还有更强劲的内置显卡,现在也有了外置显卡external GPUs.

vr.png

Model I/O, SpriteKitSceneKit框架也都添加了新特性.其它令人感兴趣的增加是用于机器学习 machine learningCoreMLVision框架.本文只关注Metal中的新特色:

1). MPS - Metal Performance Shaders目前在macOS上也可以使用了,添加的新特性包括:

  • 四种新的图片处理基本体(Image Keypoints图像关键点, Bilinear Rescale双线性重缩放, Image Statistics图像统计, Element-wise Arithmetic Operations元素运算符).
  • 新的线性代数对象如MPSVector, MPSMatrixMPSTemporaryMatrix,还有*BLAS-style matrix-matrix and matrix-vector multiplication - BLAS式的矩阵-矩阵及矩阵-向量乘法,LAPACK-style triangular matrix factorization and linear solvers - LAPACK式三角矩阵分解与线性求解器`.
  • 一系列新的CNN基本体.
  • Binary二进制卷积, XNOR同或卷积, Dilated空洞卷积, Sub-pixel子像素卷积Transpose转置卷积的卷积层被添加到现有的Standard标准卷积基本体内.
  • 添加了一个新的Neural Network Graph神经网络图形API,在用过滤器和图形节点来描述神经网络时非常有用.
  • 现在也有了Recurrent Neural Networks循环神经网络,它可以改善CNNs一对一的局限性,实现一对多和多对多的关系.

2). Argument Buffers参数缓冲器/变元缓冲器 - 可能是今年对框架最重要的添加.在传统的增强模型中,我们会为每个对象调用许多函数来设置缓冲器,纹理,线性采样,最后为该对象调用绘制命令.

ArgumentBuffers1.png

正如你想象的那样,,当将该数量乘以物体总数量及绘制帧数时,调用数急剧增长.最终这会限制屏幕上出现的物体数量.


ArgumentBuffers2.png

Argument Buffers参数缓冲器引入了一个高效的新途径来使用资源,通过采用始终存在的indirect behavior间接行为,来将其应用到纹理,采样,状态,指向其它缓冲器的指针,等等.参数缓冲器将只有每物体2个API调用:设置参数缓冲器,然后绘制.这样可以绘制更多物体.

ArgumentBuffers3.png

参数缓冲器很容易使用,就像匹配着色器数据和主机数据一样:

struct Material {
    float intensity;
    texture2d<float> aTexture;
    sampler aSampler;
}

kernel void compute(constant Material &material [[ buffer(0) ]]) {
    ...
}

CPU上,参数缓冲器是被MTLArgumentEncoder对象创建和使用的,然后它可以轻易地在CPUGPU之间做位块传送:

let function = library.makeFunction(name: "compute")
let encoder = function.makeIndirectArgumentEncoder(bufferIndex: 0)
encoder.setTexture(myTexture, index: 0)
encoder.constantData(at: 1).storeBytes(of: myPosition, as: float4)

但是使用dynamic indexing动态索引特性的话还可以更好.举例,当渲染拥挤时,参数缓冲器数组可以将所有实例(物体)的数据打包到一起.然后,不再需要每个物体调用两次,改为每帧2个API调用:一个设置到缓冲器,一个为大量实例绘制索引的基本体!

ArgumentBuffers4.png

另一个应用参数缓冲器的例子是,当运行粒子模拟时.对此,我们有resource setting on the GPU特性,它的意思是有一个参数缓冲器数组,每个粒子(线程)一个缓冲器.所有的粒子特性(位置,材料,等)在GPU上的参数缓冲器中被创建和储存的,这样当一个粒子需要某个属性时,比如材料,它将从参数缓冲器中复制出来,而不再需要从CPU获取,这样可以避免昂贵的CPUGPU之间的复制开销.

ArgumentBuffers5.png

复制内核很简单,可以让你赋值一个常数,从源对象部分复制或者完全复制到目标对象:

kernel void reuse(constant Material &source [[ buffer(0) ]],
                  device Material &destination [[ buffer(1) ]]) {
    destination.intensity = 0.5f;
    destination.aTexture = source.aTexture;
    destination = source;
}

最后,还有一个应用例子是引用其它参数缓冲器(multiple indirections).想象有一个instance结构体表示一个指向Material材料结构体的实例(特征),这样的话就会有许多实例指向同一个材料.同样的,想象另一个表示一个树状节点的结构体,其中每个节点将会有一个指针指向Instance实例结构体,起到节点中的一个实例数组的作用:

struct Instance {
    float4 position;
    device Material *material;
}

struct Node {
    device Instance *instances;
}

注意:目前为止,只有Tier 2设置支持所有的参数缓冲器特性.从Metal 2开始,GPU设备分成了Tier 1(整体式)和Tier 2(分离式).

3). Raster Order Groups光栅扫描顺序组 - 一个新的片段着色器同步基本体,它在片段着色器访问内存时允许对顺序进行更精细的控制.例如,当使用自定义混合时,大部分图形APIs保证混合是按绘制调用顺序发生的.然而,GPU的并行线程需要一个方法来防止竞争条件.Raster Order Groups光栅扫描顺序组通过提供给我们一个隐含的Wait命令来保证.

RasterOrderGroups.png

在传统混合模式下,要创建竞争条件:

fragment void blend(texture2d<float, access::read_write> out[[ texture(0) ]]) {
    float4 newColor = 0.5f;
    // non-atomic memory access without any synchronization
    float4 oldColor = out.read(position);
    float4 blended = someCustomBlendingFunction(newColor, oldColor);
    out.write(blended, position);
}

需要做的就是添加Raster Order Groups属性到纹理(或资源)中来解决访问冲突:

fragment void blend(texture2d<float, access::read_write> 
                out[[texture(0), raster_order_group(0)]]) {
    float4 newColor = 0.5f;
    // the GPU now waits on first access to raster ordered memory
    float4 oldColor = out.read(position);
    float4 blended = someCustomBlendingFunction(newColor, oldColor);
    out.write(blended, position);
}

4). ProMotion自适应刷新率 - 目前只在iPad Pro显示屏上可用.没有ProMotion时典型的帧率是60FPS(16.6ms/frame):

promotion1.png

使用ProMotion后帧率提升到120FPS(8.3ms/frame),这对于用户输入非常有用,如手指触摸或pencil使用:

promotion2.png

ProMotion也提供了弹性机制来刷新显示图片,所以我们不需要使用固定帧率.不使用ProMotion会有图片刷新不一致,这对用户体验很不好.开发者为了实现一致性,通常会将峰值帧率强制保持在30FPS,而不是理想的48FPS(20.83ms/frame):

promotion3.png

使用ProMotion我现在可以每4ms就有一个刷新点,而不再是每16ms(竖直的白线):

promotion4.png

ProMotion同样有助于掉帧.不使用ProMotion时,可能一帧画面花了太长时间来显示,就错过了截止期限:

promotion5.png

ProMotion通过对帧扩展4ms而不是一个完整帧(16.6ms)来解决这个问题:

promotion6.png

UIKit动画自动使用ProMotion,但是在Metal视图中使用ProMotion,你需要在项目的Info.plist文件中设置一下,禁用最小帧率.然后你就可以使用3个显示APIs中的一个了.传统的present(drawable:)将会在GPU结束渲染一帧画面(在固定帧率显示屏上为16.6ms,在ProMotion显示屏上为4ms)后直接呈现图像.第二个APIpresent(drawable, afterMinimumDuration:)在固定帧率显示屏上提供了帧与帧之间的最大间隔.第三个APIpresent(drawable, atTime:),在创建自定义动画循环时非常有用,或者试图与其它输出,比如音频,同步时非常有用.这里是如何实现它的例子:

let targetTime = 0.1
let drawable = metalLayer.nextDrawable()
commandBuffer.present(drawable, atTime: targetTime)
// after 1-2 frames
let presentationDelay = drawable.presentedTime - targetTime

首先,当你想要展示画面时,设置一个时间,然后渲染场景到一个命令缓冲器中.然后等待下一帧(下几帧),最后检验延迟,这样你就可以调整下一帧的时间.

5). Direct to Display直连显示屏 - 新的方式,用于将渲染器的内容以最小延迟直接发送到外置显示器(如,VR中使用的头戴显示设备).一个画面在GPU结束渲染后到最终出现在显示屏上之前会有两条路径可选.第一条是当系统将其它视图和层混合起来形成最终图像时,典型的UI方案:

DirectToDisplay1.png

当创建一个不包含混合,缩放或其它视图/图层的全屏应用程序时,第二条途径允许显示屏直接访问我们渲染的内存,这样节省了大量系统资源,避免了很多开销:


DirectToDisplay2.png

然而,这需要满足下列条件:

  • 图层是不透明的
  • 没有遮罩或圆角
  • 全屏,或带有不透明的黑色状态栏和背景
  • 被渲染尺寸最大和显示屏尺寸一样大
  • 颜色空间和像素格式与显示屏兼容

颜色空间的要求,使得判断何时Direct to Display模式能使用变得简单.例如,如果你在使用P3显示屏却禁用了P3模式,当试图使用Direct to Display模式时会很容易探测出来.

6). Other Features其它特性 - 包含但不限于:

  • memory usage queries内存使用查询 - 现在有了新的APIs可以在每次分配时查询内存使用,还有设备的总GPU内存分配:
MTLResource.allocatedSize
MTLHeap.currentAllocatedSize
MTLDevice.currentAllocatedSize
  • SIMDGroup scoped functions单指令多数据流(SIMD)群组作用域函数 - 允许数据在SIMD组内被注册者共享,避免加载/储存操作:

    SIMDGroup.png

  • non-uniform threadgroup sizes非一致性线程组尺寸 - 帮助我们不浪费GPU循环,避免遇到边缘/边界情况:

    nonuniform.png

  • Viewport Arrays视口数组 - 在macOS上现在支持多达16视口,以供顶点函数在渲染时选择顶点,在VR中结合实例非常有用.

  • Multisample Pattern Control多重采样类型控制 - 允许选择在单个像素中MSAA处于什么采样模式,对于自定义反走样非常有用.

  • Resource Heaps资源堆 - 现在在macOS上也可以使用了.它允许以下时间:控制内存分配,快速重新分配,资源混叠,快速绑定的组相关资源.

  • 其它特性,包括:

Feature特性 Description描述
Linear Textures线性纹理 MTLBuffer创建纹理,无需复制
Function Constant for Argument Indexes为参数索引的函数常量 特殊的二进制编码,供着色器参数改变绑定索引
Additional Vertex Array Formats附加顶点数组格式 添加1个/2个组件的顶点格式,及一个BGRA8顶点格式.
IOSurface Textures IO表面纹理 iOS上从IOSurfaces创建MTLTextures
Dual Source Blending双重来源混合 带有两源参数的附加混合模式

我已经为最重要的新特性制作了一张表,来说明在最新版本的操作系统上是否是新特性.


features.png

最后,还有几行我写的代码,来测试内置与外置GPU之间的不同点:

gpuCompare.png

所有图片都来自WWDC报告.
源代码source code已发布在Github上.
下次见!

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

推荐阅读更多精彩内容