005-函数与库

函数与库

本章节介绍如何创建一个作为 Metal 着色器或计算函数的引用的 MTLFunction 对象,以及如何利用 MTLLibrary 对象组织和访问一个函数。

代表着色器函数或计算函数的 MTLFunction

一个 MTLFunction 对象代表一个由 Metal 着色器语言编写的函数,它能够作为图形或计算管线的一部分在 GPU 上执行。

你可以声明一个纹理、缓冲或采样器的参数索引,来实现在 Metal 运行时和用Metal 着色器语言编写的图形、计算函数之间传递数据或状态。参数索引唯一标识一个被 Metal 运行时和 Metal 着色代码共享的纹理、缓冲或采样器。

创建一个渲染管道状态 介绍了如何在一个渲染通道内,为 MTLRenderPipelineDescriptor 对象确定一个被用于顶点或片段着色器的 MTLFunction 对象。为计算缓冲编码器确定计算状态和资源 介绍了如何在一个计算通道内,为指定设备创建 MTLComputePipelineState 时确定一个 MTLFunction 对象。

函数库

一个 MTLLibrary 对象代表了一个或多个 MTLFunction 对象的集合库。单独一个 MTLFunction 对象代表了一个用 Metal 着色器语言编写的 Metal 函数,任何使用了 Metal 函数标识符(vertex, fragment, 或 kernel)的函数都可以被引用为函数库中的一个 MTLFunction 对象。没有被这些函数标识符标识的函数则不能直接被 MTLFunction 对象引用,但是可以在着色器中被间接调用。

可以通过以下方法创建一个函数库中的 MTLFunction 对象。

  • 在 app 构建阶段,将 Metal 着色器语言编写的代码编译到二进制库格式中
  • 在 app 运行时,编译一段包含 Metal 着色器语言源代码的字符串

通过编译后的代码创建函数库

为了最佳性能,最好在 Xcode 编译构建 app 过程中就将你的 Metal 着色器源代码编译到一个二进制文件中,这样能避免在运行时执行编译函数源码的性能损耗。调用以下 MTLDevice 方法之一即可从一个二进制库创建一个 MTLLibrary 对象。

  • newDefaultLibrary 从主 bundle 中检索包含一个 app 的 XCode 项目中所有着色器和计算函数的函数库
  • newLibraryWithFile:error: 接受一个函数库文件的路径,返回包含那个文件中所有存储的方法的 MTLLibrary 对象
  • newLibraryWithData:error: 接受一个包含函数代码的二进制数据集合,返回一个 MTLLibrary 对象

MTLFunction 不提供对函数参数的访问。可以在流水线状态的创建过程中,生成一个可访问着色器或计算函数参数细节的反射对象(可能为 MTLRenderPipelineReflection 或 MTLComputePipelineReflection,取决于命令编码器类型)。更多创建流水线状态和反射对象的信息请查阅 创建渲染流水线状态创建计算流水线状态。如果不使用反射对象中的数据,要避免持有它。

反射对象中包含一个数组,数组中包含所有当前命令编码器支持的函数的 MTLArgument 对象。对于 MTLComputeCommandEncoder,MTLComputePipelineReflection 的 arguments 属性包含一个 MTLArgument 数组,对应其计算函数的参数。对于 MTLRenderCommandEncoder,MTLRenderPipelineReflection 有两个属性,vertexArguments 和 fragmentArguments,分别对应于顶点着色器和片段着色器函数的参数。

反射对象不会包含所有的函数参数,仅包含具有相关资源的参数,不包含用 [[ stage_in ]] 修饰符或内建 [[ vertex_id ]] or [[ attribute_id ]] 修饰符声明的参数。

Listing 4-2 向你展示了如何获取一个反射对象(示例中用到了 MTLComputePipelineReflection 对象)并枚举它的 arguments 属性,获取其中的 MTLArgument 对象。

MTLComputePipelineReflection* reflection;
id <MTLComputePipelineState> computePS = [device
              newComputePipelineStateWithFunction:func
              options:MTLPipelineOptionArgumentInfo
              reflection:&reflection error:&error];
for (MTLArgument *arg in reflection.arguments) {
    //  process each MTLArgument
}

MTLArgument 的属性阐述了着色器语言函数的参数的细节

  • name 属性就是参数的名称
  • active 是一个布尔值,表明此参数是否可以被忽略
  • index 是一个从 0 开始的坐标值,表明它在对应参数表中的位置,如 [[ buffer(2) ]] 的 index 为2
  • access 表示访问权限,如读写修饰符限制的读写操作
  • type 由着色器语言的修饰符确定,如[[ buffer(n) ]],[[ texture(n) ]],[[ sampler(n) ]],或者 [[ threadgroup(n) ]]

type 还确定了 MTLArgument 其他属性的含义

  • 如果 type 为 MTLArgumentTypeTexture,则 textureType 属性就表示整体的纹理类型(例如texture1d_array,texture2d_ms,和 texturecube 等),textureDataType 属性就表示分量类型(half,float,int,或 uint)
  • 如果 type 为 MTLArgumentTypeThreadgroupMemory,则 threadgroupMemoryAlignment 和 threadgroupMemoryDataSize 与之关联
  • 如果 type 为 MTLArgumentTypeBuffer,则 bufferAlignment,bufferDataSize,bufferDataType,和 bufferStructType 就与之关联

如果 buffer 参数是一个结构体(此时 bufferDataType 为 MTLDataTypeStruct),则 bufferStructType 属性就会包含一个 MTLStructType 属性来表示这个结构体,bufferDataSize 代表了结构体的字节大小。如果 buffer 参数是一个数组(或者指向数组的指针),则 bufferDataType 属性就会表示数组中元素的类型,而 bufferDataSize 表示一个数组元素的字节大小。

Listing 4-3 深入一个 MTLStructType 对象来验证结构体成员变量,每一个都被 MTLStructMember 所表示。一个结构体成员变量可能是基本类型、数组或者一个嵌套结构体。如果这个成员变量是嵌套结构体,则调用此 MTLStructMember 的 structType 来获取一个 MTLStructType 变量以表示此嵌套结构体,然后继续递归深入解析它。如果成员变量是一个数组,则调用此 MTLStructMember 的 arrayType 来获取一个表示此数组的 MTLArrayType 变量,然后检查 MTLArrayType 的 elementType 变量以确定其内部元素的类型。如果 elementType 是 MTLDataTypeStruct,调用 elementStructType 以持有此结构体,然后继续深入它的成员变量。如果 elementType 是 MTLDataTypeArray,则调用 elementArrayType 来持有此子数组,并继续解析它。

MTLStructType *structObj = [arg.bufferStructType];
for (MTLStructMember *member in structObj.members) {
    //  process each MTLStructMember
    if (member.dataType == MTLDataTypeStruct) {
       MTLStructType *nestedStruct = member.structType;
       // recursively drill down into the nested struct
    }
    else if (member.dataType == MTLDataTypeArray) {
       MTLStructType *memberArray = member.arrayType;
       // examine the elementType and drill down, if necessary
    }
    else {
       // member is neither struct nor array
       // analyze it; no need to drill down further
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 223,689评论 6 521
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,685评论 3 401
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 170,676评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,496评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,512评论 6 399
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,044评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,423评论 3 427
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,399评论 0 278
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,923评论 1 323
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,973评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,117评论 1 354
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,761评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,440评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,929评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,045评论 1 275
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,609评论 3 380
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,147评论 2 363

推荐阅读更多精彩内容

  • 任志强最新透露:想买房的就加紧,2019年,你有钱也买不到房 现在一线大城市买房真的划算吗?上海租个单身公寓5千,...
    丹阳雨阅读 135评论 0 0
  • 风吹起,长发飘起,挡住受伤的眼神 我曾幻想过,我当长发及腰,身穿白裙,在夏日微风中,青丝与白裙共同摇拽,这样的画面...
    雾宇阅读 275评论 0 1
  • YESTERDAY: 1.Operating analysis 4 sheets of Jan.❌ 2.opera...
    Just_MM阅读 123评论 0 1
  • 此刻的我,匪坐于书案前,略享其宁静。且听门外风和雨之声,思虑万干之百转,闻乡村烟雾以瞭远。 我欲心念念已斐然,觉...
    开心_0464阅读 46评论 0 2