Use a linked list for active effect slots
This commit is contained in:
parent
4b8aa9caf1
commit
8aa4a74a7b
@ -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;
|
||||
|
||||
|
40
Alc/ALu.c
40
Alc/ALu.c
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -711,7 +711,7 @@ struct ALCcontext_struct {
|
||||
ALsizei VoiceCount;
|
||||
ALsizei MaxVoices;
|
||||
|
||||
VECTOR(struct ALeffectslot*) ActiveAuxSlots;
|
||||
ATOMIC(struct ALeffectslot*) ActiveAuxSlotList;
|
||||
|
||||
ALCdevice *Device;
|
||||
const ALCchar *ExtensionList;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user