diff options
author | Chris Robinson <[email protected]> | 2020-11-07 08:36:49 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2020-11-07 08:36:49 -0800 |
commit | 4e760bbecc6ac4031dca45b4882c6faa71842e90 (patch) | |
tree | e639b40d42ef8f2c3511e93a965cddb31245a729 /al | |
parent | 120776bec5f908104f0e76453402ff45a0762846 (diff) |
Use a separate structure for the active effect slot properties
Diffstat (limited to 'al')
-rw-r--r-- | al/auxeffectslot.cpp | 72 | ||||
-rw-r--r-- | al/auxeffectslot.h | 49 | ||||
-rw-r--r-- | al/source.cpp | 6 |
3 files changed, 42 insertions, 85 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index df04f430..8271f988 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -94,16 +94,16 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *context) { if(slotids.empty()) return; - ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; size_t newcount{curarray->size() + slotids.size()}; /* Insert the new effect slots into the head of the array, followed by the * existing ones. */ - ALeffectslotArray *newarray = ALeffectslot::CreatePtrArray(newcount); + EffectSlotArray *newarray = EffectSlot::CreatePtrArray(newcount); auto slotiter = std::transform(slotids.begin(), slotids.end(), newarray->begin(), - [context](ALuint id) noexcept -> ALeffectslot* - { return LookupEffectSlot(context, id); }); + [context](ALuint id) noexcept -> EffectSlot* + { return &LookupEffectSlot(context, id)->mSlot; }); std::copy(curarray->begin(), curarray->end(), slotiter); /* Remove any duplicates (first instance of each will be kept). */ @@ -122,7 +122,7 @@ void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *cont if UNLIKELY(newcount < newarray->size()) { curarray = newarray; - newarray = ALeffectslot::CreatePtrArray(newcount); + newarray = EffectSlot::CreatePtrArray(newcount); std::copy_n(curarray->begin(), newcount, newarray->begin()); delete curarray; curarray = nullptr; @@ -139,24 +139,31 @@ void AddActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *cont void RemoveActiveEffectSlots(const al::span<const ALuint> slotids, ALCcontext *context) { if(slotids.empty()) return; - ALeffectslotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; /* Don't shrink the allocated array size since we don't know how many (if * any) of the effect slots to remove are in the array. */ - ALeffectslotArray *newarray = ALeffectslot::CreatePtrArray(curarray->size()); + EffectSlotArray *newarray = EffectSlot::CreatePtrArray(curarray->size()); - /* Copy each element in curarray to newarray whose ID is not in slotids. */ - auto slotiter = std::copy_if(curarray->begin(), curarray->end(), newarray->begin(), - [slotids](const ALeffectslot *slot) -> bool - { return std::find(slotids.begin(), slotids.end(), slot->id) == slotids.end(); }); + auto new_end = std::copy(curarray->begin(), curarray->end(), newarray->begin()); + /* Remove elements from newarray that match any ID in slotids. */ + for(const ALuint id : slotids) + { + if(ALeffectslot *auxslot{LookupEffectSlot(context, id)}) + { + auto proc_match = [auxslot](EffectSlot *slot) noexcept -> bool + { return (slot == &auxslot->mSlot); }; + new_end = std::remove_if(newarray->begin(), new_end, proc_match); + } + } /* Reallocate with the new size. */ - auto newsize = static_cast<size_t>(std::distance(newarray->begin(), slotiter)); + auto newsize = static_cast<size_t>(std::distance(newarray->begin(), new_end)); if LIKELY(newsize != newarray->size()) { curarray = newarray; - newarray = ALeffectslot::CreatePtrArray(newsize); + newarray = EffectSlot::CreatePtrArray(newsize); std::copy_n(curarray->begin(), newsize, newarray->begin()); delete curarray; @@ -250,15 +257,6 @@ void FreeEffectSlot(ALCcontext *context, ALeffectslot *slot) } // namespace -ALeffectslotArray *ALeffectslot::CreatePtrArray(size_t count) noexcept -{ - /* Allocate space for twice as many pointers, so the mixer has scratch - * space to store a sorted list during mixing. - */ - void *ptr{al_calloc(alignof(ALeffectslotArray), ALeffectslotArray::Sizeof(count*2))}; - return new (ptr) ALeffectslotArray{count}; -} - AL_API void AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) START_API_FUNC @@ -814,7 +812,7 @@ ALeffectslot::~ALeffectslot() DecrementRef(Buffer->ref); Buffer = nullptr; - ALeffectslotProps *props{Params.Update.load()}; + EffectSlotProps *props{mSlot.Update.exchange(nullptr)}; if(props) { TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", @@ -824,8 +822,8 @@ ALeffectslot::~ALeffectslot() if(mWetBuffer) mWetBuffer->mInUse = false; - if(Params.mEffectState) - Params.mEffectState->release(); + if(mSlot.mEffectState) + mSlot.mEffectState->release(); } ALenum ALeffectslot::init() @@ -837,7 +835,7 @@ ALenum ALeffectslot::init() if(!Effect.State) return AL_OUT_OF_MEMORY; Effect.State->add_ref(); - Params.mEffectState = Effect.State.get(); + mSlot.mEffectState = Effect.State.get(); return AL_NO_ERROR; } @@ -882,7 +880,7 @@ ALenum ALeffectslot::initEffect(ALeffect *effect, ALCcontext *context) Effect.Props = effect->Props; /* Remove state references from old effect slot property updates. */ - ALeffectslotProps *props{context->mFreeEffectslotProps.load()}; + EffectSlotProps *props{context->mFreeEffectslotProps.load()}; while(props) { props->State = nullptr; @@ -895,12 +893,12 @@ ALenum ALeffectslot::initEffect(ALeffect *effect, ALCcontext *context) void ALeffectslot::updateProps(ALCcontext *context) { /* Get an unused property container, or allocate a new one as needed. */ - ALeffectslotProps *props{context->mFreeEffectslotProps.load(std::memory_order_relaxed)}; + EffectSlotProps *props{context->mFreeEffectslotProps.load(std::memory_order_relaxed)}; if(!props) - props = new ALeffectslotProps{}; + props = new EffectSlotProps{}; else { - ALeffectslotProps *next; + EffectSlotProps *next; do { next = props->next.load(std::memory_order_relaxed); } while(context->mFreeEffectslotProps.compare_exchange_weak(props, next, @@ -910,14 +908,14 @@ void ALeffectslot::updateProps(ALCcontext *context) /* Copy in current property values. */ props->Gain = Gain; props->AuxSendAuto = AuxSendAuto; - props->Target = Target; + props->Target = Target ? &Target->mSlot : nullptr; props->Type = Effect.Type; props->Props = Effect.Props; props->State = Effect.State; /* Set the new container for updating internal parameters. */ - props = Params.Update.exchange(props, std::memory_order_acq_rel); + props = mSlot.Update.exchange(props, std::memory_order_acq_rel); if(props) { /* If there was an unused update container, put it back in the @@ -931,11 +929,13 @@ void ALeffectslot::updateProps(ALCcontext *context) void UpdateAllEffectSlotProps(ALCcontext *context) { std::lock_guard<std::mutex> _{context->mEffectSlotLock}; - ALeffectslotArray *auxslots{context->mActiveAuxSlots.load(std::memory_order_acquire)}; - for(ALeffectslot *slot : *auxslots) + EffectSlotArray *slots{context->mActiveAuxSlots.load(std::memory_order_acquire)}; + for(EffectSlot *slot : *slots) { - if(!slot->PropsClean.test_and_set(std::memory_order_acq_rel)) - slot->updateProps(context); + ALeffectslot *auxslot{reinterpret_cast<ALeffectslot*>( + reinterpret_cast<al::byte*>(slot) - offsetof(ALeffectslot,mSlot))}; + if(!auxslot->PropsClean.test_and_set(std::memory_order_acq_rel)) + auxslot->updateProps(context); } } diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 03ba034a..c2967c93 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -11,35 +11,16 @@ #include "alcmain.h" #include "almalloc.h" #include "atomic.h" +#include "effectslot.h" #include "effects/base.h" #include "intrusive_ptr.h" #include "vector.h" struct ALbuffer; struct ALeffect; -struct ALeffectslot; struct WetBuffer; -using ALeffectslotArray = al::FlexArray<ALeffectslot*>; - - -struct ALeffectslotProps { - float Gain; - bool AuxSendAuto; - ALeffectslot *Target; - - ALenum Type; - EffectProps Props; - - al::intrusive_ptr<EffectState> State; - - std::atomic<ALeffectslotProps*> next; - - DEF_NEWDEL(ALeffectslotProps) -}; - - enum class SlotState : ALenum { Initial = AL_INITIAL, Playing = AL_PLAYING, @@ -65,24 +46,7 @@ struct ALeffectslot { RefCount ref{0u}; - struct { - std::atomic<ALeffectslotProps*> Update{nullptr}; - - float Gain{1.0f}; - bool AuxSendAuto{true}; - ALeffectslot *Target{nullptr}; - - ALenum EffectType{AL_EFFECT_NULL}; - EffectProps mEffectProps{}; - EffectState *mEffectState{nullptr}; - - float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */ - float DecayTime{0.0f}; - float DecayLFRatio{0.0f}; - float DecayHFRatio{0.0f}; - bool DecayHFLimit{false}; - float AirAbsorptionGainHF{1.0f}; - } Params; + EffectSlot mSlot; /* Self ID */ ALuint id{}; @@ -90,13 +54,6 @@ struct ALeffectslot { /* Mixing buffer used by the Wet mix. */ WetBuffer *mWetBuffer{nullptr}; - /* Wet buffer configuration is ACN channel order with N3D scaling. - * Consequently, effects that only want to work with mono input can use - * channel 0 by itself. Effects that want multichannel can process the - * ambisonics signal and make a B-Format source pan. - */ - MixParams Wet; - ALeffectslot() { PropsClean.test_and_set(std::memory_order_relaxed); } ALeffectslot(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete; @@ -106,8 +63,6 @@ struct ALeffectslot { ALenum initEffect(ALeffect *effect, ALCcontext *context); void updateProps(ALCcontext *context); - static ALeffectslotArray *CreatePtrArray(size_t count) noexcept; - /* This can be new'd for the context's default effect slot. */ DEF_NEWDEL(ALeffectslot) }; diff --git a/al/source.cpp b/al/source.cpp index 64a7afc1..d089f24c 100644 --- a/al/source.cpp +++ b/al/source.cpp @@ -149,8 +149,8 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context auto copy_send = [](const ALsource::SendData &srcsend) noexcept -> VoiceProps::SendData { - VoiceProps::SendData ret; - ret.Slot = srcsend.Slot; + VoiceProps::SendData ret{}; + ret.Slot = srcsend.Slot ? &srcsend.Slot->mSlot : nullptr; ret.Gain = srcsend.Gain; ret.GainHF = srcsend.GainHF; ret.HFReference = srcsend.HFReference; @@ -159,6 +159,8 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context return ret; }; std::transform(source->Send.cbegin(), source->Send.cend(), props->Send, copy_send); + if(!props->Send[0].Slot && context->mDefaultSlot) + props->Send[0].Slot = &context->mDefaultSlot->mSlot; /* Set the new container for updating internal parameters. */ props = voice->mUpdate.exchange(props, std::memory_order_acq_rel); |