Allocate voice properties in clusters

This commit is contained in:
Chris Robinson 2021-12-17 04:07:00 -08:00
parent 21bdea776a
commit c9537abfb1
5 changed files with 39 additions and 31 deletions

View File

@ -100,15 +100,15 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context
/* Get an unused property container, or allocate a new one as needed. */
VoicePropsItem *props{context->mFreeVoiceProps.load(std::memory_order_acquire)};
if(!props)
props = new VoicePropsItem{};
else
{
VoicePropsItem *next;
do {
next = props->next.load(std::memory_order_relaxed);
} while(context->mFreeVoiceProps.compare_exchange_weak(props, next,
std::memory_order_acq_rel, std::memory_order_acquire) == 0);
context->allocVoiceProps();
props = context->mFreeVoiceProps.load(std::memory_order_acquire);
}
VoicePropsItem *next;
do {
next = props->next.load(std::memory_order_relaxed);
} while(unlikely(context->mFreeVoiceProps.compare_exchange_weak(props, next,
std::memory_order_acq_rel, std::memory_order_acquire) == false));
props->Pitch = source->Pitch;
props->Gain = source->Gain;

View File

@ -2082,18 +2082,6 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
}
}
/* Clear any pre-existing voice property structs, in case the number of
* auxiliary sends is changing. Active sources will have updates
* respecified in UpdateAllSourceProps.
*/
VoicePropsItem *vprops{context->mFreeVoiceProps.exchange(nullptr, std::memory_order_acq_rel)};
while(vprops)
{
VoicePropsItem *next = vprops->next.load(std::memory_order_relaxed);
delete vprops;
vprops = next;
}
auto voicelist = context->getVoicesSpan();
for(Voice *voice : voicelist)
{
@ -2108,7 +2096,8 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
SendParams{});
}
delete voice->mUpdate.exchange(nullptr, std::memory_order_acq_rel);
if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)})
AtomicReplaceHead(context->mFreeVoiceProps, props);
/* Force the voice to stopped if it was stopping. */
Voice::State vstate{Voice::Stopping};
@ -2119,6 +2108,9 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList)
voice->prepare(device);
}
/* Clear all voice props to let them get allocated again. */
context->mVoicePropClusters.clear();
context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
srclock.unlock();
context->mPropsDirty.test_and_clear(std::memory_order_release);
@ -2173,6 +2165,9 @@ bool ResetDeviceParams(ALCdevice *device, const int *attrList)
vchg = next;
ctx->mCurrentVoiceChange.store(vchg, std::memory_order_release);
ctx->mVoicePropClusters.clear();
ctx->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed);
ctx->mVoiceClusters.clear();
ctx->allocVoices(std::max<size_t>(256,
ctx->mActiveVoiceCount.load(std::memory_order_relaxed)));

View File

@ -133,16 +133,6 @@ ContextBase::~ContextBase()
delete curarray;
}
count = 0;
VoicePropsItem *vprops{mFreeVoiceProps.exchange(nullptr, std::memory_order_acquire)};
while(vprops)
{
std::unique_ptr<VoicePropsItem> old{vprops};
vprops = old->next.load(std::memory_order_relaxed);
++count;
}
TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
delete mVoices.exchange(nullptr, std::memory_order_relaxed);
count = 0;
@ -198,6 +188,25 @@ void ContextBase::allocVoiceChanges(size_t addcount)
}
}
void ContextBase::allocVoiceProps()
{
constexpr size_t clustersize{32};
TRACE("Increasing allocated voice properties to %zu\n",
(mVoicePropClusters.size()+1) * clustersize);
VoicePropsCluster cluster{std::make_unique<VoicePropsItem[]>(clustersize)};
for(size_t i{1};i < clustersize;++i)
cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed);
mVoicePropClusters.emplace_back(std::move(cluster));
VoicePropsItem *oldhead{mFreeVoiceProps.load(std::memory_order_acquire)};
do {
mVoicePropClusters.back()[clustersize-1].next.store(oldhead, std::memory_order_relaxed);
} while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back().get(),
std::memory_order_acq_rel, std::memory_order_acquire) == false);
}
void ContextBase::allocVoices(size_t addcount)
{
constexpr size_t clustersize{32};

View File

@ -122,6 +122,7 @@ struct ContextBase {
std::atomic<VoiceChange*> mCurrentVoiceChange{};
void allocVoiceChanges(size_t addcount);
void allocVoiceProps();
ContextParams mParams;
@ -162,6 +163,9 @@ struct ContextBase {
using VoiceCluster = std::unique_ptr<Voice[]>;
al::vector<VoiceCluster> mVoiceClusters;
using VoicePropsCluster = std::unique_ptr<VoicePropsItem[]>;
al::vector<VoicePropsCluster> mVoicePropClusters;
ContextBase(DeviceBase *device);
ContextBase(const ContextBase&) = delete;

View File

@ -252,7 +252,7 @@ struct Voice {
al::vector<ChannelData> mChans{2};
Voice() = default;
~Voice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
~Voice() = default;
Voice(const Voice&) = delete;
Voice& operator=(const Voice&) = delete;