Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 4 123 ... LastLast
Results 1 to 10 of 32

Thread: buffer_storage

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

    buffer_storage

    OK, so GL_ARB_texture_storage gave us immutable texture specification. You bind the texture, call glTexStorage* on it, and the storage is immutable.

    Buffer objects should be able to have something similar. So there would be a glBufferStorage function that allocates X bytes for the buffer, but also marks it as immutable. So you cannot call glBufferData on it ever.

    The main problem this avoids is someone trying to use glBufferData every frame to invalidate it, but maybe gets the hint or size parameters wrong. That's an improper invalidation of the buffer, and it results effectively in creating a new buffer object with theoretically new characteristics. So instead, you invalidate it with glMapBufferRange, and this extension would introduce a specific API for invalidating buffers: glBufferInvalidate.

    The latter might only be usable on immutable buffers. But that's debatable.

    However, this should also do some other things. Since it's an either/or process (either you use glBufferStorage or glBufferData, just like with glTexStorage), we can take the opportunity to correct some mistakes with buffer objects. Namely: hints.

    Hints with glBufferData are optional, in the sense that you can more or less ignore them. If you use GL_STATIC_DRAW, you can call glBufferData as many times as you want.

    With immutable storage however, hints should be requirements. I don't suggest keeping the previous hint enums around, as they're confusing to users and are too fuzzy (where is the dividing line between STREAM and DYNAMIC?). Whatever the new "hint" system is, it should absolutely affect the behavior of the buffer object.

    If there is an equivalent to "DRAW", for example, then it should be enforced. DRAW means that you will write but not read. So it should be an INVALID_OPERATION to use glGetBufferSubData or glMapBufferRange for reading. Same goes for "READ" and "COPY".

    I don't really have a fully developed suggestion for a new hint system, but whatever it is should specifically have a semantic component.

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

    Re: buffer_storage

    After thinking about it more, the "hints" should be behaviors. The possible options are as follows:

    1: No touching. You create the storage with glBufferStorage and that's it. You may not call glBufferSubData, glMapBufferRange, or glGetBufferSubData. You can call glBufferInvalidate. This allows you to read into the buffer from OpenGL (say, via transform feedback) after an invalidate, but even that may not be a good idea.

    2: Write exactly once. After calling glBufferStorage, you get exactly one glBufferSubData or glMapBufferRange call. After that, you get errors. Also, no invalidation. Obviously, glGetBufferSubData is out, as is read mapping.

    3: Write only after invalidate. As write exactly once, except that you can keep doing it so long as you invalidate between each write. So you can call glBufferStorage, glBufferSubData, then glBufferInvalidate, then glBufferSubData, then glMapBufferRange with GL_INVALIDATE_BUFFER_BIT, etc. Every write goes to invalidated memory.

    Note: I'm not particularly happy with this behavior, as it prevents you from mapping multiple times and writing to different locations. Perhaps allowances can be made for GL_INVALIDATE_RANGE_BIT.

    4: Writeable. You can pretty much do whatever, whenever, so long as you are writing to the buffer. So no read mapping and no glGetBufferSubData calls.

    5: Read only after invalidate. Basically, you compute some data on the GPU, read it back on the CPU, then invalidate the buffer, then do it over again. Your read accesses to the buffer must be bracketed by invalidates, as for "Write only after invalidate". The same notation applies.

    I don't see much point in a "Read only once."

    6: Readable: You can read pretty much willy-nilly. Just no writing at all.

    7: Wild-west. Basically what we have now. Whatever, whenever, read, right, arithmetic, whatever it is you want to do, you can do it.

  3. #3
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    985

    Re: buffer_storage

    Sounds very interesting. I have only two problems with it:

    1. I would never restrict MapBufferRange calls to a single invocation, rather just limit the usable map flags because, as you said, mapping several subranges would make some headaches this way. Also the amount of validations would be pretty high. I would rather say we should introduce one more "undefined behavior" (yes, I know we hate those, but they are pretty useful to provide high performance in situations where there is no clear behavior across hardware vendors as an example). So if one writes a single range multiple times through buffer mapping in case of e.g. a "Write only after invalidate" buffer then the results would be undefined. This way we can force developers not to use it this way, I believe.

    2. In case of the "No touching" behavior I think you mean something like STREAM_COPY? I don't totally understand what you meant there with the transform feedback example, but if you cannot even write to the buffer through transform feedback and/or image stores then what is the buffer good for? I'm pretty sure I've misunderstood something here but if I did maybe others will as well, so please can you clarify it?
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

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

    Re: buffer_storage

    Also the amount of validations would be pretty high.
    Perhaps, but they would only be done on read/write operations, which are already fairly heavyweight.

    This way we can force developers not to use it this way, I believe.
    The problem with marking it as undefined is that it will likely work. If the implementation does not take active steps to detect this behavior and stop it, then the code will continue to function.

    In case of the "No touching" behavior I think you mean something like STREAM_COPY?
    More just COPY in general. These behaviors only specify the pattern of CPU-based reads/writes to buffers. Reads and writes from OpenGL commands would always work.

    The only difference between STATIC_COPY and STREAM_COPY under my system is whether you ever invalidate the buffer or not. And I don't think it's worth it to introduce a new behavior just for that; the OpenGL implementation can detect if you invalidate a buffer.

  5. #5
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    985

    Re: buffer_storage

    Okay, thanks for the clarification and, again, interesting proposal.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  6. #6
    Junior Member Regular Contributor
    Join Date
    Aug 2006
    Posts
    226

    Re: buffer_storage

    I understand what you are trying to propose, but I don't understand what problem it solves?

    Regards
    elFarto

  7. #7
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    985

    Re: buffer_storage

    First, it adds immutable buffer objects in the same style ARB_texture_storage introduced immutable texture objects, and second, it gives more control over creating buffer objects for particular use case scenarios.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  8. #8
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    782

    Re: buffer_storage

    Mutable textures have the very real problem that they can be mipmap/cubemap incomplete. Buffers don't have that problem.

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

    Re: buffer_storage

    I understand what you are trying to propose, but I don't understand what problem it solves?
    One problem with buffer objects is the quantity of "hidden knowledge" about how to use them properly to achieve performance. Oh, it's easy if all you're doing is static data. But streamed data is very hard to get right, especially across platforms. Rob Barris had a couple of posts that were finally able to point us in a good direction surrounding buffer object streaming. But that's not exactly part of the API, is it?

    What inspired me to make this proposal was a question on StackOverflow from a new user about buffer objects. Every frame, he was generating new data and using glBufferData to upload it. The problem is that he would increase or decrease the size of the data uploaded. And therefore change the size of the buffer object. Which effectively means that the driver was not just invalidating memory, but reallocating it.

    A good API should be easy to use correctly and hard to use incorrectly. Invalidation via glBufferData is hard to get right; it requires knowing that you should keep the size and usage hints the same. If you aren't on this forum and aren't an experience OpenGL programmer, then you do not know this. Indeed, odds are that you have no idea what buffer invalidation is if you aren't.

    The other inspiration were a couple of facts about usage hints on NVIDIA and AMD. Did you know that AMD ignores usage hints entirely? They don't mean anything for them. And did you know that if you gave GL_DYNAMIC_DRAW to NVIDIA implementations, you killed upload performance? If one of the two major OpenGL implementations basically ignores the hint system, then there is a problem.

    If you write primarily on AMD hardware, then you may be convinced that a certain hint is giving you the correct performance. That's going to be a rude awakening when you slide over to NVIDIA and find that your DYNAMIC hint basically killed your performance.

    Now yes, performance is certainly going to be different cross-platform. Even with behavior-based usage. One platform might make "write anytime" perform as well as others. But at least there are guidelines about what the proper ways to use the buffer are.

  10. #10
    Junior Member Regular Contributor
    Join Date
    Dec 2009
    Posts
    210

    Re: buffer_storage

    I think the GL_AMD_pinned_memory extension is a nice approach for uploading use-once data. (The way it is uses a new buffer target to create pinned memory objects may be debatable.)

    You just point the driver to the data in your memory space and promise that you don't modify it until the driver has finished using it, which you can check via a sync object.

    I think an updated buffer object should provide something similar, as it is IMHO much easier to use than GL_ARB_map_buffer_range.

Posting Permissions

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