Use a linked list for active effect slots

This commit is contained in:
Chris Robinson 2016-05-29 01:40:16 -07:00
parent 4b8aa9caf1
commit 8aa4a74a7b
5 changed files with 59 additions and 60 deletions

View File

@ -2324,8 +2324,6 @@ static void FreeContext(ALCcontext *context)
context->VoiceCount = 0;
context->MaxVoices = 0;
VECTOR_DEINIT(context->ActiveAuxSlots);
if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL)
{
TRACE("Freed unapplied listener update %p\n", lprops);
@ -3115,7 +3113,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
InitRef(&ALContext->ref, 1);
ALContext->Listener = (ALlistener*)ALContext->_listener_mem;
VECTOR_INIT(ALContext->ActiveAuxSlots);
ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL);
ALContext->VoiceCount = 0;
ALContext->MaxVoices = 256;
@ -3130,8 +3128,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
al_free(ALContext->Voices);
ALContext->Voices = NULL;
VECTOR_DEINIT(ALContext->ActiveAuxSlots);
al_free(ALContext);
ALContext = NULL;
}
@ -3148,8 +3144,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
al_free(ALContext->Voices);
ALContext->Voices = NULL;
VECTOR_DEINIT(ALContext->ActiveAuxSlots);
al_free(ALContext);
ALContext = NULL;

View File

@ -1320,7 +1320,7 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context)
}
static void UpdateContextSources(ALCcontext *ctx)
static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
{
ALvoice *voice, *voice_end;
ALsource *source;
@ -1329,9 +1329,11 @@ static void UpdateContextSources(ALCcontext *ctx)
if(!ATOMIC_LOAD(&ctx->HoldUpdates))
{
CalcListenerParams(ctx);
#define UPDATE_SLOT(iter) CalcEffectSlotParams(*iter, ctx->Device)
VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, UPDATE_SLOT);
#undef UPDATE_SLOT
while(slot)
{
CalcEffectSlotParams(slot, ctx->Device);
slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
}
voice = ctx->Voices;
voice_end = voice + ctx->VoiceCount;
@ -1440,13 +1442,18 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
ctx = ATOMIC_LOAD(&device->ContextList);
while(ctx)
{
UpdateContextSources(ctx);
#define CLEAR_WET_BUFFER(iter) do { \
for(i = 0;i < (*iter)->NumChannels;i++) \
memset((*iter)->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); \
} while(0)
VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, CLEAR_WET_BUFFER);
#undef CLEAR_WET_BUFFER
ALeffectslot *slotroot;
slotroot = ATOMIC_LOAD(&ctx->ActiveAuxSlotList);
UpdateContextSources(ctx, slotroot);
slot = slotroot;
while(slot)
{
for(i = 0;i < slot->NumChannels;i++)
memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat));
slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
}
/* source processing */
voice = ctx->Voices;
@ -1459,13 +1466,14 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
}
/* effect slot processing */
c = VECTOR_SIZE(ctx->ActiveAuxSlots);
for(i = 0;i < c;i++)
slot = slotroot;
while(slot)
{
const ALeffectslot *slot = VECTOR_ELEM(ctx->ActiveAuxSlots, i);
ALeffectState *state = slot->Params.EffectState;
V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
const ALeffectslot *cslot = slot;
ALeffectState *state = cslot->Params.EffectState;
V(state,process)(SamplesToDo, cslot->WetBuffer, state->OutBuffer,
state->OutChannels);
slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
}
ctx = ctx->next;

View File

@ -129,6 +129,8 @@ typedef struct ALeffectslot {
* first-order device output (FOAOut).
*/
alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
ATOMIC(struct ALeffectslot*) next;
} ALeffectslot;
inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)

View File

@ -711,7 +711,7 @@ struct ALCcontext_struct {
ALsizei VoiceCount;
ALsizei MaxVoices;
VECTOR(struct ALeffectslot*) ActiveAuxSlots;
ATOMIC(struct ALeffectslot*) ActiveAuxSlotList;
ALCdevice *Device;
const ALCchar *ExtensionList;

View File

@ -38,8 +38,8 @@
extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
static ALenum AddEffectSlotArray(ALCcontext *Context, ALeffectslot **start, ALsizei count);
static void RemoveEffectSlotArray(ALCcontext *Context, const ALeffectslot *slot);
static void AddEffectSlotList(ALCcontext *Context, ALeffectslot *first, ALeffectslot *last);
static void RemoveEffectSlotList(ALCcontext *Context, const ALeffectslot *slot);
static UIntMap EffectStateFactoryMap;
@ -55,20 +55,17 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type)
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
{
ALCcontext *context;
VECTOR(ALeffectslot*) slotvec;
ALeffectslot *first, *last;
ALsizei cur;
ALenum err;
context = GetContextRef();
if(!context) return;
VECTOR_INIT(slotvec);
if(!(n >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(!VECTOR_RESERVE(slotvec, n))
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
first = last = NULL;
for(cur = 0;cur < n;cur++)
{
ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
@ -95,20 +92,15 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
aluInitEffectPanning(slot);
VECTOR_PUSH_BACK(slotvec, slot);
if(!first) first = slot;
if(last) ATOMIC_STORE(&last->next, slot);
last = slot;
effectslots[cur] = slot->id;
}
err = AddEffectSlotArray(context, VECTOR_BEGIN(slotvec), n);
if(err != AL_NO_ERROR)
{
alDeleteAuxiliaryEffectSlots(cur, effectslots);
SET_ERROR_AND_GOTO(context, err, done);
}
AddEffectSlotList(context, first, last);
done:
VECTOR_DEINIT(slotvec);
ALCcontext_DecRef(context);
}
@ -138,7 +130,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
continue;
FreeThunkEntry(slot->id);
RemoveEffectSlotArray(context, slot);
RemoveEffectSlotList(context, slot);
DeinitEffectSlot(slot);
memset(slot, 0, sizeof(*slot));
@ -399,32 +391,33 @@ done:
}
static ALenum AddEffectSlotArray(ALCcontext *context, ALeffectslot **start, ALsizei count)
static void AddEffectSlotList(ALCcontext *context, ALeffectslot *start, ALeffectslot *last)
{
ALenum err = AL_NO_ERROR;
LockContext(context);
if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_END(context->ActiveAuxSlots), start, start+count))
err = AL_OUT_OF_MEMORY;
UnlockContext(context);
return err;
ALeffectslot *root = ATOMIC_LOAD(&context->ActiveAuxSlotList);
do {
ATOMIC_STORE(&last->next, root, almemory_order_relaxed);
} while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALeffectslot*, &context->ActiveAuxSlotList,
&root, start));
}
static void RemoveEffectSlotArray(ALCcontext *context, const ALeffectslot *slot)
static void RemoveEffectSlotList(ALCcontext *context, const ALeffectslot *slot)
{
ALeffectslot **iter;
ALCdevice *device = context->Device;
const ALeffectslot *root, *next;
LockContext(context);
#define MATCH_SLOT(_i) (slot == *(_i))
VECTOR_FIND_IF(iter, ALeffectslot*, context->ActiveAuxSlots, MATCH_SLOT);
if(iter != VECTOR_END(context->ActiveAuxSlots))
root = slot;
next = ATOMIC_LOAD(&slot->next);
if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &context->ActiveAuxSlotList, &root, next))
{
*iter = VECTOR_BACK(context->ActiveAuxSlots);
VECTOR_POP_BACK(context->ActiveAuxSlots);
const ALeffectslot *cur;
do {
cur = root;
root = slot;
} while(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &cur->next, &root, next));
}
#undef MATCH_SLOT
UnlockContext(context);
/* Wait for any mix that may be using these effect slots to finish. */
while((ReadRef(&device->MixCount)&1) != 0)
althrd_yield();
}
@ -539,6 +532,8 @@ ALenum InitEffectSlot(ALeffectslot *slot)
slot->Params.DecayTime = 0.0f;
slot->Params.AirAbsorptionGainHF = 1.0f;
ATOMIC_INIT(&slot->next, NULL);
return AL_NO_ERROR;
}