diff options
-rw-r--r-- | al/auxeffectslot.cpp | 4 | ||||
-rw-r--r-- | alc/alc.cpp | 8 | ||||
-rw-r--r-- | alc/alu.cpp | 24 |
3 files changed, 29 insertions, 7 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 3c312c66..efc75aac 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -114,11 +114,13 @@ void AddActiveEffectSlots(const ALuint *slotids, size_t count, ALCcontext *conte delete curarray; curarray = nullptr; } + std::uninitialized_fill_n(newarray->end(), newcount, nullptr); curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); ALCdevice *device{context->mDevice.get()}; while((device->MixCount.load(std::memory_order_acquire)&1)) std::this_thread::yield(); + al::destroy_n(curarray->end(), curarray->size()); delete curarray; } @@ -150,11 +152,13 @@ void RemoveActiveEffectSlots(const ALuint *slotids, size_t count, ALCcontext *co delete curarray; curarray = nullptr; } + std::uninitialized_fill_n(newarray->end(), newsize, nullptr); curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); ALCdevice *device{context->mDevice.get()}; while((device->MixCount.load(std::memory_order_acquire)&1)) std::this_thread::yield(); + al::destroy_n(curarray->end(), curarray->size()); delete curarray; } diff --git a/alc/alc.cpp b/alc/alc.cpp index b077e796..f716bf0b 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2169,6 +2169,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) std::unique_lock<std::mutex> proplock{context->mPropLock}; std::unique_lock<std::mutex> slotlock{context->mEffectSlotLock}; + if(ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)}) + std::fill_n(curarray->end(), curarray->size(), nullptr); for(auto &sublist : context->mEffectSlotList) { uint64_t usemask = ~sublist.FreeMask; @@ -2461,7 +2463,11 @@ ALCcontext::~ALCcontext() } TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); - delete mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed); + if(ALeffectslotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) + { + al::destroy_n(curarray->end(), curarray->size()); + delete curarray; + } mDefaultSlot = nullptr; count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u}, diff --git a/alc/alu.cpp b/alc/alu.cpp index 02d5e66f..b337286b 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -437,11 +437,16 @@ bool CalcListenerParams(ALCcontext *Context) return true; } -bool CalcEffectSlotParams(ALeffectslot *slot, ALCcontext *context) +bool CalcEffectSlotParams(ALeffectslot *slot, ALeffectslot **sorted_slots, ALCcontext *context) { ALeffectslotProps *props{slot->Params.Update.exchange(nullptr, std::memory_order_acq_rel)}; if(!props) return false; + /* If the effect slot target changed, clear the first sorted entry to force + * a re-sort. + */ + if(slot->Params.Target != props->Target) + *sorted_slots = nullptr; slot->Params.Gain = props->Gain; slot->Params.AuxSendAuto = props->AuxSendAuto; slot->Params.Target = props->Target; @@ -1599,9 +1604,9 @@ void ProcessParamUpdates(ALCcontext *ctx, const ALeffectslotArray &slots, { bool force{CalcContextParams(ctx)}; force |= CalcListenerParams(ctx); - force = std::accumulate(slots.begin(), slots.end(), force, - [ctx](const bool f, ALeffectslot *slot) -> bool - { return CalcEffectSlotParams(slot, ctx) | f; }); + auto sorted_slots = const_cast<ALeffectslot**>(slots.data() + slots.size()); + for(ALeffectslot *slot : slots) + force |= CalcEffectSlotParams(slot, sorted_slots, ctx); auto calc_params = [ctx,force](ALvoice &voice) -> void { CalcSourceParams(&voice, ctx, force); }; @@ -1642,11 +1647,17 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo) auto slots = auxslots.data(); auto slots_end = slots + num_slots; - /* First sort the slots into scratch storage, so that effects come - * before their effect target (or their targets' target). + /* First sort the slots into extra storage, so that effects come before + * their effect target (or their targets' target). */ auto sorted_slots = const_cast<ALeffectslot**>(slots_end); auto sorted_slots_end = sorted_slots; + if(*sorted_slots) + { + /* Skip sorting if it has already been done. */ + sorted_slots_end += num_slots; + goto skip_sorting; + } *sorted_slots_end = *slots; ++sorted_slots_end; @@ -1674,6 +1685,7 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo) ++sorted_slots_end; } + skip_sorting: auto process_effect = [SamplesToDo](const ALeffectslot *slot) -> void { EffectState *state{slot->Params.mEffectState}; |