本文主要记录几种在工作中遇到的由于Metal Shading Language兼容导致的问题。
一、请一定动态方式创建Shader Library
系统提供了两种方式创建shader library:
/*! @method newLibraryWithFile: @abstract Load a MTLLibrary from a metallib file. */ - (nullable id <MTLLibrary>)newLibraryWithFile:(NSString *)filepath error:(__autoreleasing NSError **)error;
- (nullable id <MTLLibrary>)newLibraryWithSource:(NSString *)source options:(nullable MTLCompileOptions *)options error:(__autoreleasing NSError **)error;
在项目中我最初也由于想当然的认为苹果的兼容性比较好,只要Metal Shading Language使用的版本一致,满足系统版本要求,不会有兼容问题,使用了提前由Xcode编译好的.metallib文件创建MTLLibrary,但被事实打脸。所以在此建议大家使用源码在目标机上运行创建MTLLibrary。
二、使用源码在目标机器上运行时进行编译创建MTLLibrary,其编译对C/C++语法要求更严格。
2.1 在Xcode中编译的.metal源码中我们可以这样定义一个全局变量:
static constant float3x3 Primaries2020to709 = { float3(1.66049623f, -0.58765644f, -0.07283977f), float3(-0.12454709f, 1.13289511f, -0.00834801f), float3(-0.01815368f, -0.10059737f, 1.11875105f) };
但是如果你把这个定义使用源码在运行时进行编译创建MTLLibrary会得到如下错误:
编译器找不到这种创建float3x3矩阵的构造器,但是使用Xcode编译时,能编译过。因此只能更改为如下方式:
static constant float3x3 Primaries2020to709 = { 1.66049623f, -0.58765644f, -0.07283977f, -0.12454709f, 1.13289511f, -0.00834801f, -0.01815368f, -0.10059737f, 1.11875105f };
2.2 我们知道在Objective-C文件中,可以不用声明方法/函数,就可以在一个方法定义中使用另一个方法,使用Xcode编译.metal源码也是一样,如下代码是可以编译通过的:
float4 convert_hdr_yuv_to_rgba_for_edr(float3 yuv, /* 其它参数,为防泄密不放出来 */) { ....... return hdrrgba; } float4 deal_with_sampled_yuv(float3 yuv, float2 textureCoordinate, /* 其它参数,为防泄密不放出来 */) { ...... float4 hdr = convert_hdr_yuv_to_rgba_for_edr(yuv, /* 其它参数,为防泄密不放出来 */); return hdr; }
但当使用Metal Shader源码在目标机器上创建MTLLibrary时会出现如下错误:
解决办法是:
我的解决办法是定义为inline函数。
三、最后是一个系统及设备(2016版本Macbook + 10.11.6系统)出现的一个匪夷所思的问题:设备上渲染出来后无彩色,画面全部黑白的问题。
涉及目前公司项目原因,略去求证解决过程直接上结果
在Metal Shading Language Specification中关于saturate函数的说明如下
saturate就是将输入裁剪限定在0.0到1.0的一个闭区间(如果输入小于0.0,则输出0; 如果输入大于1.0,则输出1.0)。并且此方法是一个模板方法,如果输入一个数组,则会对数组的每一个元素做[0,0 1.0]的裁剪。但是很遗憾的是我们在2016版Macbook + macOS 10.11.6系统上发现,将rgba数组用saturate处理后,输出的数组各分量的值完全相等了,因此我们会得到一张黑白的画面。
这真的是一个很让人不敢怀疑的问题,最后二分法回退git提交,一步步回退代码,验证发现确实是苹果的这样一个基础的方法出了BUG,简直如同绝对值函数给你返回一个负数一样不可思议。
解决方法很简单,不要用saturate处理容器,只用来处理单个的数了??
Metal渲染:Metal Shading Language兼容性问题
原文:https://www.cnblogs.com/csutanyu/p/12830151.html