aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-09-27 08:55:42 -0700
committerChris Robinson <[email protected]>2017-09-27 08:55:42 -0700
commit101d284a1801532e12b7867aed3499896d7a9a6f (patch)
treec9ae9c08e48b5c0a0dd579b43de40887a8e22a8d
parent2f6613905399aa06a253a421352e6fff57a1dce1 (diff)
Update the context state properties separately
The context state properties are less likely to change compared to the listener state, and future changes may prefer more infrequent updates to the context state. Note that this puts the MetersPerUnit in as a context state, even though it's handled through the listener functions. Considering the infrequency that it's updated at (generally set just once for the context's lifetime), it makes more sense to put it there than with the more frequently updated listener properties. The aforementioned future changes would also prefer MetersPerUnit to not be updated unnecessarily.
-rw-r--r--Alc/ALc.c51
-rw-r--r--Alc/ALu.c52
-rw-r--r--OpenAL32/Include/alListener.h19
-rw-r--r--OpenAL32/Include/alMain.h5
-rw-r--r--OpenAL32/Include/alu.h2
-rw-r--r--OpenAL32/alListener.c18
-rw-r--r--OpenAL32/alState.c51
7 files changed, 138 insertions, 60 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 901b5447..cef5749d 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1669,6 +1669,7 @@ void ALCcontext_ProcessUpdates(ALCcontext *context)
while((ATOMIC_LOAD(&context->UpdateCount, almemory_order_acquire)&1) != 0)
althrd_yield();
+ UpdateContextProps(context);
UpdateListenerProps(context);
UpdateAllEffectSlotProps(context);
UpdateAllSourceProps(context);
@@ -2519,7 +2520,6 @@ static ALvoid InitContext(ALCcontext *Context)
//Initialise listener
listener->Gain = 1.0f;
- listener->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
listener->Position[0] = 0.0f;
listener->Position[1] = 0.0f;
listener->Position[2] = 0.0f;
@@ -2533,19 +2533,6 @@ static ALvoid InitContext(ALCcontext *Context)
listener->Up[1] = 1.0f;
listener->Up[2] = 0.0f;
- aluMatrixfSet(&listener->Params.Matrix,
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- );
- aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
- listener->Params.Gain = 1.0f;
- listener->Params.MetersPerUnit = listener->MetersPerUnit;
- listener->Params.DopplerFactor = 1.0f;
- listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
- listener->Params.ReverbSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
-
ATOMIC_INIT(&listener->Update, NULL);
ATOMIC_INIT(&listener->FreeList, NULL);
@@ -2577,9 +2564,28 @@ static ALvoid InitContext(ALCcontext *Context)
Context->DopplerFactor = 1.0f;
Context->DopplerVelocity = 1.0f;
Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
+ Context->MetersPerUnit = AL_DEFAULT_METERS_PER_UNIT;
ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE);
+ ATOMIC_INIT(&Context->Update, NULL);
+ ATOMIC_INIT(&Context->FreeList, NULL);
+
Context->ExtensionList = alExtList;
+
+
+ aluMatrixfSet(&listener->Params.Matrix,
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ );
+ aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
+ listener->Params.Gain = listener->Gain;
+ listener->Params.MetersPerUnit = Context->MetersPerUnit;
+ listener->Params.DopplerFactor = Context->DopplerFactor;
+ listener->Params.SpeedOfSound = Context->SpeedOfSound * Context->DopplerVelocity;
+ listener->Params.ReverbSpeedOfSound = listener->Params.SpeedOfSound *
+ listener->Params.MetersPerUnit;
}
@@ -2593,11 +2599,28 @@ static void FreeContext(ALCcontext *context)
ALlistener *listener = context->Listener;
struct ALeffectslotArray *auxslots;
struct ALlistenerProps *lprops;
+ struct ALcontextProps *cprops;
size_t count;
ALsizei i;
TRACE("%p\n", context);
+ if((cprops=ATOMIC_LOAD(&context->Update, almemory_order_acquire)) != NULL)
+ {
+ TRACE("Freed unapplied context update %p\n", cprops);
+ al_free(cprops);
+ }
+ count = 0;
+ cprops = ATOMIC_LOAD(&context->FreeList, almemory_order_acquire);
+ while(cprops)
+ {
+ struct ALcontextProps *next = ATOMIC_LOAD(&cprops->next, almemory_order_acquire);
+ al_free(cprops);
+ cprops = next;
+ ++count;
+ }
+ TRACE("Freed "SZFMT" context property object%s\n", count, (count==1)?"":"s");
+
if(context->DefaultSlot)
{
DeinitEffectSlot(context->DefaultSlot);
diff --git a/Alc/ALu.c b/Alc/ALu.c
index a2ea4811..20b2d817 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -271,7 +271,30 @@ ALboolean BsincPrepare(const ALuint increment, BsincState *state, const BSincTab
}
-static ALboolean CalcListenerParams(ALCcontext *Context)
+static bool CalcContextParams(ALCcontext *Context)
+{
+ ALlistener *Listener = Context->Listener;
+ struct ALcontextProps *props;
+
+ props = ATOMIC_EXCHANGE_PTR(&Context->Update, NULL, almemory_order_acq_rel);
+ if(!props) return false;
+
+ Listener->Params.MetersPerUnit = props->MetersPerUnit;
+
+ Listener->Params.DopplerFactor = props->DopplerFactor;
+ Listener->Params.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity;
+ if(!OverrideReverbSpeedOfSound)
+ Listener->Params.ReverbSpeedOfSound = Listener->Params.SpeedOfSound *
+ Listener->Params.MetersPerUnit;
+
+ Listener->Params.SourceDistanceModel = props->SourceDistanceModel;
+ Listener->Params.DistanceModel = props->DistanceModel;
+
+ ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &Context->FreeList, props);
+ return true;
+}
+
+static bool CalcListenerParams(ALCcontext *Context)
{
ALlistener *Listener = Context->Listener;
ALfloat N[3], V[3], U[3], P[3];
@@ -279,7 +302,7 @@ static ALboolean CalcListenerParams(ALCcontext *Context)
aluVector vel;
props = ATOMIC_EXCHANGE_PTR(&Listener->Update, NULL, almemory_order_acq_rel);
- if(!props) return AL_FALSE;
+ if(!props) return false;
/* AT then UP */
N[0] = props->Forward[0];
@@ -311,30 +334,18 @@ static ALboolean CalcListenerParams(ALCcontext *Context)
Listener->Params.Velocity = aluMatrixfVector(&Listener->Params.Matrix, &vel);
Listener->Params.Gain = props->Gain * Context->GainBoost;
- Listener->Params.MetersPerUnit = props->MetersPerUnit;
-
- Listener->Params.DopplerFactor = props->DopplerFactor;
- Listener->Params.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity;
- if(OverrideReverbSpeedOfSound)
- Listener->Params.ReverbSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
- else
- Listener->Params.ReverbSpeedOfSound = Listener->Params.SpeedOfSound *
- Listener->Params.MetersPerUnit;
-
- Listener->Params.SourceDistanceModel = props->SourceDistanceModel;
- Listener->Params.DistanceModel = props->DistanceModel;
ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &Listener->FreeList, props);
- return AL_TRUE;
+ return true;
}
-static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context)
+static bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context)
{
struct ALeffectslotProps *props;
ALeffectState *state;
props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel);
- if(!props) return AL_FALSE;
+ if(!props) return false;
slot->Params.Gain = props->Gain;
slot->Params.AuxSendAuto = props->AuxSendAuto;
@@ -366,7 +377,7 @@ static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context)
V(state,update)(context, slot, &props->Props);
ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
- return AL_TRUE;
+ return true;
}
@@ -1430,7 +1441,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *prop
WetGainLF, WetGainHF, SendSlots, ALBuffer, props, Listener, Device);
}
-static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force)
+static void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force)
{
ALbufferlistitem *BufferListItem;
struct ALvoiceProps *props;
@@ -1475,7 +1486,8 @@ static void UpdateContextSources(ALCcontext *ctx, const struct ALeffectslotArray
IncrementRef(&ctx->UpdateCount);
if(!ATOMIC_LOAD(&ctx->HoldUpdates, almemory_order_acquire))
{
- ALboolean force = CalcListenerParams(ctx);
+ ALboolean cforce = CalcContextParams(ctx);
+ ALboolean force = CalcListenerParams(ctx) | cforce;
for(i = 0;i < slots->count;i++)
force |= CalcEffectSlotParams(slots->slot[i], ctx);
diff --git a/OpenAL32/Include/alListener.h b/OpenAL32/Include/alListener.h
index eb386f7f..ae66b0e3 100644
--- a/OpenAL32/Include/alListener.h
+++ b/OpenAL32/Include/alListener.h
@@ -8,19 +8,23 @@
extern "C" {
#endif
+struct ALcontextProps {
+ ALfloat DopplerFactor;
+ ALfloat DopplerVelocity;
+ ALfloat SpeedOfSound;
+ ALboolean SourceDistanceModel;
+ enum DistanceModel DistanceModel;
+ ALfloat MetersPerUnit;
+
+ ATOMIC(struct ALcontextProps*) next;
+};
+
struct ALlistenerProps {
ALfloat Position[3];
ALfloat Velocity[3];
ALfloat Forward[3];
ALfloat Up[3];
ALfloat Gain;
- ALfloat MetersPerUnit;
-
- ALfloat DopplerFactor;
- ALfloat DopplerVelocity;
- ALfloat SpeedOfSound;
- ALboolean SourceDistanceModel;
- enum DistanceModel DistanceModel;
ATOMIC(struct ALlistenerProps*) next;
};
@@ -31,7 +35,6 @@ typedef struct ALlistener {
ALfloat Forward[3];
ALfloat Up[3];
ALfloat Gain;
- ALfloat MetersPerUnit;
/* Pointer to the most recent property values that are awaiting an update.
*/
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 614c3b43..95137972 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -382,6 +382,7 @@ struct Hrtf;
struct HrtfEntry;
struct FrontStablizer;
struct Compressor;
+struct ALcontextProps;
#define DEFAULT_OUTPUT_RATE (44100)
@@ -851,6 +852,7 @@ struct ALCcontext_struct {
ALfloat DopplerFactor;
ALfloat DopplerVelocity;
ALfloat SpeedOfSound;
+ ALfloat MetersPerUnit;
ATOMIC(ALenum) DeferUpdates;
RWLock PropLock;
@@ -863,6 +865,9 @@ struct ALCcontext_struct {
ALfloat GainBoost;
+ ATOMIC(struct ALcontextProps*) Update;
+ ATOMIC(struct ALcontextProps*) FreeList;
+
struct ALvoice **Voices;
ALsizei VoiceCount;
ALsizei MaxVoices;
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 1295fee3..2344cc6d 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -514,6 +514,8 @@ void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
/* Caller must lock the device. */
void aluHandleDisconnect(ALCdevice *device);
+void UpdateContextProps(ALCcontext *context);
+
extern ALfloat ConeScale;
extern ALfloat ZScale;
extern ALboolean OverrideReverbSpeedOfSound;
diff --git a/OpenAL32/alListener.c b/OpenAL32/alListener.c
index 5a12673d..a4471539 100644
--- a/OpenAL32/alListener.c
+++ b/OpenAL32/alListener.c
@@ -21,7 +21,7 @@
#include "config.h"
#include "alMain.h"
-#include "AL/alc.h"
+#include "alu.h"
#include "alError.h"
#include "alListener.h"
#include "alSource.h"
@@ -45,8 +45,10 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
case AL_METERS_PER_UNIT:
if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
- context->Listener->MetersPerUnit = value;
- break;
+ context->MetersPerUnit = value;
+ if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ UpdateContextProps(context);
+ goto done;
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
@@ -266,7 +268,7 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
break;
case AL_METERS_PER_UNIT:
- *value = context->Listener->MetersPerUnit;
+ *value = context->MetersPerUnit;
break;
default:
@@ -489,14 +491,6 @@ void UpdateListenerProps(ALCcontext *context)
props->Up[2] = listener->Up[2];
props->Gain = listener->Gain;
- props->MetersPerUnit = listener->MetersPerUnit;
-
- props->DopplerFactor = context->DopplerFactor;
- props->DopplerVelocity = context->DopplerVelocity;
- props->SpeedOfSound = context->SpeedOfSound;
-
- props->SourceDistanceModel = context->SourceDistanceModel;
- props->DistanceModel = context->DistanceModel;;
/* Set the new container for updating internal parameters. */
props = ATOMIC_EXCHANGE_PTR(&listener->Update, props, almemory_order_acq_rel);
diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c
index 48c3498a..86534efb 100644
--- a/OpenAL32/alState.c
+++ b/OpenAL32/alState.c
@@ -72,7 +72,7 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
- UpdateListenerProps(context);
+ UpdateContextProps(context);
done:
WriteUnlock(&context->PropLock);
@@ -97,7 +97,7 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
- UpdateListenerProps(context);
+ UpdateContextProps(context);
done:
WriteUnlock(&context->PropLock);
@@ -648,7 +648,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);
+ UpdateContextProps(context);
WriteUnlock(&context->PropLock);
done:
@@ -668,7 +668,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);
+ UpdateContextProps(context);
WriteUnlock(&context->PropLock);
done:
@@ -688,7 +688,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);
+ UpdateContextProps(context);
WriteUnlock(&context->PropLock);
done:
@@ -713,7 +713,7 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
if(!context->SourceDistanceModel)
{
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
- UpdateListenerProps(context);
+ UpdateContextProps(context);
}
WriteUnlock(&context->PropLock);
@@ -779,3 +779,42 @@ done:
return value;
}
+
+
+void UpdateContextProps(ALCcontext *context)
+{
+ struct ALcontextProps *props;
+
+ /* Get an unused proprty container, or allocate a new one as needed. */
+ props = ATOMIC_LOAD(&context->FreeList, almemory_order_acquire);
+ if(!props)
+ props = al_calloc(16, sizeof(*props));
+ else
+ {
+ struct ALcontextProps *next;
+ do {
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeList, &props, next,
+ almemory_order_seq_cst, almemory_order_acquire) == 0);
+ }
+
+ /* Copy in current property values. */
+ props->MetersPerUnit = context->MetersPerUnit;
+
+ props->DopplerFactor = context->DopplerFactor;
+ props->DopplerVelocity = context->DopplerVelocity;
+ props->SpeedOfSound = context->SpeedOfSound;
+
+ props->SourceDistanceModel = context->SourceDistanceModel;
+ props->DistanceModel = context->DistanceModel;
+
+ /* Set the new container for updating internal parameters. */
+ props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
+ if(props)
+ {
+ /* If there was an unused update container, put it back in the
+ * freelist.
+ */
+ ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeList, props);
+ }
+}