aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--al/auxeffectslot.cpp8
-rw-r--r--al/auxeffectslot.h2
-rw-r--r--alc/alc.cpp14
-rw-r--r--alc/context.cpp7
-rw-r--r--core/context.cpp21
-rw-r--r--core/context.h7
-rw-r--r--core/effectslot.h2
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.