Allocate EffectSlots in clusters
parent
0b9fc03545
commit
0f4679981b
|
@ -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,
|
||||
|
|
|
@ -68,7 +68,7 @@ struct ALeffectslot {
|
|||
/* Self ID */
|
||||
ALuint id{};
|
||||
|
||||
ALeffectslot();
|
||||
ALeffectslot(ALCcontext *context);
|
||||
ALeffectslot(const ALeffectslot&) = delete;
|
||||
ALeffectslot& operator=(const ALeffectslot&) = delete;
|
||||
~ALeffectslot();
|
||||
|
|
14
alc/alc.cpp
14
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue