设为首页 加入收藏

TOP

资深程序员的Metal入门教程总结(二)
2019-09-17 17:35:12 】 浏览:69
Tags:资深 程序员 Metal 入门教程 总结
up 指的是设定的处理单元,这个值要根据具体的设备进行区别,但必须是足够小的,能让GPU执行; threadgroupCount 是需要处理的次数,一般来说threadgroupCount*threadgroup=需要处理的大小。

性能相关

临时对象(创建和销毁是廉价的,它们的创建方法都返回 autoreleased对象) 1.Command Buffers 2.Command Encoders 代码中不需要持有。

高消耗对象(在性能相关的代码里应该尽量重用它,避免反复创建) 1.Command Queues 2.Buffers 3.Textures 5.Compute States 6.Render Pipeline States 代码中需长期持有。

Metal常用的四种数据类型:half、float、short(ushort)、int(uint)。 GPU的寄存器是16位,half是性能消耗最低的数据类型;float需要两次读取、消耗两倍的寄存器空间、两倍的带宽、两倍的电量。 为了提升性能,half和float之间的转换由硬件来完成,不占用任何开销。 同时,Metal自带的函数都是经过优化的。 在float和half数据类型混合的计算中,为了保持精度会自动将half转成float来处理,所以如果想用half节省开销的话,要避免和float混用。 Metal同样不擅长处理control flow,应该尽可能使用使用三元表达式,取代简单的if判断。

此部分参考自WWDC

img

常见的图形渲染管道

二、Metal Shader Language

Metal Shader Language的使用场景有两个,分别是图形渲染和通用计算;基于C++ 14,运行在GPU上,GPU的特点:带宽大,并行处理,内存小,对条件语句处理较慢(等待时间长)。 Metal着色语言使用clang和 LLVM,支持重载函数,但不支持图形渲染和通用计算入口函数的重载、递归函数调用、new和delete操作符、虚函数、异常处理、函数指针等,也不能用C++ 11的标准库。

基本函数

shader有三个基本函数:

  • 顶点函数(vertex),对每个顶点进行处理,生成数据并输出到绘制管线;
  • 像素函数(fragment),对光栅化后的每个像素点进行处理,生成数据并输出到绘制管线;
  • 通用计算函数(kernel),是并行计算的函数,其返回值类型必须为void;

顶点函数相关的修饰符:

  • [[vertex_id]] vertex_id是顶点shader每次处理的index,用于定位当前的顶点
  • [[instance_id]] instance_id是单个实例多次渲染时,用于表明当前索引;
  • [[clip_distance]],float 或者 float[n], n必须是编译时常量;
  • [[point_size]],float;
  • [[position]],float4;

如果一个顶点函数的返回值不是void,那么返回值必须包含顶点位置; 如果返回值是float4,默认表示位置,可以不带[[ position ]]修饰符; 如果一个顶点函数的返回值是结构体,那么结构体必须包含“[[ position ]]”修饰的变量。

像素函数相关的修饰符:

  • [[color(m)]] float或half等,m必须是编译时常量,表示输入值从一个颜色attachment中读取,m用于指定从哪个颜色attachment中读取;
  • [[front_facing]] bool,如果像素所属片元是正面则为true;
  • [[point_coord]] float2,表示点图元的位置,取值范围是0.0到1.0;
  • [[position]] float4,表示像素对应的窗口相对坐标(x, y, z, 1/w);
  • [[sample_id]] uint,The sample number of the sample currently being processed.
  • [[sample_mask]] uint,The set of samples covered by the primitive generating the fragmentduring multisample rasterization.

以上都是输入相关的描述符。像素函数的返回值是单个像素的输出,包括一个或是多个渲染结果颜色值,一个深度值,还有一个sample遮罩,对应的输出描述符是[[color(m)]] floatn、[[depth(depth_qualifier)]] float、[[sample_mask]] uint。

struct LYFragmentOutput {
    // color attachment 0
    float4 color_float [[color(0)]];// color attachment 1
    int4 color_int4 [[color(1)]];// color attachment 2
    uint4 color_uint4 [[color(2)]];};
fragment LYFragmentOutput fragment_shader( ... ) { ... };

需要注意,颜色attachment的参数设置要和像素函数的输入和输出的数据类型匹配。

Metal支持一个功能,叫做前置深度测试(early depth testing),允许在像素着色器运行之前运行深度测试。如果一个像素被覆盖,则会放弃渲染。使用方式是在fragment关键字前面加上[[early_fragment_tests]]: [[early_fragment_tests]] fragment float4 samplingShader(..) 使用前置深度测试的要求是不能在fragment shader对深度进行写操作。 深度测试还不熟悉的,可以看LearnOpenGL关于深度测试的介绍

参数的地址空间选择

Metal种的内存访问主要有两种方式:Device模式和Constant模式,由代码中显式指定。 Device模式是比较通用的访问模式,使用限制比较少,而Constant模式是为了多次读取而设计的快速访问只读模式,通过Constant内存模式访问的参数的数据的字节数量是固定的,特点总结为:

  • Device支持读写,并且没有size的限制;
  • Constant是只读,并且限定大小;

如何选择Device和Constant模式? 先看数据size是否会变化,再看访问的频率高低,只有那些固定size且经常访问的部分适合使用constant模式,其他的均用Device。

// Metal关键函数用到的指针参数要用地址空间修饰符(device, threadgroup, or constant) 如下
vertex RasterizerData // 返回给片元着色器的结构体
vertexShader(uint vertexID [[ vertex_id ]], // vertex_id是顶点shader每次处理的index,用于定位当前的顶点
             constant LYVertex *vertexArray [[ buffer(0) ]]); // buffer表明是缓存数据,0是索引

img

地址空间的修饰符共有四个,device、threadgroup、constant、thread。 顶点函数(vertex)、像素函数(fragment)、通用计算函数(

首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇架构演化 下一篇[转载]单点登录SSO:概述与示例

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目