Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 53

Thread: Bindless Stuff

Hybrid View

  1. #1
    Senior Member OpenGL Guru
    Join Date
    Dec 2000
    Location
    Reutlingen, Germany
    Posts
    2,052

    Bindless Stuff

    So i tried this magical NV_vertex_buffer_unified_memory because i want my app to run 7.5x faster.

    All i can produce is hard crashes, though.

    So, i reduced it to the case of binding only the index-array via bindless-stuff and leave the vertex-data array as is, for now. Still, i can't get it to run.

    This is the code, to setup the data:

    int iIndexDataSize = iIndices * sizeof (short);
    glGenBuffers (1, &IndexBufferID);
    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
    glBufferData (GL_ELEMENT_ARRAY_BUFFER, iIndexDataSize, (void*) &pIndices[0], GL_STATIC_DRAW);
    glGetBufferParameterui64vNV (GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_GPU_ADDRESS_NV, &ptrIndexArray);
    glMakeBufferResidentNV (GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);

    And this is the code to bind the buffer at runtime:

    if (UseBindless) {
    glEnableClientState (GL_ELEMENT_ARRAY_UNIFIED_NV);
    glBufferAddressRangeNV (GL_ELEMENT_ARRAY_ADDRESS_NV, 0, ptrIndexArray, iIndexDataSize);
    }
    else
    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);

    If i understand the "documentation" (which is very shallow IMO) correctly, that should be it, and nothing else is necessary.

    However, it just crashes all the time. Any ideas?

    Thanks,
    Jan.
    GLIM - Immediate Mode Emulation for GL3

  2. #2
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,714

    Re: Bindless Stuff

    If i understand the "documentation" (which is very shallow IMO) correctly, that should be it, and nothing else is necessary.
    You might want to use these functions:

    Code :
        void VertexFormatNV(int size, enum type, sizei stride);
        void NormalFormatNV(enum type, sizei stride);
        void ColorFormatNV(int size, enum type, sizei stride);
        void IndexFormatNV(enum type, sizei stride);
        void TexCoordFormatNV(int size, enum type, sizei stride);
        void EdgeFlagFormatNV(sizei stride);
        void SecondaryColorFormatNV(int size, enum type, sizei stride);
        void FogCoordFormatNV(enum type, sizei stride);
        void VertexAttribFormatNV(uint index, int size, enum type,
                                  boolean normalized, sizei stride);
        void VertexAttribIFormatNV(uint index, int size, enum type,
                                   sizei stride);

  3. #3
    Senior Member OpenGL Guru
    Join Date
    Dec 2000
    Location
    Reutlingen, Germany
    Posts
    2,052

    Re: Bindless Stuff

    Yes, for vertex-data! But i am currently only trying it out with index-data. And since even that does not work, i'd like some more information.

    Jan.
    GLIM - Immediate Mode Emulation for GL3

  4. #4
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,714

    Re: Bindless Stuff

    From the spec:

    Quote Originally Posted by the spec
    It is not possible to mix vertex or attrib arrays sourced from GPU
    addresses with either vertex or attrib arrays in client memory or
    specified with classic VBO bindings.
    If they prohibit mixing and matching VBOs with bindless for attributes, there's a good chance that they're not too keen on mixing and matching VBO attributes with bindless elements. Though it'd be nice if they actually said something about it.

  5. #5
    Senior Member OpenGL Guru
    Join Date
    Dec 2000
    Location
    Reutlingen, Germany
    Posts
    2,052

    Re: Bindless Stuff

    Hmmm, but it talks about old-style vertex-arrays (GL_COLOR_ARRAY, etc.) and new-style (generic vertex-attribs) and stuff in client memory (RAM) and other stuff in GPU memory. As i interpret it, it does not say anything about index-arrays and vertex-arrays.

    Both my index and vertex data is in a VBO. And since there are two states to enable (glEnableClientState (GL_ELEMENT_ARRAY_UNIFIED_NV) and glEnableClientState (GL_ATTRIB_ARRAY_UNIFIED_NV)) i would guess you can mix&match at least that.

    I will try using bindless stuff for both, tomorrow, but from how i understand the spec, only binding index or vertex arrays with it should be possible.

    Jan.
    GLIM - Immediate Mode Emulation for GL3

  6. #6
    Advanced Member Frequent Contributor Aleksandar's Avatar
    Join Date
    Jul 2009
    Posts
    943

    Re: Bindless Stuff

    The specification is pretty straight forward. There are no ambiguities out there. Before start complaining on extension try to find error in your code. Maybe the tutorial (http://developer.download.nvidia.com...s_graphics.pdf) would help you.

    I have implemented bindles with both fixed functionality and shaders, and it works perfectly.

    I'll try to summarize the most important things:

    1. Set Bindless vertex formats
    (glVertexFormatNV, glNormalFormatNV, glTexCoordFormatNV, etc for fixed functionality or glVertexAttribFormatNV for generic attributes)

    2. Enable adequate client states (GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV - for vertex arrays, and
    GL_ELEMENT_ARRAY_UNIFIED_NV - for index arrays)


    3. Create VBOs, grab the pointers and make them resident
    - glBufferData
    - glGetBufferParameterui64vNV
    - glMakeBufferResidentNV


    4. Enable vertex attributes and set address range for the pointers
    - glEnableVertexAttribArray
    - glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDR ESS_NV,...) - for attributes and
    - glBufferAddressRangeNV(GL_ELEMENT_ARRAY_ADDRESS_NV , ...) - for index


    5. Finally, draw your VBOs!!!

    It isn't so complicated, is it?

  7. #7
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: Bindless Stuff

    Quote Originally Posted by Jan
    So i tried this magical NV_vertex_buffer_unified_memory because i want my app to run 7.5x faster.
    Yeah , on contrived cases.

    2X is all I've gotten on real use cases, which ain't shabby at all!

    So, i reduced it to the case of binding only the index-array via bindless-stuff and leave the vertex-data array as is, for now.
    I personally have never tried mixing bindless and "classic" VBOs in the same batch (to use language from the extension), though I agree the presence of separate enables would otherwise imply that you should be able to do this. At the same time, the extension basically states that they don't want to support mixing "bindless" with "classic" VBOs (see Question #4) -- the goal of the extension being reducing batch overhead, and that would just increase it. But this permutation isn't spelled out exactly.

    (terminology: "Bindless VBOs" being VBOs set up by GPU address, and "classic VBOs" being VBOs set up by buffer handle).

    Still, i can't get it to run....Any ideas?
    Nothing immediately obvious. It may be your mixing of "bindless" and "classic" VBOs within a batch, which the extension spec speaks against.

    Other ideas: I can tell you when I was first playing with this the #1 cause of crashes by far was leaving the bindless enables enabled:

    Code :
        glEnableClientState ( GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV );
        glEnableClientState ( GL_ELEMENT_ARRAY_UNIFIED_NV       );
    accidentally when I needed to render something with "classic" VBOs (I didn't convert everything over at once).

    If you've got this in a short test program, feel free to post and we'll figure it out. Also, if I have time this evening, I'll whip up a short working batch bindless test pgm and post it -- something you can morph into your usage and figure out what's up with the crash.

    Also, as with all "crash" issues, have you run a CPU memory debugger (e.g. valgrind, Purify, etc.) to see if it's something obvious?

  8. #8
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: Bindless Stuff

    Ok, here's a simple little GLUT test program to illustrate how to draw a "bindless batch" (that is, draw it with NV_vertex_buffer_unified_memory from here). To build without bindless, comment out #define WITH_BINDLESS.

    To keep it simple, I used the fixed-function pipe and legacy vertex attributes.

    Anyway, here's the code.

    Code :
    //------------------------------------------------------------------------------
    //  Bindless batches example:
    //
    //    NOTE: To keep this as stupid-simple as possible, this demo pgm
    //    doesn't use shaders, and therefore doesn't use generic vertex
    //    attributes (since to do so would require assuming NVidia vertex
    //    attribute aliasing.  Of course, bindless trivially supports both.
    //
    //------------------------------------------------------------------------------
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define GL_GLEXT_PROTOTYPES
    #include <GL/gl.h>
    #include <GL/glut.h>
     
    //------------------------------------------------------------------------
    // Uncomment the following to build with NV bindless batches support
    //   (i.e. NV_vertex_buffer_unified_memory)
    //------------------------------------------------------------------------
    #define WITH_BINDLESS
     
     
    GLuint Vbo_handle[3];          // Positions, Colors, Index list
     
    #ifdef WITH_BINDLESS
    GLuint64EXT Vbo_addr[3];       // Positions, Colors, Index list
    GLuint      Vbo_size[3];       // Positions, Colors, Index list
    #endif
     
    //-----------------------------------------------------------------------
     
    void checkGLError( const char hdr[] )
    {
      int err = glGetError();
      if( err )
      {
        fprintf(stderr, "ERROR %s: %s\n", hdr, gluErrorString(err));
        exit(1);
      }
    }
     
    //-----------------------------------------------------------------------
     
    void init()
    {
      static const GLfloat pos  [] = { -1, -1,
                                       -1,  1,
                                        1,  1,
                                        1, -1 };
      static const GLfloat color[]  = { 1,0,0,1,
                                        1,0,0,1,
                                        1,0,0,1,
                                        1,0,0,1 };
      static const GLushort index[] = { 0, 1, 2, 3 };
     
      // Create and fill VBOs
      glGenBuffers( 3, Vbo_handle );
     
      GLenum gl_target = GL_ARRAY_BUFFER;
     
      // Positions...
      glBindBuffer( gl_target, Vbo_handle[0] );
      glBufferData( gl_target, sizeof(pos)  , pos  , GL_STATIC_DRAW );
     
      // Colors...
      glBindBuffer( gl_target, Vbo_handle[1] );
      glBufferData( gl_target, sizeof(color), color, GL_STATIC_DRAW );
     
      // Index array...
      gl_target = GL_ELEMENT_ARRAY_BUFFER;
     
      glBindBuffer( gl_target, Vbo_handle[2] );
      glBufferData( gl_target, sizeof(index), index, GL_STATIC_DRAW );
     
    #ifdef WITH_BINDLESS
      // Make them resident and query GPU addresses
      for ( int i = 0; i < 3; i++ )
      {
        glBindBuffer( gl_target, Vbo_handle[i] );
        glGetBufferParameterui64vNV( gl_target, GL_BUFFER_GPU_ADDRESS_NV, 
                                     &amp;Vbo_addr[i] );
        glMakeBufferResidentNV     ( gl_target, GL_READ_ONLY );
      }
     
      Vbo_size[0] = sizeof(pos);
      Vbo_size[1] = sizeof(color);
      Vbo_size[2] = sizeof(index);
     
      // Make draw calls use the GPU address VAO state, not the handle VAO state
      glEnableClientState( GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV );
      glEnableClientState( GL_ELEMENT_ARRAY_UNIFIED_NV );
    #endif
    }
     
    //-----------------------------------------------------------------------
     
    void reshape(int width, int height)
    {
      glViewport(0, 0, width, height);
    }
     
    //-----------------------------------------------------------------------
     
    void display()
    {
      static float angle = 0.0;
     
      // Clear screen
      int err=0;
      glClear( GL_COLOR_BUFFER_BIT );
     
      // Load up PROJECTION and MODELVIEW
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glOrtho(-2,2,-2,2,-2,2);
     
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
     
      glRotatef(angle, 0,0,1);
      angle += 0.01;
     
      // Draw a quad
      glEnableClientState( GL_VERTEX_ARRAY );
      glEnableClientState( GL_COLOR_ARRAY );
     
    #ifdef WITH_BINDLESS
     
      // "Bindless VBOs case
      glVertexFormatNV      ( 2, GL_FLOAT, 2*sizeof(GLfloat) );
      glBufferAddressRangeNV( GL_VERTEX_ARRAY_ADDRESS_NV, 0, 
                              Vbo_addr[0], Vbo_size[0]);
     
      glColorFormatNV       ( 4, GL_FLOAT, 4*sizeof(GLfloat) );
      glBufferAddressRangeNV( GL_COLOR_ARRAY_ADDRESS_NV , 0, 
                              Vbo_addr[1], Vbo_size[1]);
     
      glBufferAddressRangeNV( GL_ELEMENT_ARRAY_ADDRESS_NV, 0, 
                              Vbo_addr[2], Vbo_size[2] );
    #else
     
      // "Classic" VBOs case
      glBindBuffer       ( GL_ARRAY_BUFFER, Vbo_handle[0] );
      glVertexPointer    ( 2, GL_FLOAT, 2*sizeof(GLfloat), 0 );
     
      glBindBuffer       ( GL_ARRAY_BUFFER, Vbo_handle[1] );
      glColorPointer     ( 4, GL_FLOAT, 4*sizeof(GLfloat), 0 );
     
      glBindBuffer       ( GL_ELEMENT_ARRAY_BUFFER, Vbo_handle[2] );
    #endif
     
      glDrawElements     ( GL_QUADS, 4, GL_UNSIGNED_SHORT, 0 );
     
      // Swap
      glutSwapBuffers();
      glutPostRedisplay();
      checkGLError( "End of display()" );
    }
     
    //-----------------------------------------------------------------------
     
    void keyboard(unsigned char key, int x, int y)
    {
       switch (key) {
          case 27:
             exit(0);
             break;
       }
    }
     
    int main (int argc, char** argv)
    {
      glutInit(&amp;argc, argv);
      glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE );
      glutCreateWindow(argv[0]);
     
      glutKeyboardFunc(keyboard);
      glutDisplayFunc(display);
      glutReshapeFunc(reshape);
     
      glutReshapeWindow(400,400);
     
      printf("GL_RENDERER = %s\n",glGetString(GL_RENDERER));
     
      glClearColor(0,0,0,0);
     
      init();
     
      glutMainLoop();
      return 0;
    }

    If instead you wanted to use generic vertex attributes, in display() you'd just change the attribute setup to this:

    Code :
    glVertexAttribFormatNV( attrib_id, width, type, norm_fixed_pt, stride );
    glBufferAddressRangeNV( GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, attrib_id, gpu_addr, gpu_size );

    And of course use the generic enable (e.g. glEnableVertexAttribArray) instead of the legacy attribute enables.

  9. #9
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    2,882

    Re: Bindless Stuff

    Quote Originally Posted by Dark Photon
    So, i reduced it to the case of binding only the index-array via bindless-stuff and leave the vertex-data array as is, for now.
    I personally have never tried mixing bindless and "classic" VBOs in the same batch...
    Out of curiousity, I just hacked the above little test program to do just that (bindless index VBO and "classic" attribute array VBOs), and it worked just fine.

    Tested on NVidia 195.36.07.03 (Linux), their new GL 3.3 drivers (equiv: 197.15 Windows):
    * NVidia 3.3 drivers

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •