Use a normal vector for buffer sublists

This commit is contained in:
Chris Robinson 2018-11-18 22:31:51 -08:00
parent becbaab2dc
commit 81aed2ea01
4 changed files with 44 additions and 49 deletions

View File

@ -2388,7 +2388,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
ALCdevice_struct::ALCdevice_struct(DeviceType type)
: Type{type}
{
VECTOR_INIT(BufferList);
almtx_init(&BufferLock, almtx_plain);
VECTOR_INIT(EffectList);
@ -2416,10 +2415,11 @@ ALCdevice_struct::~ALCdevice_struct()
almtx_destroy(&BackendLock);
ReleaseALBuffers(this);
#define FREE_BUFFERSUBLIST(x) al_free((x)->Buffers)
VECTOR_FOR_EACH(BufferSubList, BufferList, FREE_BUFFERSUBLIST);
#undef FREE_BUFFERSUBLIST
VECTOR_DEINIT(BufferList);
std::for_each(BufferList.begin(), BufferList.end(),
[](BufferSubList &entry) noexcept -> void
{ al_free(entry.Buffers); }
);
BufferList.clear();
almtx_destroy(&BufferLock);
ReleaseALEffects(this);

View File

@ -509,10 +509,9 @@ typedef union AmbiConfig {
typedef struct BufferSubList {
ALuint64 FreeMask;
struct ALbuffer *Buffers; /* 64 */
ALuint64 FreeMask{0u};
struct ALbuffer *Buffers{nullptr}; /* 64 */
} BufferSubList;
TYPEDEF_VECTOR(BufferSubList, vector_BufferSubList)
typedef struct EffectSubList {
ALuint64 FreeMask;
@ -606,7 +605,7 @@ struct ALCdevice_struct {
ALsizei NumAuxSends{};
// Map of Buffers for this device
vector_BufferSubList BufferList{};
al::vector<BufferSubList> BufferList;
almtx_t BufferLock;
// Map of Effects for this device

View File

@ -55,40 +55,37 @@ ALbuffer *AllocBuffer(ALCcontext *context)
ALCdevice *device = context->Device;
std::unique_lock<almtx_t> buflock{device->BufferLock};
auto sublist = std::find_if(device->BufferList.begin(), device->BufferList.end(),
[](const BufferSubList &entry) noexcept -> bool
{ return entry.FreeMask != 0; }
);
auto lidx = std::distance(device->BufferList.begin(), sublist);
ALbuffer *buffer{nullptr};
ALsizei lidx{0}, slidx{0};
BufferSubList *sublist{VECTOR_BEGIN(device->BufferList)};
BufferSubList *subend{VECTOR_END(device->BufferList)};
for(;sublist != subend;++sublist)
ALsizei slidx{0};
if(LIKELY(sublist != device->BufferList.end()))
{
if(sublist->FreeMask)
{
slidx = CTZ64(sublist->FreeMask);
buffer = sublist->Buffers + slidx;
break;
}
++lidx;
slidx = CTZ64(sublist->FreeMask);
buffer = sublist->Buffers + slidx;
}
if(UNLIKELY(!buffer))
else
{
static constexpr BufferSubList empty_sublist{ 0, nullptr };
/* Don't allocate so many list entries that the 32-bit ID could
* overflow...
*/
if(UNLIKELY(VECTOR_SIZE(device->BufferList) >= 1<<25))
if(UNLIKELY(device->BufferList.size() >= 1<<25))
{
buflock.unlock();
alSetError(context, AL_OUT_OF_MEMORY, "Too many buffers allocated");
return nullptr;
}
lidx = (ALsizei)VECTOR_SIZE(device->BufferList);
VECTOR_PUSH_BACK(device->BufferList, empty_sublist);
sublist = &VECTOR_BACK(device->BufferList);
device->BufferList.emplace_back();
sublist = device->BufferList.end() - 1;
sublist->FreeMask = ~U64(0);
sublist->Buffers = reinterpret_cast<ALbuffer*>(al_calloc(16, sizeof(ALbuffer)*64));
if(UNLIKELY(!sublist->Buffers))
{
VECTOR_POP_BACK(device->BufferList);
device->BufferList.pop_back();
buflock.unlock();
alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate buffer batch");
return nullptr;
@ -98,8 +95,7 @@ ALbuffer *AllocBuffer(ALCcontext *context)
buffer = sublist->Buffers + slidx;
}
memset(buffer, 0, sizeof(*buffer));
buffer = new (buffer) ALbuffer{};
/* Add 1 to avoid buffer ID 0. */
buffer->id = ((lidx<<6) | slidx) + 1;
@ -115,9 +111,10 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer)
ALsizei slidx = id & 0x3f;
al_free(buffer->data);
memset(buffer, 0, sizeof(*buffer));
buffer->data = nullptr;
buffer->~ALbuffer();
VECTOR_ELEM(device->BufferList, lidx).FreeMask |= U64(1) << slidx;
device->BufferList[lidx].FreeMask |= U64(1) << slidx;
}
inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
@ -125,12 +122,12 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
ALuint lidx = (id-1) >> 6;
ALsizei slidx = (id-1) & 0x3f;
if(UNLIKELY(lidx >= VECTOR_SIZE(device->BufferList)))
if(UNLIKELY(lidx >= device->BufferList.size()))
return nullptr;
BufferSubList *sublist{&VECTOR_ELEM(device->BufferList, lidx)};
if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
BufferSubList &sublist = device->BufferList[lidx];
if(UNLIKELY(sublist.FreeMask & (U64(1)<<slidx)))
return nullptr;
return sublist->Buffers + slidx;
return sublist.Buffers + slidx;
}
@ -1187,24 +1184,24 @@ ALsizei ChannelsFromFmt(FmtChannels chans)
*/
ALvoid ReleaseALBuffers(ALCdevice *device)
{
BufferSubList *sublist = VECTOR_BEGIN(device->BufferList);
BufferSubList *subend = VECTOR_END(device->BufferList);
size_t leftover = 0;
for(;sublist != subend;++sublist)
for(auto &sublist : device->BufferList)
{
ALuint64 usemask = ~sublist->FreeMask;
ALuint64 usemask = ~sublist.FreeMask;
while(usemask)
{
ALsizei idx = CTZ64(usemask);
ALbuffer *buffer = sublist->Buffers + idx;
ALbuffer *buffer = sublist.Buffers + idx;
al_free(buffer->data);
memset(buffer, 0, sizeof(*buffer));
buffer->data = nullptr;
buffer->~ALbuffer();
++leftover;
usemask &= ~(U64(1) << idx);
}
sublist->FreeMask = ~usemask;
sublist.FreeMask = ~usemask;
}
if(leftover > 0)
WARN("(%p) Deleted " SZFMT " Buffer%s\n", device, leftover, (leftover==1)?"":"s");

View File

@ -76,16 +76,15 @@ static inline ALsource *LookupSource(ALCcontext *context, ALuint id)
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;
if(UNLIKELY(lidx >= device->BufferList.size()))
return nullptr;
BufferSubList &sublist = device->BufferList[lidx];
if(UNLIKELY(sublist.FreeMask & (U64(1)<<slidx)))
return nullptr;
return sublist.Buffers + slidx;
}
static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)