Avoid resupplying unneeded source updates

The source's voice holds a copy of the last properties it received, so listener
updates can make sources recalculate internal properties from that stored copy.
This commit is contained in:
Chris Robinson
2016-08-23 18:56:01 -07:00
parent bd054632e0
commit dc8b7814c7
6 changed files with 90 additions and 91 deletions
+2 -2
View File
@@ -1602,8 +1602,6 @@ void ALCcontext_ProcessUpdates(ALCcontext *context)
{
ALsizei pos;
UpdateListenerProps(context);
LockUIntMapRead(&context->SourceMap);
V0(device->Backend,lock)();
for(pos = 0;pos < context->SourceMap.size;pos++)
@@ -1626,6 +1624,8 @@ void ALCcontext_ProcessUpdates(ALCcontext *context)
}
V0(device->Backend,unlock)();
UnlockUIntMapRead(&context->SourceMap);
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
ReadUnlock(&context->PropLock);
+50 -27
View File
@@ -228,7 +228,7 @@ static ALboolean BsincPrepare(const ALuint increment, BsincState *state)
}
static void CalcListenerParams(ALCcontext *Context)
static ALboolean CalcListenerParams(ALCcontext *Context)
{
ALlistener *Listener = Context->Listener;
ALfloat N[3], V[3], U[3], P[3];
@@ -237,7 +237,7 @@ static void CalcListenerParams(ALCcontext *Context)
aluVector vel;
props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel);
if(!props) return;
if(!props) return AL_FALSE;
/* AT then UP */
N[0] = ATOMIC_LOAD(&props->Forward[0], almemory_order_relaxed);
@@ -288,6 +288,8 @@ static void CalcListenerParams(ALCcontext *Context)
ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
} while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*,
&Listener->FreeList, &first, props) == 0);
return AL_TRUE;
}
static void CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
@@ -1281,7 +1283,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
}
}
static void CalcSourceParams(ALvoice *voice, ALCcontext *context)
static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force)
{
ALsource *source = voice->Source;
const ALbufferlistitem *BufferListItem;
@@ -1289,33 +1291,54 @@ static void CalcSourceParams(ALvoice *voice, ALCcontext *context)
struct ALsourceProps *props;
props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, NULL, almemory_order_acq_rel);
if(!props) return;
BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed);
while(BufferListItem != NULL)
if(!props)
{
const ALbuffer *buffer;
if((buffer=BufferListItem->buffer) != NULL)
if(!force)
return;
BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed);
while(BufferListItem != NULL)
{
if(buffer->FmtChannels == FmtMono)
CalcAttnSourceParams(voice, props, buffer, context);
else
CalcNonAttnSourceParams(voice, props, buffer, context);
break;
const ALbuffer *buffer;
if((buffer=BufferListItem->buffer) != NULL)
{
if(buffer->FmtChannels == FmtMono)
CalcAttnSourceParams(voice, &voice->Props, buffer, context);
else
CalcNonAttnSourceParams(voice, &voice->Props, buffer, context);
break;
}
BufferListItem = BufferListItem->next;
}
BufferListItem = BufferListItem->next;
}
else
{
BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed);
while(BufferListItem != NULL)
{
const ALbuffer *buffer;
if((buffer=BufferListItem->buffer) != NULL)
{
if(buffer->FmtChannels == FmtMono)
CalcAttnSourceParams(voice, props, buffer, context);
else
CalcNonAttnSourceParams(voice, props, buffer, context);
break;
}
BufferListItem = BufferListItem->next;
}
voice->Props = *props;
/* WARNING: A livelock is theoretically possible if another thread keeps
* changing the freelist head without giving this a chance to actually swap
* in the old container (practically impossible with this little code,
* but...).
*/
first = ATOMIC_LOAD(&source->FreeList);
do {
ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
} while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*,
&source->FreeList, &first, props) == 0);
/* WARNING: A livelock is theoretically possible if another thread keeps
* changing the freelist head without giving this a chance to actually swap
* in the old container (practically impossible with this little code,
* but...).
*/
first = ATOMIC_LOAD(&source->FreeList);
do {
ATOMIC_STORE(&props->next, first, almemory_order_relaxed);
} while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*,
&source->FreeList, &first, props) == 0);
}
}
@@ -1327,7 +1350,7 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
IncrementRef(&ctx->UpdateCount);
if(!ATOMIC_LOAD(&ctx->HoldUpdates))
{
CalcListenerParams(ctx);
ALboolean force = CalcListenerParams(ctx);
while(slot)
{
CalcEffectSlotParams(slot, ctx->Device);
@@ -1342,7 +1365,7 @@ static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot)
if(source->state != AL_PLAYING && source->state != AL_PAUSED)
voice->Source = NULL;
else
CalcSourceParams(voice, ctx);
CalcSourceParams(voice, ctx, force);
}
}
IncrementRef(&ctx->UpdateCount);
+37 -34
View File
@@ -22,40 +22,6 @@ typedef struct ALbufferlistitem {
} ALbufferlistitem;
typedef struct ALvoice {
struct ALsource *volatile Source;
/** Current target parameters used for mixing. */
ALint Step;
/* If not 'moving', gain/coefficients are set directly without fading. */
ALboolean Moving;
ALboolean IsHrtf;
ALuint Offset; /* Number of output samples mixed since starting. */
alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
BsincState SincState;
struct {
ALfloat (*Buffer)[BUFFERSIZE];
ALuint Channels;
} DirectOut;
struct {
ALfloat (*Buffer)[BUFFERSIZE];
ALuint Channels;
} SendOut[MAX_SENDS];
struct {
DirectParams Direct;
SendParams Send[MAX_SENDS];
} Chan[MAX_INPUT_CHANNELS];
} ALvoice;
struct ALsourceProps {
ATOMIC(ALfloat) Pitch;
ATOMIC(ALfloat) Gain;
@@ -108,6 +74,43 @@ struct ALsourceProps {
ATOMIC(struct ALsourceProps*) next;
};
typedef struct ALvoice {
struct ALsourceProps Props;
struct ALsource *volatile Source;
/** Current target parameters used for mixing. */
ALint Step;
/* If not 'moving', gain/coefficients are set directly without fading. */
ALboolean Moving;
ALboolean IsHrtf;
ALuint Offset; /* Number of output samples mixed since starting. */
alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
BsincState SincState;
struct {
ALfloat (*Buffer)[BUFFERSIZE];
ALuint Channels;
} DirectOut;
struct {
ALfloat (*Buffer)[BUFFERSIZE];
ALuint Channels;
} SendOut[MAX_SENDS];
struct {
DirectParams Direct;
SendParams Send[MAX_SENDS];
} Chan[MAX_INPUT_CHANNELS];
} ALvoice;
typedef struct ALsource {
/** Source properties. */
ALfloat Pitch;
+1 -1
View File
@@ -210,7 +210,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
slot->AuxSendAuto = value;
UpdateEffectSlotProps(slot);
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
UpdateAllSourceProps(context);
UpdateListenerProps(context);
break;
default:
-18
View File
@@ -52,10 +52,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
@@ -93,10 +90,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
@@ -149,10 +143,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
@@ -174,10 +165,7 @@ AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
@@ -207,10 +195,7 @@ AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, A
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
@@ -256,10 +241,7 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
done:
WriteUnlock(&context->PropLock);
-9
View File
@@ -557,10 +557,7 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
WriteLock(&context->PropLock);
context->DopplerFactor = value;
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
WriteUnlock(&context->PropLock);
done:
@@ -580,10 +577,7 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
WriteLock(&context->PropLock);
context->DopplerVelocity = value;
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
WriteUnlock(&context->PropLock);
done:
@@ -603,10 +597,7 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
WriteLock(&context->PropLock);
context->SpeedOfSound = value;
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
{
UpdateListenerProps(context);
UpdateAllSourceProps(context);
}
WriteUnlock(&context->PropLock);
done: