diff options
-rw-r--r-- | al/auxeffectslot.cpp | 8 | ||||
-rw-r--r-- | al/auxeffectslot.h | 2 | ||||
-rw-r--r-- | alc/alc.cpp | 14 | ||||
-rw-r--r-- | alc/context.cpp | 7 | ||||
-rw-r--r-- | core/context.cpp | 21 | ||||
-rw-r--r-- | core/context.h | 7 | ||||
-rw-r--r-- | core/effectslot.h | 2 |
7 files changed, 55 insertions, 6 deletions
diff --git a/al/auxeffectslot.cpp b/al/auxeffectslot.cpp index 25814e83..aaf9ce4c 100644 --- a/al/auxeffectslot.cpp +++ b/al/auxeffectslot.cpp @@ -278,7 +278,7 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context) auto slidx = static_cast<ALuint>(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALeffectslot *slot{al::construct_at(sublist->EffectSlots + slidx)}; + ALeffectslot *slot{al::construct_at(sublist->EffectSlots + slidx, context)}; aluInitEffectPanning(slot->mSlot, context); /* Add 1 to avoid source ID 0. */ @@ -907,7 +907,7 @@ START_API_FUNC END_API_FUNC -ALeffectslot::ALeffectslot() +ALeffectslot::ALeffectslot(ALCcontext *context) { EffectStateFactory *factory{getFactoryByType(EffectSlotType::None)}; if(!factory) throw std::runtime_error{"Failed to get null effect factory"}; @@ -915,7 +915,7 @@ ALeffectslot::ALeffectslot() al::intrusive_ptr<EffectState> state{factory->create()}; Effect.State = state; - mSlot = new EffectSlot{}; + mSlot = context->getEffectSlot(); mSlot->mEffectState = state.release(); } @@ -938,7 +938,7 @@ ALeffectslot::~ALeffectslot() if(mSlot->mEffectState) mSlot->mEffectState->release(); - delete mSlot; + mSlot->InUse = false; } ALenum ALeffectslot::initEffect(ALenum effectType, const EffectProps &effectProps, diff --git a/al/auxeffectslot.h b/al/auxeffectslot.h index 8b80a2d4..b8b41174 100644 --- a/al/auxeffectslot.h +++ b/al/auxeffectslot.h @@ -68,7 +68,7 @@ struct ALeffectslot { /* Self ID */ ALuint id{}; - ALeffectslot(); + ALeffectslot(ALCcontext *context); ALeffectslot(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete; ~ALeffectslot(); diff --git a/alc/alc.cpp b/alc/alc.cpp index 3ce14dac..4a142ca6 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2224,6 +2224,20 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) context->mWetBuffers.end(), buffer_not_in_use); context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end()); + /* Clear out unused effect slot clusters. */ + auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &cluster) + { + for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i) + { + if(cluster[i].InUse) + return false; + } + return true; + }; + auto slotcluster_iter = std::remove_if(context->mEffectSlotClusters.begin(), + context->mEffectSlotClusters.end(), slot_cluster_not_in_use); + context->mEffectSlotClusters.erase(slotcluster_iter, context->mEffectSlotClusters.end()); + if(ALeffectslot *slot{context->mDefaultSlot.get()}) { aluInitEffectPanning(slot->mSlot, context); diff --git a/alc/context.cpp b/alc/context.cpp index 456e42da..4d04526a 100644 --- a/alc/context.cpp +++ b/alc/context.cpp @@ -128,6 +128,9 @@ ALCcontext::~ALCcontext() eax_uninitialize(); #endif // ALSOFT_EAX + /* Delete the ALeffectslots, so the EffectSlots can be deleted before the + * WetBuffers are deleted. + */ mDefaultSlot = nullptr; count = std::accumulate(mEffectSlotList.cbegin(), mEffectSlotList.cend(), size_t{0u}, [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t @@ -136,13 +139,15 @@ ALCcontext::~ALCcontext() WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s"); mEffectSlotList.clear(); mNumEffectSlots = 0; + + mEffectSlotClusters.clear(); } void ALCcontext::init() { if(sDefaultEffect.type != AL_EFFECT_NULL && mDevice->Type == DeviceType::Playback) { - mDefaultSlot = std::make_unique<ALeffectslot>(); + mDefaultSlot = std::make_unique<ALeffectslot>(this); aluInitEffectPanning(mDefaultSlot->mSlot, this); } diff --git a/core/context.cpp b/core/context.cpp index 39fd8522..111802d9 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -136,3 +136,24 @@ void ContextBase::allocVoices(size_t addcount) delete oldvoices; } } + + +EffectSlot *ContextBase::getEffectSlot() +{ + for(auto& cluster : mEffectSlotClusters) + { + for(size_t i{0};i < EffectSlotClusterSize;++i) + { + if(!cluster[i].InUse) + return &cluster[i]; + } + } + + if(1 >= std::numeric_limits<int>::max()/EffectSlotClusterSize - mEffectSlotClusters.size()) + throw std::runtime_error{"Allocating too many effect slots"}; + const size_t totalcount{(mEffectSlotClusters.size()+1) * EffectSlotClusterSize}; + TRACE("Increasing allocated effect slots to %zu\n", totalcount); + + mEffectSlotClusters.emplace_back(std::make_unique<EffectSlot[]>(EffectSlotClusterSize)); + return getEffectSlot(); +} diff --git a/core/context.h b/core/context.h index f5768629..d2e6b546 100644 --- a/core/context.h +++ b/core/context.h @@ -163,6 +163,13 @@ struct ContextBase { al::vector<VoicePropsCluster> mVoicePropClusters; + static constexpr size_t EffectSlotClusterSize{4}; + EffectSlot *getEffectSlot(); + + using EffectSlotCluster = std::unique_ptr<EffectSlot[]>; + al::vector<EffectSlotCluster> mEffectSlotClusters; + + ContextBase(DeviceBase *device); ContextBase(const ContextBase&) = delete; ContextBase& operator=(const ContextBase&) = delete; diff --git a/core/effectslot.h b/core/effectslot.h index 92fd1961..2470326d 100644 --- a/core/effectslot.h +++ b/core/effectslot.h @@ -51,6 +51,8 @@ struct EffectSlotProps { struct EffectSlot { + bool InUse{false}; + std::atomic<EffectSlotProps*> Update{nullptr}; /* Wet buffer configuration is ACN channel order with N3D scaling. |