首页 > 解决方案 > 对齐 SSBO 的内存,即包含数组的结构数组?

问题描述

我正在展平八叉树并使用 SSBO 将其发送到我的片段着色器,我相信我遇到了一些内存对齐问题。我正在使用std430布局并将体素向量绑定到这个 SSBO,这是我的着色器中的结构。我正在使用 GLSL 4.3 仅供参考

struct Voxel
{
    bool data;   // 4
    vec4 pos;    // 16
    vec4 col;    // 16
    float size;  // 4
    int index;   // 4
    int pIndex;  // 4
    int cIdx[8]; // 4, 16 or 32 bytes?
};

layout (std430, binding=2) buffer octreeData
{
    Voxel voxels[];
};

我不是 100% 确定,但我认为我在使用int cIdx[8]结构内部的数组时遇到了问题,查看规范(第 124 页,第 7.6 节)

  1. 如果成员是标量或向量数组,则根据规则 (1)、(2) 和 (3) 设置基本对齐方式和数组跨度以匹配单个数组元素的基本对齐方式,并向上取整为vec4 的基本对齐方式。数组末尾可能有填充;数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。

我不完全确定对齐是什么,我知道 vec4 占用 16 个字节的内存,但我的数组有多少?如果只是sizeof(int)*832,但它说它被设置为单个数组元素的大小,然后四舍五入到 vec4 对吗?那么这是否意味着我的 cIdx 数组具有 16 个字节的基本对齐方式?没有后续成员,所以是否有填充添加到我的结构中?

所以总结构内存 = 52 个字节(如果我们只为 cIdx 分配 4 个字节),这是否意味着我需要添加 12 个字节的填充,这可能会导致我出现问题?如果它分配 16 个字节,那么结构总共是 64 个字节,并且没有内存对齐问题吗?

我对应的c++结构

struct Voxel
{
    bool data;
    glm::vec4 pos;
    glm::vec4 col;
    float size;
    int index;
    int pIndex;
    int cIdx[8];
};

然后我填写我的std::vector<Voxel>并将它传递给我的着色器,就像这样

 glGenBuffers(1, &octreeSSBO);
 glBindBuffer(GL_SHADER_STORAGE_BUFFER, octreeSSBO);
 glBufferData(GL_SHADER_STORAGE_BUFFER, voxelData.size()*sizeof(Voxel), voxelData.data(), GL_DYNAMIC_DRAW);
 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, octreeSSBO);

直接从voxelData向量中读取,我可以确认数据被正确填充,我什至可以偶尔看到数据被传递给着色器,但与我期望看到的值相比表现不正确我'米看着。

看起来这里有内存对齐问题吗?

标签: c++arraysopenglmemorygpu

解决方案


我不完全确定对齐方式是什么

该规范非常清楚事物的基本对齐方式。您的问题不在第 4 项中(std430无论如何都不会进行第 4 项中指定的舍入)。

你的问题在#2:

如果成员是一个二元或四元向量,其分量消耗 N 个基本机器单元,则基本对齐分别为 2N 或 4N。

在 GLSL 中,vec4基本对齐为 16。这意味着任何vec4 必须在 16 字节边界上分配。

pos必须在 16 字节的边界上。但是,data只有4个字节。因此,必须在 和 之间插入 12 个字节的填充datapos以满足 std430 的对齐要求。

但是,glm::vec4C++ 对齐为 4。因此 C++ 编译器不会data在和之间插入一堆填充pos。因此,两种语言中的类型不一致。

alignas您应该使用 C++11 的关键字显式对齐 C++ 结构中要匹配 GLSL 的所有 GLM 向量:

struct Voxel
{
    bool data;
    alignas(16) glm::vec4 pos;
    alignas(16) glm::vec4 col;
    float size;
    int index;
    int pIndex;
    int cIdx[8];
};

另外,我不会假设 C++ 类型bool和 GLSL 类型bool具有相同的大小。


推荐阅读