Search code examples
c++openglglslglm-mathcompute-shader

Invalid array values ​in compute shader?


I use a buffer to which I pass my C++ structures

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

In the shader it looks like this

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

layout(std430, binding=4) readonly buffer Octree_data {
    Node nodes[];
};

In the process of calculations, I find out that in all elements of the array (except for the first element) there are incorrect data (most likely displaced) in what could I make a mistake?


Solution

  • The std430 required alignment for your Node structure is 16-bytes. This is because it contains a 16-byte-aligned type (vec4 and ivec4). Therefore, every array element in the Node array will have to start at a 16-byte boundary. So the array stride for nodes will have to be 48.

    The C++ alignment of your Node structure is probably 4 bytes. This is because nothing in C++'s layout for your Node structure requires higher alignment. GLM's 4-element vector types are 4-byte aligned (or rather, they're float aligned, which is almost always 4 bytes). This means that the sizeof(Node) will be 44 bytes, as will the array stride.

    If you want your C++ struct to match the GLSL required layout, you need to align it properly:

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