Allocate EffectSlots in clusters

master
Chris Robinson 2022-07-15 06:14:25 -07:00
parent 0b9fc03545
commit 0f4679981b
7 changed files with 55 additions and 6 deletions

View File

@ -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,

View File

@ -68,7 +68,7 @@ struct ALeffectslot {
/* Self ID */
ALuint id{};
ALeffectslot();
ALeffectslot(ALCcontext *context);
ALeffectslot(const ALeffectslot&) = delete;
ALeffectslot& operator=(const ALeffectslot&) = delete;
~ALeffectslot();

View File

@ -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);

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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.