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

William Stewart bills at apple.com
Tue Feb 26 11:42:31 PST 2008


We've added a simple extension to OpenAL for MacOS X that I think  
might be related to this. Sorry if this is off topic (I haven't read  
through all of the posts), but it seems similar at a cursory glance.

We had requests from developers to provide access to the OAL buffers  
to avoid the copy from the buffer the app is filling which would then  
get copied into the al buffer object.

The extension looks like this:

typedef ALvoid	AL_APIENTRY	(*alBufferDataStaticProcPtr) (const ALint  
bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq);

So, this works in a similar way to the alBufferData API, except that  
the application owns the memory - it uses the dataPtr the application  
provides directly instead of copying into an internal buffer. The  
application's responsibility is to keep this buffer pointer valid and  
untouched as long as this buffer is in use. So, the contract is  
similar for the applications responsibility with regards to the life  
cycle of an alBuffer (the buffer must not be deleted while it is in  
use by an alSource object)

Bill

On Feb 25, 2008, at 7:20 PM, Chris Robinson wrote:

> 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.
> _______________________________________________
> Openal-devel mailing list
> Openal-devel at opensource.creative.com
> http://opensource.creative.com/mailman/listinfo/openal-devel



More information about the Openal-devel mailing list