Properly defer effect slot changes
Note that this now also causes all playing sources to update when an effect slot is updated. This is a bit wasteful, as it should only need to re-update sources that are using the effect slot (and only when a relevant property is changed), but it's good enough. Especially with deferring since all playing sources are going to get updated on the process call anyway.
This commit is contained in:
@@ -1611,6 +1611,7 @@ void ALCcontext_ProcessUpdates(ALCcontext *context)
|
||||
althrd_yield();
|
||||
|
||||
UpdateListenerProps(context);
|
||||
UpdateAllEffectSlotProps(context);
|
||||
|
||||
LockUIntMapRead(&context->SourceMap);
|
||||
V0(device->Backend,lock)();
|
||||
|
||||
@@ -295,14 +295,14 @@ static ALboolean CalcListenerParams(ALCcontext *Context)
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
static void CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
|
||||
static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
|
||||
{
|
||||
struct ALeffectslotProps *first;
|
||||
struct ALeffectslotProps *props;
|
||||
ALeffectState *state;
|
||||
|
||||
props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel);
|
||||
if(!props) return;
|
||||
if(!props) return AL_FALSE;
|
||||
|
||||
slot->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed);
|
||||
slot->Params.AuxSendAuto = ATOMIC_LOAD(&props->AuxSendAuto, almemory_order_relaxed);
|
||||
@@ -339,6 +339,8 @@ static void CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
|
||||
ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
|
||||
} while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*,
|
||||
&slot->FreeList, &first, props) == 0);
|
||||
|
||||
return AL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -1339,7 +1341,7 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
|
||||
ALboolean force = CalcListenerParams(ctx);
|
||||
while(slot)
|
||||
{
|
||||
CalcEffectSlotParams(slot, ctx->Device);
|
||||
force |= CalcEffectSlotParams(slot, ctx->Device);
|
||||
slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ struct ALeffectslotProps {
|
||||
|
||||
|
||||
typedef struct ALeffectslot {
|
||||
ALboolean NeedsUpdate;
|
||||
|
||||
ALfloat Gain;
|
||||
ALboolean AuxSendAuto;
|
||||
|
||||
@@ -152,6 +154,7 @@ inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id)
|
||||
ALenum InitEffectSlot(ALeffectslot *slot);
|
||||
void DeinitEffectSlot(ALeffectslot *slot);
|
||||
void UpdateEffectSlotProps(ALeffectslot *slot);
|
||||
void UpdateAllEffectSlotProps(ALCcontext *context);
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
|
||||
|
||||
|
||||
|
||||
+28
-11
@@ -56,6 +56,13 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type)
|
||||
static void ALeffectState_IncRef(ALeffectState *state);
|
||||
static void ALeffectState_DecRef(ALeffectState *state);
|
||||
|
||||
#define DO_UPDATEPROPS() do { \
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
|
||||
UpdateEffectSlotProps(slot); \
|
||||
else \
|
||||
slot->NeedsUpdate = AL_TRUE; \
|
||||
} while(0)
|
||||
|
||||
|
||||
AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
|
||||
{
|
||||
@@ -212,14 +219,12 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
|
||||
if(!(value == AL_TRUE || value == AL_FALSE))
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
slot->AuxSendAuto = value;
|
||||
UpdateEffectSlotProps(slot);
|
||||
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
||||
UpdateListenerProps(context);
|
||||
break;
|
||||
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
DO_UPDATEPROPS();
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
@@ -279,7 +284,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
|
||||
default:
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
||||
}
|
||||
UpdateEffectSlotProps(slot);
|
||||
DO_UPDATEPROPS();
|
||||
|
||||
done:
|
||||
UnlockEffectSlotsRead(context);
|
||||
@@ -517,13 +522,9 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
|
||||
|
||||
ALeffectState_DecRef(EffectSlot->Effect.State);
|
||||
EffectSlot->Effect.State = State;
|
||||
UpdateEffectSlotProps(EffectSlot);
|
||||
}
|
||||
else if(effect)
|
||||
{
|
||||
EffectSlot->Effect.Props = effect->Props;
|
||||
UpdateEffectSlotProps(EffectSlot);
|
||||
}
|
||||
|
||||
/* Remove state references from old effect slot property updates. */
|
||||
props = ATOMIC_LOAD(&EffectSlot->FreeList);
|
||||
@@ -531,7 +532,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
|
||||
{
|
||||
State = ATOMIC_EXCHANGE(ALeffectState*, &props->State, NULL, almemory_order_relaxed);
|
||||
if(State) ALeffectState_DecRef(State);
|
||||
ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
||||
}
|
||||
|
||||
return AL_NO_ERROR;
|
||||
@@ -577,6 +578,7 @@ ALenum InitEffectSlot(ALeffectslot *slot)
|
||||
if(!(slot->Effect.State=V0(factory,create)()))
|
||||
return AL_OUT_OF_MEMORY;
|
||||
|
||||
slot->NeedsUpdate = AL_FALSE;
|
||||
slot->Gain = 1.0;
|
||||
slot->AuxSendAuto = AL_TRUE;
|
||||
InitRef(&slot->ref, 0);
|
||||
@@ -661,8 +663,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
|
||||
/* Swap out any stale effect state object there may be in the container, to
|
||||
* delete it.
|
||||
*/
|
||||
if(slot->Effect.State)
|
||||
ALeffectState_IncRef(slot->Effect.State);
|
||||
ALeffectState_IncRef(slot->Effect.State);
|
||||
oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Effect.State,
|
||||
almemory_order_relaxed);
|
||||
|
||||
@@ -685,6 +686,22 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
|
||||
ALeffectState_DecRef(oldstate);
|
||||
}
|
||||
|
||||
void UpdateAllEffectSlotProps(ALCcontext *context)
|
||||
{
|
||||
ALeffectslot *slot;
|
||||
|
||||
LockEffectSlotsRead(context);
|
||||
slot = ATOMIC_LOAD(&context->ActiveAuxSlotList);
|
||||
while(slot)
|
||||
{
|
||||
if(slot->NeedsUpdate)
|
||||
UpdateEffectSlotProps(slot);
|
||||
slot->NeedsUpdate = AL_FALSE;
|
||||
slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed);
|
||||
}
|
||||
UnlockEffectSlotsRead(context);
|
||||
}
|
||||
|
||||
ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
|
||||
{
|
||||
ALsizei pos;
|
||||
|
||||
Reference in New Issue
Block a user