diff options
author | Chris Robinson <[email protected]> | 2018-01-27 01:51:01 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2018-01-27 01:51:01 -0800 |
commit | 9613b4bfe24cbefba0f4c9c738ebd30d4b116970 (patch) | |
tree | 99c21c7dd7834f8bc9b44db7801e2d77c1df4030 /OpenAL32/alSource.c | |
parent | 5d2196c119f376ca6e58e23b43d4ffbaf4c68c12 (diff) |
Use a different method for storing and looking up buffers
Rather than each buffer being individually allocated with a generated 'thunk'
ID that's used with a uint:ptr map, buffers are allocated in arrays of 64
within a vector. Each group of 64 has an associated 64-bit mask indicating
which are free to use, and the buffer ID is comprised of the two array indices
which directly locate the buffer (no searching, binary or otherwise).
Currently no buffers are actually deallocated after being allocated, though
they are reused. So an app that creates a ton of buffers once, then deletes
them all and uses only a couple from then on, will have a bit of waste, while
an app that's more consistent with the number of used buffers won't be a
problem. This can be improved by removing elements of the containing vector
that contain all-free buffers while there are plenty of other free buffers.
Also, this method can easily be applied to other resources, like sources.
Diffstat (limited to 'OpenAL32/alSource.c')
-rw-r--r-- | OpenAL32/alSource.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 898e54d6..17d57852 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -56,6 +56,21 @@ static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *conte static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALsizei *frac); static ALboolean ApplyOffset(ALsource *Source, ALvoice *voice); +static inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) +{ + BufferSubList *sublist; + ALuint lidx = (id-1) >> 6; + ALsizei slidx = (id-1) & 0x3f; + + if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList))) + return NULL; + sublist = &VECTOR_ELEM(device->BufferList, lidx); + if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx))) + return NULL; + return sublist->Buffers + slidx; +} + + typedef enum SourceProp { srcPitch = AL_PITCH, srcGain = AL_GAIN, @@ -757,10 +772,10 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p return AL_TRUE; case AL_BUFFER: - LockBuffersRead(device); + LockBufferList(device); if(!(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL)) { - UnlockBuffersRead(device); + UnlockBufferList(device); SETERR_RETURN(Context, AL_INVALID_VALUE, AL_FALSE, "Invalid buffer ID %u", *values); } @@ -770,7 +785,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) { WriteUnlock(&Source->queue_lock); - UnlockBuffersRead(device); + UnlockBufferList(device); SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE, "Setting non-persistently mapped buffer %u", buffer->id); } @@ -780,7 +795,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p if(state == AL_PLAYING || state == AL_PAUSED) { WriteUnlock(&Source->queue_lock); - UnlockBuffersRead(device); + UnlockBufferList(device); SETERR_RETURN(Context, AL_INVALID_OPERATION, AL_FALSE, "Setting buffer on playing or paused source %u", Source->id); } @@ -808,7 +823,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp p Source->queue = NULL; } WriteUnlock(&Source->queue_lock); - UnlockBuffersRead(device); + UnlockBufferList(device); /* Delete all elements in the previous queue */ while(oldlist != NULL) @@ -2879,7 +2894,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } - LockBuffersRead(device); + LockBufferList(device); BufferListStart = NULL; BufferList = NULL; for(i = 0;i < nb;i++) @@ -2950,7 +2965,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu al_free(BufferListStart); BufferListStart = next; } - UnlockBuffersRead(device); + UnlockBufferList(device); goto done; } } @@ -2965,7 +2980,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu } BufferList = ATOMIC_LOAD(&BufferList->next, almemory_order_relaxed); } - UnlockBuffersRead(device); + UnlockBufferList(device); /* Source is now streaming */ source->SourceType = AL_STREAMING; |