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 9 of 9

Thread: Uniform Buffers and BindBufferRange

  1. #1
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,135

    Uniform Buffers and BindBufferRange

    Hey everyone!

    I'm currently playing around with glBindBufferBase. Let's assume I have a uniform buffer of size 4 * 16 * sizeof(GLfloat), where one collection of uniforms has the size 1 * 16 * sizeof(GLfloat). Now I'm rendering 4 objects and I want to bind one collection at a time and use it within the active shader with the following block declaration:

    Code :
     
    layout(std140) uniform Collection
    {
      vec4 c0;
      vec4 c1;
      vec4 c2;
      vec4 c3;
    }

    Since my driver reports an offset alignment of 256 machine units, I get an INVALID_VALUE error when binding buffer range like this:

    Code :
    glBindBufferRange(GL_UNIFORM_BUFFER, buffer_index, offset, 16 * sizeof(GLfloat));
    with offset = i * 16 * sizeof(GLfloat) and i {0, 1, 2, 3}.

    Do I have to face facts and realize that I can only bind a collection which has a size equal to the offset alignment, or am I terribly missing somethin here?

    Do I need to resort to indexing into an array of structs within the UB and use a constant size (which totally defeats the purpose), or go back to using glUniform*() which will result in a massive increase in API calls with more then just a few objects?

    I'm using OpenGL 3.3 Core. Thank you!

    Edit: BTW, gDEBugger confirmed that the buffer is setup correctly and so is the uniform block binding.

  2. #2
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,065

    Re: Uniform Buffers and BindBufferRange

    Honestly, I was going to tell you to look at the reference docs, but sadly, they are incomplete on this point.

    When you use glBindBufferRange on uniform buffers, the `offset` parameter must be aligned to an implementation-dependent value: GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT. Also, the size bound must be a minimum of GL_UNIFORM_BLOCK_SIZE_DATA.

    So you need to fetch these values, then build your buffer objects based on them:

    Code :
    GLint uniformBufferAlignSize = 0;
    GLint uniformBufferMinSize = 0;
    glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformBufferAlignSize);
    glGetIntegerv(GL_UNIFORM_BLOCK_SIZE_DATA, &uniformBufferMinSize);

  3. #3
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,135

    Re: Uniform Buffers and BindBufferRange

    Quote Originally Posted by Alfonse Reinheart
    Honestly, I was going to tell you to look at the reference docs, but sadly, they are incomplete on this point.
    OT: I always do my best to check every available reference BEFORE posting in a board. I checked the core spec, the ARB extension spec, the GL wiki. However, you could not have guessed that.

    Quote Originally Posted by Alfonse Reinheart
    [..] the `offset` parameter must be aligned to an implementation-dependent value[..]
    I already mentioned the offset alignment of 256 bytes (in my case), so I'm aware of this. Also, since I'm using the std140 layout, my block size is known in advance and I did of course match the size of each collection to the block size.

    My point is: If I have to honor this limitation, the minimal collection of uniforms I can bind at a time would have to span 256 bytes. Right?

    This is what I don't get. It basically seems to render uniform blocks with small uniform collections unusable, unless you bind it using BindBufferBase and use some indexing scheme within a shader.

    Am I right or simply too stupid?

  4. #4
    Senior Member OpenGL Pro Ilian Dinev's Avatar
    Join Date
    Jan 2008
    Location
    Watford, UK
    Posts
    1,294

    Re: Uniform Buffers and BindBufferRange

    Afaik, the original alignment was 64, and was recently changed for future-proof with VAX AVX and stuff (why??). 64 was a nice number: a mat4 for world-pos, or mat4x3 for worldpos and a vec4 for something else.
    But anyway the update to 256-byte alignment isn't that bad, imho: At most you'll lose 192 bytes per object; and if there are 50k bigger objects in the scene, you'll waste only 9MB. For many tiny instanced objects, usually you'll keep instance-consts in 3-4 floats, and index into an array.

    I'd have loved to have 4-byte alignment, though.

  5. #5
    Senior Member OpenGL Pro Ilian Dinev's Avatar
    Join Date
    Jan 2008
    Location
    Watford, UK
    Posts
    1,294

    Re: Uniform Buffers and BindBufferRange

    Correction: ARB_map_buffer_alignment.txt was speaking about 256 bits instead of bytes, so the 256 alignment you're seeing is a somewhat arbitrary limitation an IHV has decided upon.

  6. #6
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,065

    Re: Uniform Buffers and BindBufferRange

    My point is: If I have to honor this limitation, the minimal collection of uniforms I can bind at a time would have to span 256 bytes. Right?
    No; that's just the required alignment for binding.

    If your uniform block is less than this size, then there will simply be extra space at the end. If your uniform block is only 64 bytes, then you need to allocate chunks in your buffer to the required alignment.

    So your buffer would look like this:

    Code :
    ---------- 0 bytes
    block data
    block data
    ---------- 64 bytes: end of block data you care about
    unused
    unused
    unused
    ---------- 1*alignment bytes: end of *actual* block data.
    block data
    block data
    ---------- 1*alignment + 64 bytes
    unused
    unused
    unused
    ---------- 2*alignment: end of second block data.
    ...

    Your uniform block definition in GLSL does not need to have the unused area in padding. That is, it doesn't need extra unused fields. This padding is all about how much room you give each section in your buffer object.

  7. #7
    Senior Member OpenGL Pro
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    1,135

    Re: Uniform Buffers and BindBufferRange

    Man, thank you guys so much! Works like a charm.

    With my current setup I'm losing 10 vec4s per object which is not a problem at all. I had suspected I needed to waste a bit of memory, but I got way to caught up in it.


  8. #8
    Junior Member Newbie
    Join Date
    Dec 2009
    Posts
    2

    Re: Uniform Buffers and BindBufferRange

    Hello,

    Quote Originally Posted by Alfonse Reinheart
    When you use glBindBufferRange on uniform buffers, the `offset` parameter must be aligned to an implementation-dependent value: GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT.
    That's OK for me, written in the spec.

    Quote Originally Posted by Alfonse Reinheart
    Also, the size bound must be a minimum of GL_UNIFORM_BLOCK_SIZE_DATA.
    I couldn't find any other reference to this, neither in the spec (3.3 core) nor even in any result from Google (which actually returns only this thread as its only search result). Could you tell me more about it? Was it removed? Is it a future feature?

    Thanks.

  9. #9
    Senior Member OpenGL Lord
    Join Date
    May 2009
    Posts
    6,065

    Re: Uniform Buffers and BindBufferRange

    I couldn't find any other reference to this, neither in the spec (3.3 core) nor even in any result from Google (which actually returns only this thread as its only search result).
    The bottom of page 73 and the top of page 74 of the 3.3 core OpenGL specification. Are you using an up-to-date PDF reader with search capabilities?

Posting Permissions

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