Определение структур в каркасе "Яблоки"

Я играю с Metal для 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;
};

На этом этапе все еще работает просто отлично, если я не укажу новый 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 ответов

Другие вопросы по тегам