aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-03-04 21:15:32 -0800
committerChris Robinson <[email protected]>2020-03-04 23:18:05 -0800
commit78251fd7e6dc11c63481970be9fa453540951dbd (patch)
tree63f4497c0438ea3ad1ef2a59b2b9bd68b7c49991 /alc
parent48b9b541ec55dc5498409fda6f0a0c788ebe234e (diff)
Fix voices being forced to update without valid properties
When starting a voice, the source ID was set before its first update struct was provided, creating a small window where a listener or effect slot update could force a voice to update without it having any valid properties to update with. Supplying the update struct first would create a different race, where the mixer could see a voice without a source but with an update struct, causing the update struct to be 'freed' without being applied. The fix here is to provide the update struct before setting the source ID, and change the mixer to ignore update structs for voices without a source ID. This can pseudo-orphan the updates that get set on a voice just as it stops, leaving the struct unusable until the voice is used again, or the voice gets deleted which will clear it. But it allows the update struct to stay in place and get applied once the voice gets a source ID.
Diffstat (limited to 'alc')
-rw-r--r--alc/alu.cpp21
1 files changed, 7 insertions, 14 deletions
diff --git a/alc/alu.cpp b/alc/alu.cpp
index 862ba9a2..ae65fbcb 100644
--- a/alc/alu.cpp
+++ b/alc/alu.cpp
@@ -1576,17 +1576,7 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
void CalcSourceParams(ALvoice *voice, ALCcontext *context, bool force)
{
ALvoiceProps *props{voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel)};
- if(voice->mSourceID.load(std::memory_order_relaxed) == 0)
- {
- /* Don't update voices that no longer have a source. But make sure any
- * update struct it has is returned to the free list.
- */
- if UNLIKELY(props)
- AtomicReplaceHead(context->mFreeVoiceProps, props);
- return;
- }
- if(!props && !force)
- return;
+ if(!props && !force) return;
if(props)
{
@@ -1723,9 +1713,12 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray &slots,
for(ALeffectslot *slot : slots)
force |= CalcEffectSlotParams(slot, sorted_slots, ctx);
- auto calc_params = [ctx,force](ALvoice *voice) -> void
- { CalcSourceParams(voice, ctx, force); };
- std::for_each(voices.begin(), voices.end(), calc_params);
+ for(ALvoice *voice : voices)
+ {
+ /* Only update voices that have a source. */
+ if(voice->mSourceID.load(std::memory_order_relaxed) != 0)
+ CalcSourceParams(voice, ctx, force);
+ }
}
IncrementRef(ctx->mUpdateCount);
}