在Apples Metal框架

时间:2016-02-15 17:54:02

标签: ios c++11 metal compute-shader memory-layout

我正在玩Metal for iOS制作一款小游戏。在我的一个内核着色器中(在我的.metal文件中)。我正在定义一个结构来保存游戏部分的一些元数据。

结构看起来像这样:

struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float degradationRate;
};

这很好用,但是当我尝试在我的struc中添加更多字段时,例如:

struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float4 threshholdColor;
    float degradationRate;
};

代码行为不端,似乎无法使用某些字段。此时,未使用新字段。我的第一个想法是它与结构的内存对齐有关。我的印象是编译器会添加正确的填充但仍然继续并尝试自己正确地对齐结构的大小(按降序排列字段并将结构对齐到48和64字节),但没有任何成功。我也尝试使用打包数据类型来避免对齐问题,但仍然没有成功。

我知道逻辑是正确的,因为我在不使用结构的情况下编写了相同的逻辑,然后将其移植到使用结构来保存具有完全相同行为的数据。但是在这一点上添加任何字段都会破坏它。此外,保留原始结构但使用压缩数据类型也会以类似的方式打破它。

struct ColorSetup {
    packed_float4 color;
    packed_float4 degradationColor;
    float degradationRate;
};

所以这看起来肯定像是一个内存布局问题,但我不清楚如何在不解决问题的情况下解决它。

我可以尝试任何想法或想法吗?

编辑:

数据不会通过MTLBuffer传递到我的计算着色器中,而只是在.metal文件中内联的常量内存空间中定义:

constant ColorSetup redColor = {
    .color = red,
    .degradationColor = white,
    .degradationRate = 0.0035
};

编辑2:

尝试描述一些更多的发现以及代码实际上在做什么。

有问题的函数是一种假设根据此结构中提供的值淡化颜色的方法。

float4 degrade(float4 color, ColorSetup colorSetup, ColorLimit colorLimit) {
    float4 targetColor = colorSetup.degradationColor;
    float rate = colorSetup.degradationRate;
    if (colorLimit.degradationThreshold.r < color.r && colorLimit.degradationThreshold.g < color.g && colorLimit.degradationThreshold.b < color.b) {
        targetColor = colorSetup.degradationColor;
    } else {
        targetColor = colorSetup.color;
    }

    int r = (color.r - targetColor.r) < 0 ? 1 : -1;
    int g = (color.g - targetColor.g) < 0 ? 1 : -1;
    int b = (color.b - targetColor.b) < 0 ? 1 : -1;
    float4 newColor = float4(color.r + float(r)*rate, color.g + float(g)*rate, color.b + float(b)*rate, 1);
    return normalizeColor(newColor);
}

当我将结构定义为:

时,此函数按预期工作
struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float degradationRate;
};

如果我给它添加一个浮点数(即使我没有在任何地方读取它并且它不是任何计算的一部分。这只是为了试图找出错误的位置)。

struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float degradationRate;
    float padding;
};

此时,如果我没有在构造中指定新的float,它仍然可以正常工作。

constant ColorSetup redColor = {
    .color = red,
    .degradationColor = white,
    .degradationRate = 0.0035,
};

但如果我这样做:

constant ColorSetup redColor = {
    .color = red,
    .degradationColor = white,
    .degradationRate = 0.0035,
    .padding = 0
};

上面指定的功能停止工作,颜色不再褪色。

另一个有趣的观察是,如果我使用int而不是一切正常:

struct ColorSetup {
    float4 color;
    float4 degradationColor;
    float degradationRate;
    int padding;
};

0 个答案:

没有答案