5

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

结构如下所示:

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

这工作得很好,但是当我尝试向我的结构添加更多字段时,例如:

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;
};

在这一点上,如果我没有在构造中指定新的浮点数,它仍然可以正常工作。

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;
};
4

0 回答 0