Avoid a full wipe and reallocation of wet buffers

This commit is contained in:
Chris Robinson
2020-11-02 05:08:23 -08:00
parent 52d58a4023
commit 03389f390c
2 changed files with 40 additions and 33 deletions
+6 -22
View File
@@ -2102,29 +2102,13 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
{
std::unique_lock<std::mutex> proplock{context->mPropLock};
std::unique_lock<std::mutex> 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()})
{
+34 -11
View File
@@ -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;
}