金属内核着色器 - 淡入淡出实现

时间:2017-07-23 04:33:28

标签: metal pixel-shader

我还没有写过很多金属内核着色器;这是两个RGBX-32图像之间的一个初出茅庐的“淡入淡出”着色器,使用inBuffer1(0.0)到inBuffer2(1.0)之间的补间值0.0到1.0。

我在这里缺少什么?有些事情让我觉得这可能非常低效。

我的第一个想法是尝试使用可能更好的矢量数据类型(例如char4)进行减法和乘法,但结果肯定是未定义的(因为某些组件将为负数)

此外,使用MTLTextureMTLBuffer对象有什么好处吗?

kernel void fade_Kernel(device const uchar4  *inBuffer1  [[ buffer(0) ]],
                        device const uchar4  *inBuffer2  [[ buffer(1) ]],
                        device const float   *tween      [[ buffer(2) ]],
                        device uchar4        *outBuffer  [[ buffer(3) ]],
                        uint gid [[ thread_position_in_grid ]])
{
    const float t = tween[0];
    uchar4 pixel1 = inBuffer1[gid];
    uchar4 pixel2 = inBuffer2[gid];

    // these values will be negative
    short r=(pixel2.r-pixel1.r)*t;  
    short g=(pixel2.g-pixel1.g)*t;
    short b=(pixel2.b-pixel1.b)*t;

    outBuffer[gid]=uchar4(pixel1.r+r,pixel1.g+g,pixel1.b+b,0xff);
}

2 个答案:

答案 0 :(得分:2)

首先,您应该将tween参数声明为:

constant float &tween [[ buffer(2) ]],

使用constant地址空间更适合这样的值,对于函数的所有调用(并且不通过网格位置等索引)都是相同的。此外,将其作为引用而不是指针告诉编译器您不会将"数组中的其他元素编入索引。指针可能是。

最后,有一个mix()函数可以执行您在此处执行的计算。因此,您可以使用以下函数替换函数体:

uchar4 pixel1 = inBuffer1[gid];
uchar4 pixel2 = inBuffer2[gid];

outBuffer[gid] = uchar4(uchar3(mix(float3(pixel1.rgb), float3(pixel2.rgb), tween)), 0xff);

关于使用纹理是否更好,这在某种程度上取决于您在运行此内核后计划对结果做什么。无论如何,如果你要用它做类似纹理的东西,那么在整个过程中使用纹理可能会更好。实际上,使用混合而不是计算内核来绘制操作可能会更好。毕竟,这种混合是GPU必须始终做的事情,因此路径可能很快。您必须测试每种方法的性能。

答案 1 :(得分:0)

如果您正在处理图像,使用MTLTexture比使用MTLBuffer要高效得多。使用“一半”比“uchar”更好。我今年直接从WWDC的Apple工程师那里学到了这一点。

unmerged paths:
     deleted by them : db.sqlite3
     both modifiled : management/__pacache__/forms.cpython-35.pyc