0

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?

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • An array is not the same as three distinct variables. If you want to have an array of integers in the shader, you must have the corresponding array in the C++ code. – Some programmer dude Mar 02 '22 at 17:16
  • As for the likely reason, see [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) – Some programmer dude Mar 02 '22 at 17:17
  • I tried the option with three different int variables, there is the same result =( sizeof(Node) outputs 44 – Kirill Gurevich Mar 02 '22 at 17:20
  • I found out that each variable in my shader takes up 16 bytes, for a total of 80, while my C++ structure is only 44, how to correctly load the data? – Kirill Gurevich Mar 02 '22 at 17:53
  • @KirillGurevich: "*I found out that each variable in my shader takes up 16 bytes, for a total of 80*" How did you find this out? `std430` layout doesn't say that. – Nicol Bolas Mar 02 '22 at 17:57
  • I used glGetActiveUniformBlockiv – Kirill Gurevich Mar 02 '22 at 18:17

1 Answers1

5

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;
};
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982