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:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user