Skip to main content
GameDev.net gamedev.net
🔒 Locked

Vertex buffer objects: usage

Started by Mayrel Jun 27, 2004 at 8:51 PM 20 replies 4k views
Original Post
Mayrel
Mayrel
I'm a little confused as to what you're meant to use STREAM_* for. My understanding is that STREAM_* is used for geometry you specify and render only once. What I don't understand is why you wouldn't use DYNAMIC_* and just delete the vertex data after you've used it. What's different about STREAM_* that makes it good for things that DYNAMIC_* and STATIC_* aren't good for?
schue
schue
http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_buffer_object.txt

you will find your answer there.
Mayrel
Mayrel
Quote:
Original post by schue
http://oss.sgi.com/projects/ogl-sample/registry/ARB/vertex_buffer_object.txt

you will find your answer there.

Erm. No, I won't. That doesn't have any kind of comparison of the different usage modes on hardware. It's purposely very cagey about the whole affair.
KronosGL
KronosGL
Quote:

STREAM_DRAW_ARB - The data store contents will be specified once by the application, and used at most a few times as the source of a GL (drawing) command.

STREAM_READ_ARB - The data store contents will be specified once by reading data from the GL, and queried atmost a few times by the application.

STREAM_COPY_ARB - The data store contents will be specified once by reading data from the GL, and used at most a few times as the source of a GL (drawing) command.

STATIC_DRAW_ARB - The data store contents will be specified once by the application, and used many times as the source for GL (drawing) commands.

STATIC_READ_ARB - The data store contents will be specified once by reading data from the GL, and queried many times by the application.

STATIC_COPY_ARB - The data store contents will be specified once by reading data from the GL, and used many times as the source for GL (drawing) commands.

DYNAMIC_DRAW_ARB - The data store contents will be respecified repeatedly by the application, and used many times as the source for GL (drawing) commands.

DYNAMIC_READ_ARB - The data store contents will be respecified repeatedly by reading data from the GL, and queried many times by the application.

DYNAMIC_COPY_ARB - The data store contents will be respecified repeatedly by reading data from the GL, and used many times as the source for GL (drawing) commands.


Just read it carefully and don't mind where the data ends up. That job belongs to the driver...
STREAM is when you or GL provide the data once.
Mayrel
Mayrel
Quote:
Original post by KronosGL
Quote:

STREAM_DRAW_ARB - The data store contents will be specified once by the application, and used at most a few times as the source of a GL (drawing) command.

STREAM_READ_ARB - The data store contents will be specified once by reading data from the GL, and queried atmost a few times by the application.

STREAM_COPY_ARB - The data store contents will be specified once by reading data from the GL, and used at most a few times as the source of a GL (drawing) command.

STATIC_DRAW_ARB - The data store contents will be specified once by the application, and used many times as the source for GL (drawing) commands.

STATIC_READ_ARB - The data store contents will be specified once by reading data from the GL, and queried many times by the application.

STATIC_COPY_ARB - The data store contents will be specified once by reading data from the GL, and used many times as the source for GL (drawing) commands.

DYNAMIC_DRAW_ARB - The data store contents will be respecified repeatedly by the application, and used many times as the source for GL (drawing) commands.

DYNAMIC_READ_ARB - The data store contents will be respecified repeatedly by reading data from the GL, and queried many times by the application.

DYNAMIC_COPY_ARB - The data store contents will be respecified repeatedly by reading data from the GL, and used many times as the source for GL (drawing) commands.


Just read it carefully and don't mind where the data ends up. That job belongs to the driver...
STREAM is when you or GL provide the data once.


I don't care where the data is: I care about the performance characteristics. Because, as you say, it's up to the driver what to do, the specification of the extension purposely has nothing to say about the performance characteristics. It's not much use here.

I care about whether anyone has experience with using the different modes with different kinds of data and has actual first-hand knowledge of how best to use the different modes.
vincoof
vincoof
I won't talk about any READ or COPY operation since (i) I've not used them and (ii) that's not the most important point for *vertex* buffer objects (but the spec states clearly there will be obvious opportunity to use them in the future, for things like render to vertex array / dynamic displacement mapping).

All DRAW commands are faster than traditional vertex when you make use of them as specified, though I've not noted good use of STREAM ... in all cases I've tested, either STATIC or DYNAMIC were the fastest, never STREAM. It may be due to an inappropriate driver optimization, or simply my tests don't fit in the 'best case scenario' for STREAM.

My experience is that you absolutely need to use DYNAMIC when your data changes. If you ever use STATIC on dynamic data, the GL accepts it but the performance drop is awful, generally as slow as traditional vertex arrays, and sometimes as slow as immediate mode. So, if you have any doubt about the "dynamicity" of your data, use always DYNAMIC. Even with static data, the performance between STATIC and DYNAMIC is not very big. However, if you really want to push the cards to its limits, STATIC is the way to go. Just make sure your data is really static.

[edit] Please note this is just "my" experience for "current" hardware. Needless to say, other ppl may have different experience, and certainly that the next generations of graphics cards (or simply the next generation of drivers) will upset those kind of tests.
Mayrel
Mayrel
Thanks for the informative reply. :)

Quote:
Original post by vincoof
I won't talk about any READ or COPY operation since (i) I've not used them and (ii) that's not the most important point for *vertex* buffer objects (but the spec states clearly there will be obvious opportunity to use them in the future, for things like render to vertex array / dynamic displacement mapping).

By the looks of the specification for VBOs, READ and COPY operations aren't even used for VBO. That's probably fairly obvious: there's no glCopyBufferARB() (which would probably have been useful).
Quote:

My experience is that you absolutely need to use DYNAMIC when your data changes. If you ever use STATIC on dynamic data, the GL accepts it but the performance drop is awful, generally as slow as traditional vertex arrays, and sometimes as slow as immediate mode. So, if you have any doubt about the "dynamicity" of your data, use always DYNAMIC. Even with static data, the performance between STATIC and DYNAMIC is not very big. However, if you really want to push the cards to its limits, STATIC is the way to go. Just make sure your data is really static.

Something I haven't tried, but I assume would work just fine, is to use STATIC and vertex_program together to blend between frames of interpolated meshes. That way, you can have dynamic meshes without needing DYNAMIC vertex arrays. Obviously, that works best if you can store all the frames in VBOs, but I would expect to interpolate between dynamically created frames from a skeletal animation system, so that would be sped up as well.
vincoof
vincoof
Quote:
Original post by Mayrel
Something I haven't tried, but I assume would work just fine, is to use STATIC and vertex_program together to blend between frames of interpolated meshes.

That's generally a good solution to let the GPU compute things that CPU would do, especially if your mesh changes *every* frame. But if there's some chance that interpolation is not needed at all frames (typically a pause in the animation) the sometimes it's better to compute it in the CPU side (and keep it in the memory so it doesn't have to be computed multiple times) and use DYNAMIC VBO's.

Quote:
Original post by Mayrel
Obviously, that works best if you can store all the frames in VBOs, but I would expect to interpolate between dynamically created frames from a skeletal animation system, so that would be sped up as well.

Storing all frames in VBO's is not a very good solution. First, it wastes alot of memory. Secondly, it has no flexibility regarding the animation refinement. Third, it needs much more initialization time. And at last, but not least, it only works for keyframe animation. You can't pre-compute all cases in bone-based animations.
And even in the case that (i) you have enough memory, (ii) your animation refinement is fixed, (iii) you don't care about initialization time and (iv) your animation is keyframe-based, storing all frames in VBO's will not necessarily speed up things due to cache misses. (vertex cache misses, but also texture cache misses since memory that VBO uses is memory that texture does not use, when graphics cards memory is REALLY shared)
Mayrel
Mayrel
Quote:
Original post by vincoof
Quote:
Original post by Mayrel
Something I haven't tried, but I assume would work just fine, is to use STATIC and vertex_program together to blend between frames of interpolated meshes.

That's generally a good solution to let the GPU compute things that CPU would do, especially if your mesh changes *every* frame. But if there's some chance that interpolation is not needed at all frames (typically a pause in the animation) the sometimes it's better to compute it in the CPU side (and keep it in the memory so it doesn't have to be computed multiple times) and use DYNAMIC VBO's.

Erm? Surely if no animation occurs, then STATIC is the best bet?
Quote:

Quote:
Original post by Mayrel
Obviously, that works best if you can store all the frames in VBOs, but I would expect to interpolate between dynamically created frames from a skeletal animation system, so that would be sped up as well.

Storing all frames in VBO's is not a very good solution. First, it wastes alot of memory. Secondly, it has no flexibility regarding the animation refinement. Third, it needs much more initialization time. And at last, but not least, it only works for keyframe animation. You can't pre-compute all cases in bone-based animations.

First: You can use a caching system to store the N most-recently-used frames in STATIC buffers, and the rest in DYNAMIC buffers.

Secondly: How you can apply refinements to a keyframe animation?

Third: You don't need to load all the frames at initialisation time. A frame doesn't need to be loaded until it is used the first time.

You don't need to pre-compute all cases, just the cases that you're interpolating from and to. If the skeletal animation system usually generates a new mesh every 16 frames, then I I'm sure STATIC would be a Big Win.
Quote:

And even in the case that (i) you have enough memory, (ii) your animation refinement is fixed, (iii) you don't care about initialization time and (iv) your animation is keyframe-based, storing all frames in VBO's will not necessarily speed up things due to cache misses. (vertex cache misses, but also texture cache misses since memory that VBO uses is memory that texture does not use, when graphics cards memory is REALLY shared)

(i) isn't a problem if you use your brain, (ii) doesn't apply, (iii) isn't a problem if you use your brain, (iv) doesn't apply.
vincoof
vincoof
Quote:
Original post by Mayrel
Erm? Surely if no animation occurs, then STATIC is the best bet?

Sure :)

Quote:
Original post by Mayrel
First: You can use a caching system to store the N most-recently-used frames in STATIC buffers, and the rest in DYNAMIC buffers.

Apply your own LRU algorithm ? So what happens to a buffer that is N+1 recently used ? You switch it from STATIC to DYNAMIC ? I'm not sure the kind of optimization you're doing here. ^^

Quote:
Original post by Mayrel
Secondly: How you can apply refinements to a keyframe animation?

There is a maximum number of frames stored in the keyframe data (well, by clever algorithms it's generally possible to go over that limit, but that's not the point here) but you can also choose to take less frames, say 1 out of 2 for example. This is especially useful for computers which speed or memory is so weak that you accept to lower the quality of the animation.

Quote:
Original post by Mayrel
Third: You don't need to load all the frames at initialisation time. A frame doesn't need to be loaded until it is used the first time.

Uploading is slow. You will get lags if your application uploads textures or VBO's while the game is running. The only case where realtime upload is useful is when you want to perform continuous loading for games that never show a loading screen (expect the very first one of course).

Quote:
Original post by Mayrel
You don't need to pre-compute all cases, just the cases that you're interpolating from and to. If the skeletal animation system usually generates a new mesh every 16 frames, then I I'm sure STATIC would be a Big Win.

Skeletal animation is not about ecomputing pre- and post-meshes and interpolating them. Rather it's about using pre- and post-matrices and interpolating them, then use the interpolated matrix set to compute the vertex position (preferably in a vertex program). At this point there's no use in multiple sets of VBO's. Simply store the "original" mesh in a VBO and compute every animation from it.

I'm sorry if sometimes I sound harsh. I know I need to learn better English in order to be able to write more 'diplomatic' words ^^

[edit]typos
NLDEV
NLDEV
Quote:
Original post by Mayrel
By the looks of the specification for VBOs, READ and COPY operations aren't even used for VBO. That's probably fairly obvious: there's no glCopyBufferARB() (which would probably have been useful).


Well, you can Map the buffer then copy.
Mayrel
Mayrel
Quote:
Original post by vincoof
Quote:
Original post by Mayrel
First: You can use a caching system to store the N most-recently-used frames in STATIC buffers, and the rest in DYNAMIC buffers.

Apply your own LRU algorithm ? So what happens to a buffer that is N+1 recently used ? You switch it from STATIC to DYNAMIC ? I'm not sure the kind of optimization you're doing here. ^^

Well, no. That would be silly, wouldn't it? However, I would expect the driver to apply a LRU. STATIC/STREAM/DYNAMIC are only hints, after all: I wouldn't be offended if a driver noticed that a vertex buffer I'd allocated as DYNAMIC wasn't actually changing very often and could safely be stored in video memory. Similarly, if it noticed that a STATIC buffer was being changed more often than rendered from, I wouldn't mind if it moved it to system memory.
Quote:

Quote:
Original post by Mayrel
Secondly: How you can apply refinements to a keyframe animation?

There is a maximum number of frames stored in the keyframe data (well, by clever algorithms it's generally possible to go over that limit, but that's not the point here) but you can also choose to take less frames, say 1 out of 2 for example. This is especially useful for computers which speed or memory is so weak that you accept to lower the quality of the animation.

I don't see that's an issue here. If you want to skip a frame, you only need to select an appropriate target VBO.
Quote:

Quote:
Original post by Mayrel
Third: You don't need to load all the frames at initialisation time. A frame doesn't need to be loaded until it is used the first time.

Uploading is slow. You will get lags if your application uploads textures or VBO's while the game is running. The only case where realtime upload is useful is when you want to perform continuous loading for games that never show a loading screen (expect the very first one of course).

I don't think uploading is that slow.

It appears to me that most of the slowness comes with performing processing upon the disk representation of the data to make it suitable for use by the driver.

Consider: All the frames could be held in system memory at the start. Then, each time a particular frame is used, it's loaded into a VBO. You might have a fixed number of VBOs for each object, and use a LRU system to reuse an old VBO when a new frame comes up. I can't see that being notably less efficient than just using traditional vertex arrays.
Quote:

Quote:
Original post by Mayrel
You don't need to pre-compute all cases, just the cases that you're interpolating from and to. If the skeletal animation system usually generates a new mesh every 16 frames, then I I'm sure STATIC would be a Big Win.

Skeletal animation is not about ecomputing pre- and post-meshes and interpolating them. Rather it's about using pre- and post-matrices and interpolating them, then use the interpolated matrix set to compute the vertex position (preferably in a vertex program). At this point there's no use in multiple sets of VBO's. Simply store the "original" mesh in a VBO and compute every animation from it.

That can't be the only way to do skeletal animation, otherwise you wouldn't be able to do skeletal animation with hardware/drivers that didn't support vertex weighting. I won't deny that the vertex-weighting technique will be more efficient, but obviously that's not going to help if you are unable to use it.
Quote:

I'm sorry if sometimes I sound harsh. I know I need to learn better English in order to be able to write more 'diplomatic' words ^^

Don't worry about it. I sounded harsh as well. :)
_the_phantom_
_the_phantom_
Quote:
Original post by Mayrel
Well, no. That would be silly, wouldn't it? However, I would expect the driver to apply a LRU. STATIC/STREAM/DYNAMIC are only hints, after all: I wouldn't be offended if a driver noticed that a vertex buffer I'd allocated as DYNAMIC wasn't actually changing very often and could safely be stored in video memory. Similarly, if it noticed that a STATIC buffer was being changed more often than rendered from, I wouldn't mind if it moved it to system memory.


tbh, i dont think that is likely to happen. While it is only hints to the driver its a pretty important hint as to the useage pattern, if you say its static, while its not going to stop you changing the data the driver is more likely to place the VBO in vram as the write access speed doesnt matter, where as read can be optermised.
Its kinda related to the DRAW/READ stuff is only hints, but pretty important ones, if you are only drawing from a VBO and writing data into it then the driver will be able to judge where to put the data better, you'll still be able to read from it but you'll have to wait for a copy back operation to system ram.
So, while they maybe only hints, I'd say they are pretty important and i wouldnt count on the driver changing the access mode if you decide to go against what you have told it you are going todo.
Rule of thumb : if you are going to change the data reasonable often, maybe it dynamic draw, that way you should get the best of both world (fast update and fast rendering).
vincoof
vincoof
Quote:
Original post by Mayrel
Quote:
Original post by vincoof
Apply your own LRU algorithm ? So what happens to a buffer that is N+1 recently used ? You switch it from STATIC to DYNAMIC ? I'm not sure the kind of optimization you're doing here. ^^

Well, no. That would be silly, wouldn't it?

Yup, that's why I wasn't sure what you meant.
Quote:
Original post by Mayrel
However, I would expect the driver to apply a LRU.

Most drivers (if not all) do already apply a LRU algorithm for VBO.

Quote:
Original post by Mayrel
STATIC/STREAM/DYNAMIC are only hints, after all: I wouldn't be offended if a driver noticed that a vertex buffer I'd allocated as DYNAMIC wasn't actually changing very often and could safely be stored in video memory. Similarly, if it noticed that a STATIC buffer was being changed more often than rendered from, I wouldn't mind if it moved it to system memory.

But how would the driver know "data is changing very often" ? For this to work the driver would have to run some kind of benchmark. And I don't know of any driver doing this, for many reasons (the first one being : it's a too high level feature for a driver).

Quote:
Original post by Mayrel
If you want to skip a frame, you only need to select an appropriate target VBO.

Okay, but then the skipped frame wastes memory and wastes time for uploading it (though, for sure the driver will be clever enough not to upload the data into video memory unless the data is used).

Quote:
Original post by Mayrel
I don't think uploading is that slow.

It appears to me that most of the slowness comes with performing processing upon the disk representation of the data to make it suitable for use by the driver.

Sure the time spent uploading VBO is negligible compared to time loading from disk, but still the VBO uploading time is not free. However, you can compare VBO uploading during the game to disk access during the game, but at a lower cost of course. The general point is : reduce transferts anytime you can. Bandwidth is always limited, be it IDE bandwidth or AGP bandwidth.

Quote:
Original post by Mayrel
Consider: All the frames could be held in system memory at the start. Then, each time a particular frame is used, it's loaded into a VBO. You might have a fixed number of VBOs for each object, and use a LRU system to reuse an old VBO when a new frame comes up. I can't see that being notably less efficient than just using traditional vertex arrays.

Yes it's a good idea, but ... the driver already does that ! :)
So let it work, I'm pretty sure many of us won't do it better than nVidia or ATi developers, especially considering the fact that driver developers can work at a level which is much closer to the hardware.

Quote:
Original post by Mayrel
That can't be the only way to do skeletal animation, otherwise you wouldn't be able to do skeletal animation with hardware/drivers that didn't support vertex weighting. I won't deny that the vertex-weighting technique will be more efficient, but obviously that's not going to help if you are unable to use it.

The old way of performing skeletal animation is to pre-compute frames from a fixed set of skeletal animations, and generate keyframes from them. Anyway I think we're going a bit off-topic, considering the topic is based on VBO's, not animation techniques.
Mayrel
Mayrel
Quote:
Original post by MikeMJH
Quote:
Original post by Mayrel
By the looks of the specification for VBOs, READ and COPY operations aren't even used for VBO. That's probably fairly obvious: there's no glCopyBufferARB() (which would probably have been useful).

Well, you can Map the buffer then copy.

That's still the CPU doing the copy. To me, the description of COPY is clearly referring to buffers that the GL will be copying things between: it uses the phrase "reading data from the GL" to describe how data gets into it. My assumption is that COPY is likely to be for pixel buffers that the GL will draw in, or for vertex buffers that the GL will fill with geometry using evaluators.
Mayrel
Mayrel
Quote:
Original post by _the_phantom_
Quote:
Original post by Mayrel
Well, no. That would be silly, wouldn't it? However, I would expect the driver to apply a LRU. STATIC/STREAM/DYNAMIC are only hints, after all: I wouldn't be offended if a driver noticed that a vertex buffer I'd allocated as DYNAMIC wasn't actually changing very often and could safely be stored in video memory. Similarly, if it noticed that a STATIC buffer was being changed more often than rendered from, I wouldn't mind if it moved it to system memory.


tbh, i dont think that is likely to happen. While it is only hints to the driver its a pretty important hint as to the useage pattern, if you say its static, while its not going to stop you changing the data the driver is more likely to place the VBO in vram as the write access speed doesnt matter, where as read can be optermised.

But there's a limited amount of VRAM available. A driver cannot always put a VBO in video memory, even if you specify STATIC. What STATIC does is tell the driver that, if it has to choose between a set of VBOs to load into video memory, it should choose the STATIC one.
Quote:

Its kinda related to the DRAW/READ stuff is only hints, but pretty important ones,

They're entirely unimportant because VBOs don't even use the READ usages:
Quote:
ARB_vertex_buffer_object
Note that the "copy" and "read" usage tokens will become meaningful only when pixel transfer capability is added to buffer objects by a (presumed) subsequent extension.

Quote:

if you are only drawing from a VBO and writing data into it then the driver will be able to judge where to put the data better, you'll still be able to read from it but you'll have to wait for a copy back operation to system ram.
So, while they maybe only hints, I'd say they are pretty important and i wouldnt count on the driver changing the access mode if you decide to go against what you have told it you are going todo.

No, I wouldn't count on the driver doing that. I'm just saying that I wouldn't be upset if it did.
Quote:
Original post by vincoof
Quote:
Original post by Mayrel
However, I would expect the driver to apply a LRU.

Most drivers (if not all) do already apply a LRU algorithm for VBO.

Which is why I don't see a memory problem. I'd expect the driver not to transfer a STATIC buffer to video memory until it's actually used, and to remove it if it stops being used.
Quote:

Quote:
Original post by Mayrel
STATIC/STREAM/DYNAMIC are only hints, after all: I wouldn't be offended if a driver noticed that a vertex buffer I'd allocated as DYNAMIC wasn't actually changing very often and could safely be stored in video memory. Similarly, if it noticed that a STATIC buffer was being changed more often than rendered from, I wouldn't mind if it moved it to system memory.

But how would the driver know "data is changing very often" ? For this to work the driver would have to run some kind of benchmark. And I don't know of any driver doing this, for many reasons (the first one being : it's a too high level feature for a driver).

I don't think that's particularly difficult. All the driver has to do is keep a track of how often the VBO is used as a source of vertex data and how often the VBO has its data respecified. The driver knows the ratio of source/respecification that's suitable for each usage type, and would be able to move them around as suitable.

Remember -- the usage hints are only hints. It is the explicit responsibility of the driver to manage the storage of VBOs, taking the hints into account where that's possible. Nothing prevents a driver from taking usage stats into account.
Quote:

Quote:
Original post by Mayrel
If you want to skip a frame, you only need to select an appropriate target VBO.

Okay, but then the skipped frame wastes memory and wastes time for uploading it (though, for sure the driver will be clever enough not to upload the data into video memory unless the data is used).

This is true, but if you're skipping frames because the computer is slow/short on memory, you probably know that when you load the model, so you can skip frames when loading it. No memory wasted. Of course, if you want to adaptively change the 'frame-rate' of a model, you'll need to load all the frames. But you'd need to do that anyway, so I don't think it's a problem.
Quote:

Quote:
Original post by Mayrel
I don't think uploading is that slow.

It appears to me that most of the slowness comes with performing processing upon the disk representation of the data to make it suitable for use by the driver.

Sure the time spent uploading VBO is negligible compared to time loading from disk, but still the VBO uploading time is not free. However, you can compare VBO uploading during the game to disk access during the game, but at a lower cost of course. The general point is : reduce transferts anytime you can. Bandwidth is always limited, be it IDE bandwidth or AGP bandwidth.

And I agree. But the simple fact is that uploading static frames to video memory every N frames (where N is the number of frames between each interpolation frame) uses notably less bandwidth than uploading dynamic frames every 1 frame.
vincoof
vincoof
Quote:
Original post by Mayrel
I'd expect the driver not to transfer a STATIC buffer to video memory until it's actually used, and to remove it if it stops being used.

Good point. It's exactly what the driver does actually. :)

Quote:
Original post by Mayrel
I don't think that's particularly difficult. All the driver has to do is keep a track of how often the VBO is used as a source of vertex data and how often the VBO has its data respecified. The driver knows the ratio of source/respecification that's suitable for each usage type, and would be able to move them around as suitable.

Remember -- the usage hints are only hints. It is the explicit responsibility of the driver to manage the storage of VBOs, taking the hints into account where that's possible. Nothing prevents a driver from taking usage stats into account.

You're right about the fact that "hints" leave the driver developer free to choose whatever algorithm they want (well, this would make hints pointless). Anyway I don't think drivers are going to run this way. This wastes computational resources, and I wouldn't rely on such detection. I for one know better than the driver if a-priori the data will be dynamic or not. Your proposal may be a good a-posteriori analysis but I think the analysis comes "too late" (needs many frames to have been rendered).

Quote:
Original post by Mayrel
And I agree. But the simple fact is that uploading static frames to video memory every N frames (where N is the number of frames between each interpolation frame) uses notably less bandwidth than uploading dynamic frames every 1 frame.

Oh, but I've never meant to replace N-STATIC by a 1-DYNAMIC VBO. I'm sorry if my bad english leaded to that confusion.
Mayrel
Mayrel
Quote:
Original post by vincoof
You're right about the fact that "hints" leave the driver developer free to choose whatever algorithm they want (well, this would make hints pointless). Anyway I don't think drivers are going to run this way. This wastes computational resources, and I wouldn't rely on such detection.

And neither would I.

I just think the driver would be able to do that quite easily.
Quote:

I for one know better than the driver if a-priori the data will be dynamic or not.

I think it depends upon how dynamic it is, perhaps. If you know the data will be changing every frame, or that it will never change, then there's no obvious advantage to a driver that analyses usage stats.

On the other hand, if you have vertex data that will change often at some times, and then remain unchanged at others, then you have to do extra work if you want to make sure things are efficient.

An example might be a map or model editor: parts of the mesh will be modified many times, but then you move on to another part of the mesh. To be efficient, if the driver didn't automatically detect the changing usage of the various parts of the mesh, you'd have to manage it manually. If the driver does analyse usage patterns, then it can do it itself.

The computation still has to be done, but I think the driver would be in a better place to act on it efficiently -- it would be easier for the driver to change the usage mode of a VBO, or part of a VBO, because the only way for the editor to do it is to respecify the entire VBO, and it can only specify a usage mode for the entire VBO.

Perhaps, to be explicit, an ADAPTIVE_{DRAW|READ|COPY} usage could be defined in some later extension, which makes it clear that the driver is to handle the management. That way, you don't have to worry about the driver having to do extra processing which isn't needed.
Quote:

Your proposal may be a good a-posteriori analysis but I think the analysis comes "too late" (needs many frames to have been rendered).

I don't think that's a problem. I wouldn't suggest removing usages altogether, just that the driver is in a position to adapt to changing usage patterns and should be encouraged to do so.
_the_phantom_
_the_phantom_
Quote:
Original post by Mayrel
An example might be a map or model editor: parts of the mesh will be modified many times, but then you move on to another part of the mesh. To be efficient, if the driver didn't automatically detect the changing usage of the various parts of the mesh, you'd have to manage it manually. If the driver does analyse usage patterns, then it can do it itself.

The computation still has to be done, but I think the driver would be in a better place to act on it efficiently -- it would be easier for the driver to change the usage mode of a VBO, or part of a VBO, because the only way for the editor to do it is to respecify the entire VBO, and it can only specify a usage mode for the entire VBO.


I honestly dont see the advantage here, by the fact that you are going to adjust the verts makes the VBOs dynamic anyway so if i was writing an editor i'd make the VBOs dynamic and be done with it.
Also, you've just added overhead to a situation which doesnt require it.
Currently its upto you to decide how the driver should treat the data, so you tell it as such and it deals with it as best it can end of story.
However in your method the driver has to perform some kind of tracking to work out how likely it is a bit of data is going to be required to be updated and how like it is that its going to be static, this work would have to be done pretty often.
Performance wise you'll probably gain nowt even if it was for free and the fact it isnt for free is going to cost you in a postion where you wont want the overhead.
In a game you want buffer switches to be as fast as possible, and they are already relatively slow anyways, start asking the driver to try to guess (which is really all it is) when you are going to use the VBO to write to next and you've added more overhead for frankly a pretty much useless feature.

Quote:

Perhaps, to be explicit, an ADAPTIVE_{DRAW|READ|COPY} usage could be defined in some later extension, which makes it clear that the driver is to handle the management.


The driver manages what happens to the VBO anyways based on the useage model you give it.

Quote:

That way, you don't have to worry about the driver having to do extra processing which isn't needed.


You mean like trying to guess how you are going to use the VBO and perform useage tracking, which in the majority of cases is no use? That kind of extra processing?

Quote:

I don't think that's a problem. I wouldn't suggest removing usages altogether, just that the driver is in a position to adapt to changing usage patterns and should be encouraged to do so.


I dont belive thats the case at all, just because a drive CAN do a thing it doesnt always follow that it MUST do a thing.
And as I've stated in the majority of cases i dont think you'll gain anything from this and mostly likely lose more than you'll gain anyways just because the drive is being asked to track more than it should.

This is kinda like the discussion that was had a while ago on if the driver should track glEnable() states for things like texturing so that if two enables where called the second one would be ignored and the basic idea was that this was pointless at a driver level simple because of the extra work load required, much the same with this idea as well.
Mayrel
Mayrel
Quote:
Original post by _the_phantom_
Quote:
Original post by Mayrel
An example might be a map or model editor: parts of the mesh will be modified many times, but then you move on to another part of the mesh. To be efficient, if the driver didn't automatically detect the changing usage of the various parts of the mesh, you'd have to manage it manually. If the driver does analyse usage patterns, then it can do it itself.

The computation still has to be done, but I think the driver would be in a better place to act on it efficiently -- it would be easier for the driver to change the usage mode of a VBO, or part of a VBO, because the only way for the editor to do it is to respecify the entire VBO, and it can only specify a usage mode for the entire VBO.


I honestly dont see the advantage here, by the fact that you are going to adjust the verts makes the VBOs dynamic anyway so if i was writing an editor i'd make the VBOs dynamic and be done with it.

Which is why I wouldn't use your editor. The point is that out of potentially millions of vertices, only a couple hundred, say, will be being editted at any time.
Quote:

However in your method the driver has to perform some kind of tracking to work out how likely it is a bit of data is going to be required to be updated and how like it is that its going to be static, this work would have to be done pretty often.
Performance wise you'll probably gain nowt even if it was for free and the fact it isnt for free is going to cost you in a postion where you wont want the overhead.

It is effectively for free. It costs the driver nothing to increment a counter when a vertex array is referenced by a array-drawing primitive. It costs the driver nothing to add that counter to a weight that it will need to generate anyway to decide what data to evict from the scarse video memory.
Quote:

In a game you want buffer switches to be as fast as possible, and they are already relatively slow anyways, start asking the driver to try to guess (which is really all it is) when you are going to use the VBO to write to next and you've added more overhead for frankly a pretty much useless feature.

And yet, obviously, I wasn't talking about a game. And, of course, it isn't a guess.
Quote:

Quote:

Perhaps, to be explicit, an ADAPTIVE_{DRAW|READ|COPY} usage could be defined in some later extension, which makes it clear that the driver is to handle the management.

The driver manages what happens to the VBO anyways based on the useage model you give it.

Are you even listening? You just said that the driver isn't allowed to manage the VBOs in the way that I'm describing. The ADAPTIVE usage notion gives it permission to do so, on the understanding that the developer knows it's going to happen and is prepared for whatever mythical performance drain you want to make up.
Quote:

Quote:

That way, you don't have to worry about the driver having to do extra processing which isn't needed.

You mean like trying to guess how you are going to use the VBO and perform useage tracking, which in the majority of cases is no use? That kind of extra processing?

For God's sake, LISTEN! The usage tracking will be useful if you specify an ADAPTIVE usage -- that's why you'd specify it.
Quote:

Quote:

I don't think that's a problem. I wouldn't suggest removing usages altogether, just that the driver is in a position to adapt to changing usage patterns and should be encouraged to do so.

I dont belive thats the case at all, just because a drive CAN do a thing it doesnt always follow that it MUST do a thing.
And as I've stated in the majority of cases i dont think you'll gain anything from this and mostly likely lose more than you'll gain anyways just because the drive is being asked to track more than it should.

You're quite right. There's no point actually bothering to check if adaptive usage could possibly speed up any programs anywhere. We might as well just assume it can't.
Quote:

This is kinda like the discussion that was had a while ago on if the driver should track glEnable() states for things like texturing so that if two enables where called the second one would be ignored and the basic idea was that this was pointless at a driver level simple because of the extra work load required, much the same with this idea as well.

Eh? You think that the driver shouldn't ignore glEnable(GL_TEXTURE_2D) if texturing is already enabled? That a "CMP AX, texture2D_bit; JE glEnable_return;" is so much work that it would be better to wait for a CPU-to-GPU-to-CPU round-trip to tell the GPU to enable texturing?

Even then, it's not the same. Moving VBOs off the graphics card when they aren't being used is something the driver can do for free. The GPU itself can monitor the usage of VBOs in its memory, and it can do that in parallel. There's no sense in which such a technique would automatically result in a reduction in performance.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.