Выравнивание памяти элемента массива C++

Привет, я пытался дать шейдеру массив, например, точечных положений света. Но этот шейдер хочет, чтобы vec3 были выровнены по 16 байтам, а не по 12 байтам от glm. Для одного vec3 проблем не было, можно было просто поставить перед ним "alignas(16)". Но для массива С++ просто считает, что весь массив должен быть выровнен по 16, а не его отдельные элементы.

struct Scene {
   alignas(16) glm::vec3 lights[2];
};

int main() {
  Scene scene;
  scene.lights[0] = { 1,2,3 };
  scene.lights[1] = { 4,5,6 };
}

Я также просмотрел отладчик памяти в Visual Studio, и байты просто плотно упакованы без каких-либо дополнений.

Скриншот отладчика памяти Visual Studio

Единственное решение, которое я могу придумать, это одно: изменить исходный код glm на выравнивание 16 (что не очень хорошая идея)

два: создать новую структуру типа "16ByteAlignedVec3" , содержащую vec3, и установить для этой структуры выравнивание 16. А затем использовать это как тип массива.

и третий: использование указателя для доступа к данным массива и увеличение его на 16 байт, если вы хотите получить доступ, например, к индексу 1.

🤔 А знаете ли вы, что...
Язык C++ активно применяется в разработке приложений для научных вычислений и искусственного интеллекта.


364
1

Ответ:

Решено

Но для массива С++ просто считает, что весь массив должен быть выровнен по 16, а не его отдельные элементы.

Действительно. Вот что означает указание alignas для массива. Выравнивание массива затронуто; не выравнивание элементов.

два: создать новую структуру типа "16ByteAlignedVec3", которая содержит vec3, и установить для этой структуры выравнивание 16

Это разумный подход. Вы можете заставить класс вести себя так же, как если бы он был glm::vec3, используя наследование вместо члена:

struct Scene {
    struct alignas(16) 16ByteAlignedVec3 : glm::vec3 {};
    aligned_vec3 lights[2];
};