1

I created a shader storage buffer object to give information to my vertex shader. It is bound to a buffer containing a single structure. But there is a problem. The data I keep in this structure is not a simple array, it's a std::vector.

Here is the structure :

typedef struct {
    glm::mat4 modelMatrix;
} entityInfo;

typedef struct {
    std::vector<entityInfo> entityInfoBuffer;
} shaderData;

mat4 is just a simple 4x4 float matrix.

If I give this to OpenGL, the data transmitted to the GPU will be just a bunch of pointers and info about the matrix/vector, and not the data in them.

One solution would be to create a structure only for OpenGL:

typedef struct {
    float* modelMatrix;
} SSBOentityInfo;

typedef struct {
    SSBOentityInfo* entityInfoBuffer;
} SSBOshaderData;

But I would have to copy eeeeevery pointer corresponding to the data of the containers.

Is there a better way to do it?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Talesseed
  • 191
  • 1
  • 11
  • Wouldn't you want to just send the contents of `entityInfoBuffer` to the GPU? You don't want to be copying CPU pointers to the GPU, they won't mean anything to the GPU (you might as well be copying random numbers). – user253751 Jul 27 '16 at 22:46
  • I think that, when using a shader storage buffer object, you have to use structs ? I am wrong ? That would mean I would have to set `entityInfoBuffer.data()` to the SSBOshaderData `entityInfoBuffer` ? Also, OpenGL will only be able to read `&mat4[0][0]`. – Talesseed Jul 27 '16 at 23:08
  • @Talesseed: "*you have to use structs ?*" Why? Data is data, memory is memory, and buffer objects are buffer objects. – Nicol Bolas Jul 27 '16 at 23:47
  • Yes, my bad... I just want to use structs to be able to add elements that I may need after. – Talesseed Jul 27 '16 at 23:55

1 Answers1

4

glm::mat4 is, for all intents and purposes, an array of 16 floats. Not a pointer to 16 floats, an actual float[16] array. 16 floats, one after the other.

Therefore, a vector<glm::mat4> manages a contiguous array of elements, where each element is 16 floats. It is that data that you want to store in your buffer object. So... do that.

vector manages a contiguous array of data, so it's perfectly legal to get a pointer to this array. That's what vector.data() is for. So that's the source pointer you give to glBufferSubData or whatever. The size would be the number of elements in the array (vector.size()) times the size of each element as computed by sizeof.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks, I though that mat4 wasn't an array. However, what can I do if I want to use structs to be able to add elements later on ? – Talesseed Jul 27 '16 at 23:57
  • @Talesseed: It's not clear what you mean by that, but I'm pretty sure that's a different question from the one you asked here. – Nicol Bolas Jul 28 '16 at 00:03
  • I wanted to add more members to shaderData. But yes, I think that is another question. – Talesseed Jul 28 '16 at 00:11
  • And for the typedef, the second awnser explains that the absence of typedef can lead to a bug (http://stackoverflow.com/questions/612328/difference-between-struct-and-typedef-struct-in-c) – Talesseed Jul 28 '16 at 00:12
  • @Talesseed: That's what *namespaces* are for. Also, it's a bug so rare that most dedicated C++ programmers don't even know its a possibility. – Nicol Bolas Jul 28 '16 at 00:16