Thread: GLFW glBufferData doesn't work with float pointers

  1. #1
    Registered User
    Join Date
    Jun 2016
    Posts
    40

    GLFW glBufferData doesn't work with float pointers

    I’ve been following this OpenGL tutorial, which uses GLFW with OpenGL 3.3. After finishing it, I changed the code so that the vertices variable is a float pointer instead of an array. Like so:

    Code:
    float* vertices = new float[9]
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    glBufferData seemed to have no problem with this change, but when I ran the program, the triangle just doesn’t get drawn. Despite the contents of the pointer being the same as the array’s.

    To fix this, I’ve tried to dereference the vertices var in the sizeof call passed to glBufferData, which is here:

    Code:
    glBufferData(GL_ARRAY_BUFFER, sizeof(*vertices), vertices, GL_STATIC_DRAW);
    When that didn’t work (also tried dereferencing vertices in the third arg), I had vertices be a float vector. Again, no dice; apparently, glBufferData will only work with non-pointer float arrays.

    I then tried to loop through the float pointer to pass its contents to an array. Couldn't even initialize the array to do that, since C++ doesn’t allow variable-sized arrays without some fancy extension.

    I’m at my wit’s end ^^; Am I going to have to use arrays with hard-coded lengths, or is there a way to make float pointers work with glBufferData?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Sizeof on a pointer doesn't tell you how much data it points to.
    Code:
    $ cat foo.cpp
    #include <iostream>
    using namespace std;
    
    int main()
    {
        float* vertices = new float[9]
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
        cout << "Surprise=" << sizeof(*vertices) << endl;
        return 0;
    }
    $ g++ -std=c++11 foo.cpp
    $ ./a.out 
    Surprise=4
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Guest
    Guest
    Notice how he tutorial allocates the array on the stack?
    Code:
    float vertices[] = { // no new
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    Only then will sizeof be aware of the number of bytes in the array. Keep things simple for now!

  4. #4
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    Quote Originally Posted by Salem View Post
    Sizeof on a pointer doesn't tell you how much data it points to.
    <code example dereferencing the pointer>
    As I mentioned in the OP, I already tried dereferencing the pointer. Didn't work.

    Quote Originally Posted by Guest View Post
    Notice how the tutorial allocates the array on the stack?
    <code example>
    Only then will sizeof be aware of the number of bytes in the array. Keep things simple for now!
    So basically, glBufferData only works with regular arrays with hard-coded lengths?

  5. #5
    Guest
    Guest
    The reason your example fails is that the sizeof operator cannot deduce the total size of heap allocated memory, as Salem pointed out. That information is lost forever unless you track it with a separate variable; that's just how C/C++ works.

    You can invoke glBufferData with any contiguous array of data, as long as you pass it the appropriate parameters. For instance you could use containers that track their own size:
    Code:
    #include <array>
    #include <vector>
    
    const array<float, 9> a_verts {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    glBufferData(GL_ARRAY_BUFFER, a_verts.size() * sizeof(float), a_verts.data(), GL_STATIC_DRAW); // .size() * sizeof(float) == 9 * 4 bytes
    
    const vector<float> v_verts {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    glBufferData(GL_ARRAY_BUFFER, v_verts.size() * sizeof(float), v_verts.data(), GL_STATIC_DRAW);

  6. #6
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    So basically, if my data collection is on the stack, I pass it to sizeof as the size argument, since sizeof can work with that.

    If it's on the heap, I have to pass the combined amount of space each member takes up. If each item takes up the exact same amount of space (like when they're all floats), I pass the size of a float multiplied by the item count. Otherwise, I'll have to go through each item one by one, accumulating their combined sizes to get the right number to pass. Though, this second approach would still work for when each item takes up the same amount of space.

    Did I get it right?
    Last edited by Tesp; 05-26-2018 at 08:52 AM.

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Sort of, except for the fundamental problem of not knowing what sizeof is actually capable of doing.

    For example, sizeof has nothing to do with scope.
    Code:
    float vertices[] = { // no new
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    // This is fine
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    // This is broken
    float *pVertices = vertices;
    glBufferData(GL_ARRAY_BUFFER, sizeof(*pVertices), pVertices, GL_STATIC_DRAW);
    It has NOTHING to do with the scope of pVertices, or whether pVertices points to a local array or some block of heap memory.

    You would also run into the same problem if you passed the array (in either incarnation) from one function to another function, before passing it onto glBufferData.


    These on the other hand would work in both cases.
    Code:
    float vertices[] = { // no new
        -0.5f, -0.5f, 0.0f,
         0.5f, -0.5f, 0.0f,
         0.0f,  0.5f, 0.0f
    };
    // This is fine
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices[0]) * 9, vertices, GL_STATIC_DRAW);
    
    // This is fine too :)
    float *pVertices = vertices;
    glBufferData(GL_ARRAY_BUFFER, sizeof(pVertices[0]) * 9, pVertices, GL_STATIC_DRAW);

    But as Guest demonstrates, there are better C++ ways of creating array like objects.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    So what you're saying is that if I want sizeof to work with a pointer to a collection, I need to use the pointer to pass a single element of said collection. One way is to dereference the pointer and index the dereferenced collection, as your example showed.

    The indexing approach (where possible) would also work with non-pointer vars for collections, though in that case, I could simply pass the non-pointer var without having to keep track of how much stuff it has.

    I figured out that last bit by making a non-pointer vector of floats with the verts, passing it to sizeof (with no indices or multiplication), and seeing what happened.

    Code:
    vector<float> vecVertices = 
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    // The triangle was drawn fine with this.
    glBufferData(GL_ARRAY_BUFFER, sizeof(vecVertices), vecVertices.data(), GL_STATIC_DRAW);
    Am I at least getting warmer? xD Sorry if I'm being slow to understand.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    By itself, sizeof is insufficient when you have pointers. It will tell you how big an element is, but you need to maintain a separate count of the total number of elements.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    Yes, I understood that part. Is there anything else?

  11. #11
    Guest
    Guest
    Quote Originally Posted by Tesp View Post
    Code:
    vector<float> vecVertices = 
    {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    
    // The triangle was drawn fine with this.
    glBufferData(GL_ARRAY_BUFFER, sizeof(vecVertices), vecVertices.data(), GL_STATIC_DRAW);
    Careful! If this rendered fine, you got lucky. Consider:
    Code:
    vector<char> vchar_small {'a', 'b', 'c'};
    vector<char> vchar_big {'a', 'b', 'c', 'd', 'e', 'f'};
    vector<float> vfloat {1.0, 2.0, 3.0, 4.0, 5.0};
    vector<double> vdouble {1.0, 2.0, 3.0, 4.0, 5.0};
    
    cout << "vchar_small: " << sizeof(vchar_small) << "\n"
            "vchar_big: " << sizeof(vchar_big) << "\n"
            "vfloat: " << sizeof(vfloat) << "\n"
            "vdouble: " << sizeof(vdouble) << endl;
    Look at the output this gives you.

  12. #12
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    Those all gave me 16. And when I tried to store their actual sizes in vars, I got this:

    vCharSmallSize: 3
    vCharBigSize: 6
    vFloatSize: 20
    vDoubleSize: 40
    Since chars take up one byte each, floats take up four bytes each, and doubles take up eight bytes each, this is the actual correct output. Which means that passing whole non-regular-array containers to sizeOf only gives you the size of the container itself (without taking into account its contents).

    I see how that's a problem ^^; All right, scratch the part where non-pointer containers are safe to simply pass to sizeof in this scenario; that only applies to regular non-pointer arrays.

  13. #13
    Guest
    Guest
    Exactly!

  14. #14
    Registered User
    Join Date
    Jun 2016
    Posts
    40
    Glad I finally got it! ^_^

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Float doesn't seem to be working?
    By SoLDMG in forum C Programming
    Replies: 7
    Last Post: 07-05-2016, 05:47 PM
  2. Replies: 1
    Last Post: 12-07-2010, 06:53 AM
  3. Supposed to return float but doesn't.
    By bliss in forum C++ Programming
    Replies: 6
    Last Post: 05-18-2005, 12:49 PM
  4. my function doesn't work! it should work
    By Unregistered in forum C Programming
    Replies: 13
    Last Post: 05-02-2002, 02:53 PM
  5. can't work out float???
    By Wiz_Nil in forum C++ Programming
    Replies: 3
    Last Post: 02-19-2002, 09:52 AM

Tags for this Thread