From 03389f390c2b9979563b0901bdb73b2e0cd0e8fb Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 2 Nov 2020 05:08:23 -0800 Subject: [PATCH] Avoid a full wipe and reallocation of wet buffers --- alc/alc.cpp | 28 ++++++---------------------- alc/panning.cpp | 45 ++++++++++++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/alc/alc.cpp b/alc/alc.cpp index b3da9209..c94a9d53 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -2102,29 +2102,13 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) { std::unique_lock proplock{context->mPropLock}; std::unique_lock slotlock{context->mEffectSlotLock}; - /* HACK: Clear the effect slots' wet buffer references, and clear the wet - * buffer array so they're reallocated (with potentially a new channel - * count) when reinitialized. - */ - if(ALeffectslot *slot{context->mDefaultSlot.get()}) - { - slot->mWetBuffer = nullptr; - slot->Wet.Buffer = {}; - } - for(auto &sublist : context->mEffectSlotList) - { - uint64_t usemask{~sublist.FreeMask}; - while(usemask) - { - const ALsizei idx{CountTrailingZeros(usemask)}; - ALeffectslot *slot{sublist.EffectSlots + idx}; - usemask &= ~(1_u64 << idx); - slot->mWetBuffer = nullptr; - slot->Wet.Buffer = {}; - } - } - decltype(context->mWetBuffers){}.swap(context->mWetBuffers); + /* Clear out unused wet buffers. */ + auto buffer_not_in_use = [](WetBufferPtr &wetbuffer) noexcept -> bool + { return !wetbuffer->mInUse; }; + auto wetbuffer_iter = std::remove_if(context->mWetBuffers.begin(), + context->mWetBuffers.end(), buffer_not_in_use); + context->mWetBuffers.erase(wetbuffer_iter, context->mWetBuffers.end()); if(ALeffectslot *slot{context->mDefaultSlot.get()}) { diff --git a/alc/panning.cpp b/alc/panning.cpp index ee7f39eb..51c13771 100644 --- a/alc/panning.cpp +++ b/alc/panning.cpp @@ -1040,20 +1040,43 @@ void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context) ALCdevice *device{context->mDevice.get()}; const size_t count{AmbiChannelsFromOrder(device->mAmbiOrder)}; - ALuint idx{0}; - for(auto &wetbuffer : context->mWetBuffers) + auto wetbuffer_iter = context->mWetBuffers.end(); + if(slot->mWetBuffer) { - if(!wetbuffer->mInUse) - break; - ++idx; + /* If the effect slot already has a wet buffer attached, allocate a new + * one in its place. + */ + wetbuffer_iter = context->mWetBuffers.begin(); + for(;wetbuffer_iter != context->mWetBuffers.end();++wetbuffer_iter) + { + if(wetbuffer_iter->get() == slot->mWetBuffer) + { + slot->mWetBuffer = nullptr; + slot->Wet.Buffer = {}; + + *wetbuffer_iter = WetBufferPtr{new(FamCount(count)) WetBuffer{count}}; + + break; + } + } } - if(idx == context->mWetBuffers.size()) + if(wetbuffer_iter == context->mWetBuffers.end()) { - auto newbuffer = WetBufferPtr{new(FamCount(count)) WetBuffer{count}}; - context->mWetBuffers.emplace_back(std::move(newbuffer)); + /* Otherwise, search for an unused wet buffer. */ + wetbuffer_iter = context->mWetBuffers.begin(); + for(;wetbuffer_iter != context->mWetBuffers.end();++wetbuffer_iter) + { + if(!(*wetbuffer_iter)->mInUse) + break; + } + if(wetbuffer_iter == context->mWetBuffers.end()) + { + /* Otherwise, allocate a new one to use. */ + context->mWetBuffers.emplace_back(WetBufferPtr{new(FamCount(count)) WetBuffer{count}}); + wetbuffer_iter = context->mWetBuffers.end()-1; + } } - auto *wetbuffer = context->mWetBuffers[idx].get(); - slot->mWetBuffer = wetbuffer; + WetBuffer *wetbuffer{slot->mWetBuffer = wetbuffer_iter->get()}; wetbuffer->mInUse = true; auto acnmap_end = AmbiIndex::FromACN.begin() + count; @@ -1061,7 +1084,7 @@ void aluInitEffectPanning(ALeffectslot *slot, ALCcontext *context) [](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f, acn}; }); std::fill(iter, slot->Wet.AmbiMap.end(), BFChannelConfig{}); - slot->Wet.Buffer = {wetbuffer->mBuffer.data(), count}; + slot->Wet.Buffer = wetbuffer->mBuffer; } -- 2.11.4.GIT