[Openal-devel] Faster buffer model, and more random stuff

Chris Robinson chris.kcat at gmail.com
Mon Feb 25 19:20:42 PST 2008


On Monday 25 February 2008 05:45:52 pm Sherief N. Farouk wrote:
> When buffering data, an implementation is free to not resize the memory
> segment if the new data is smaller than the current, as long as it'll
> behave as expected. And even if it did, decreasing a memory segment's size
> is very cheap. And as I'd be hard pressed to believe someone would need to
> update a buffer queue more than 5 to 10 times a second, this isn't going to
> be a bottleneck compared to the actual audio mixing or Ogg decoding.
>
> >>: The immutable buffer approach makes it free, instead of "relatively
> >>: cheap". Note that "relatively cheap" thinking on the implementation
> >>: side uses lots of branching statements that are MURDER on some of the
> >>: platforms we work on, and anything without Out of order execution,
> >>: basically.

Making it immutable would require a new extension. I probably wouldn't have 
much of a problem supporting it since I don't think it'd be very difficult. 
All it'd do is remove a single if check and integer assignment, though.

I'd also say that if GL3 is going down the immutable size route, we may want 
to hold off and see how they do it, to get ideas for the API style, etc. And 
maybe even update all of AL itself to 2.0 with a new API styled after GL3 
(depending on how different it is).

> Then how do you deal with the fact that data may not be in a format known
> by the app? It couldn't know the mapped buffer is, eg. 24-bit signed
> integer with 8-bit padding, as opposed to the float-32 it created the
> buffer with, or that the data is deinterlaced and possibly in completely
> different memory segments. Converting on (un)map, I think is beyond the
> scope of what mapping is for, let alone that it wouldn't even be possible
> if the mapped buffer memory is smaller than the pre-converted data.
>
> >>: Again, this is a convert-on-read. You seem to treat mapping as a
> >>: direct, literal mapping. It's not. It's more logical than you treat it.
> >>: It BEHAVES like it's stored in memory in that format.

Since GL doesn't allow you mapped access to texture or framebuffer data, 
there's no reason for it to use a non-literal mapping. You can only map pixel 
buffer objects, which are using the user-specified format since they're not 
used for rendering or texturing and thus don't need to be in a 
performance-minded format. I don't see any reason to break from this for AL.

> >>: Regardless of the 
> >>: internal format, a buffer created with format X (the implementation can
> >>: store it in any format it deems suitable, mind you) expects data to be
> >>: written to the pointer provided by map buffer in the format X, and
> >>: provides a pointer pointing to data in the format X when a mapping is
> >>: requested for read. Conversion is done when necessary. Again, think
> >>: nvidia GPUs and RGBA.

Yes, but again, this doesn't apply to textures or framebuffers since they're 
not mappable. Pixel buffers, which are mappable, are used just like a user 
pointer, just in "high-performance memory" instead of RAM. The subsequent 
function calls using the pixel buffer convert it, just like your data 
pointer, not the mapping of the buffer.

> With BufferData though, you know exactly what it's going to do at any given
> time: (re)allocate buffer storage for itself, and copy/convert the given
> buffer data to an internal representation.
>
> >>: It's not really useful to know exactly that it's gonna do a bad thing
> >>: all the time :D. You have no idea how painful (and plain outright
> >>: wrong) is it to allocate memory in your main game loop. It hurts on PC,
> >>: it's a lot more painful on consoles. Just see some of Pete Isensee's
> >>: talks on that.

Yes, but that's why you'd only load the buffer once as soon as possible (like 
on level/object loads), and reuse it for different sources while you continue 
to need it. You wouldn't refill it every time something new needs it. For 
embedded type systems, you'd probably store it in a specific format for the 
implementation and use some client_storage like extension to keep memory 
duplications down.

> >>: I still fail to see why a user-transparent flow of:
>
> Create buffer in AL_STEREO_32F format
> Set as source output target
> play source
> Map buffer for read
> Isn't the choice. The driver can do all the necessary conversions in the
> background, implementations do what they see best and all's transparent
> from the user..

Because IMO, mapping should just map the data into user space (as is what GL 
does), not convert it inline to whatever the app wants. If you map some data 
so it has to be converted, it may not be able to convert it in the buffer (or 
if it can, may not be optimal).. instead it would have to create a temporary 
buffer *somewhere*, convert it to there, then pass that to the application. 
All this is done behind the programs back, which takes away control from it.

I think buffer data conversions should happen in one place: alBufferData (and 
a future alGetBufferData-like function). There, it's converted to/from 
whatever the mixer likes, and the mixer can do whatever it likes with it. 
User functions shouldn't behave differently depending on implementation 
details (this was a short-coming of DirectSound we don't need to copy). The 
fewer gotcha's the better.


More information about the Openal-devel mailing list