[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