计算着色器中的数组值无效?

0 c++ opengl glsl compute-shader glm-math

我使用一个缓冲区来传递我的 C++ 结构

struct Node {
    Node(int size, glm::ivec3 position);

    bool isEmpty();
    int getSubIndex(const glm::ivec3& vec);
    void divide(std::vector<Node> &nodes);
    void setColor(glm::vec4 color);
    int getSubNodeIndex(const glm::ivec3& vec);
    int getSubNodeIndex(int subIndex);

    glm::ivec4 position;
    glm::vec4 color;
    int halfSize;
    int sub;
    int leaf;
};
Run Code Online (Sandbox Code Playgroud)

在着色器中看起来像这样

struct Node {
    vec4 position;
    vec4 color;
    int data[3];
};

layout(std430, binding=4) readonly buffer Octree_data {
    Node nodes[];
};
Run Code Online (Sandbox Code Playgroud)

在计算过程中,我发现数组的所有元素(除了第一个元素)都有不正确的数据(很可能是移位的),我会犯什么错误?

Nic*_*las 5

std430您的结构所需的对齐方式是Node16 字节。这是因为它包含 16 字节对齐类型 (vec4ivec4)。因此,Node数组中的每个数组元素都必须从 16 字节边界开始。因此数组步幅nodes必须为 48。

您的结构的 C++ 对齐方式Node可能是 4 个字节。这是因为C++ 的结构布局中没有任何内容Node需要更高的对齐度。GLM 的 4 元素向量类型是 4 字节对齐的(或者更确切地说,它们是float对齐的,几乎总是 4 字节)。这意味着sizeof(Node)将是 44 个字节,数组步幅也是 44 个字节。

如果您希望 C++ 结构体匹配 GLSL 所需的布局,则需要正确对齐它:

struct Node {
    Node(int size, glm::ivec3 position);

    bool isEmpty();
    int getSubIndex(const glm::ivec3& vec);
    void divide(std::vector<Node> &nodes);
    void setColor(glm::vec4 color);
    int getSubNodeIndex(const glm::ivec3& vec);
    int getSubNodeIndex(int subIndex);

    alignas(16) glm::ivec4 position;
    alignas(16) glm::vec4 color;
    int halfSize;
    int sub;
    int leaf;
};
Run Code Online (Sandbox Code Playgroud)