Use a normal vector for the voices array
This commit is contained in:
parent
c47a6d2279
commit
ef2769af03
@ -77,10 +77,10 @@ using namespace std::placeholders;
|
||||
ALvoice *GetSourceVoice(ALsource *source, ALCcontext *context)
|
||||
{
|
||||
ALuint idx{source->VoiceIdx};
|
||||
if(idx < context->mVoiceCount.load(std::memory_order_relaxed))
|
||||
if(idx < context->mVoices.size())
|
||||
{
|
||||
ALuint sid{source->id};
|
||||
ALvoice &voice = (*context->mVoices)[idx];
|
||||
ALvoice &voice = context->mVoices[idx];
|
||||
if(voice.mSourceID.load(std::memory_order_acquire) == sid)
|
||||
return &voice;
|
||||
}
|
||||
@ -2671,38 +2671,20 @@ START_API_FUNC
|
||||
}
|
||||
|
||||
/* Count the number of reusable voices. */
|
||||
auto voices_end = context->mVoices->begin() +
|
||||
context->mVoiceCount.load(std::memory_order_relaxed);
|
||||
auto free_voices = std::accumulate(context->mVoices->begin(), voices_end, ALsizei{0},
|
||||
[](const ALsizei count, const ALvoice &voice) noexcept -> ALsizei
|
||||
{
|
||||
if(voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice.mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
return count + 1;
|
||||
return count;
|
||||
}
|
||||
);
|
||||
auto count_free_voices = [](const ALsizei count, const ALvoice &voice) noexcept -> ALsizei
|
||||
{
|
||||
if(voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
voice.mSourceID.load(std::memory_order_relaxed) == 0u)
|
||||
return count + 1;
|
||||
return count;
|
||||
};
|
||||
auto free_voices = std::accumulate(context->mVoices.begin(), context->mVoices.end(),
|
||||
ALsizei{0}, count_free_voices);
|
||||
if UNLIKELY(n > free_voices)
|
||||
{
|
||||
/* Increment the number of voices to handle the request. */
|
||||
/* Increase the number of voices to handle the request. */
|
||||
const ALuint need_voices{static_cast<ALuint>(n) - free_voices};
|
||||
const size_t rem_voices{context->mVoices->size() -
|
||||
context->mVoiceCount.load(std::memory_order_relaxed)};
|
||||
|
||||
if UNLIKELY(need_voices > rem_voices)
|
||||
{
|
||||
/* Allocate more voices to get enough. */
|
||||
const size_t alloc_count{need_voices - rem_voices};
|
||||
if UNLIKELY(context->mVoices->size() > std::numeric_limits<ALsizei>::max()-alloc_count)
|
||||
SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
|
||||
"Overflow increasing voice count to %zu + %zu", context->mVoices->size(),
|
||||
alloc_count);
|
||||
|
||||
const size_t newcount{context->mVoices->size() + alloc_count};
|
||||
context->allocVoices(newcount);
|
||||
}
|
||||
|
||||
context->mVoiceCount.fetch_add(need_voices, std::memory_order_relaxed);
|
||||
context->mVoices.resize(context->mVoices.size() + need_voices);
|
||||
}
|
||||
|
||||
auto start_source = [&context,device](ALsource *source) -> void
|
||||
@ -2757,9 +2739,8 @@ START_API_FUNC
|
||||
}
|
||||
|
||||
/* Look for an unused voice to play this source with. */
|
||||
auto voices_end = context->mVoices->begin() +
|
||||
context->mVoiceCount.load(std::memory_order_relaxed);
|
||||
voice = std::find_if(context->mVoices->begin(), voices_end,
|
||||
auto voices_end = context->mVoices.data() + context->mVoices.size();
|
||||
voice = std::find_if(context->mVoices.data(), voices_end,
|
||||
[](const ALvoice &voice) noexcept -> bool
|
||||
{
|
||||
return voice.mPlayState.load(std::memory_order_acquire) == ALvoice::Stopped &&
|
||||
@ -2767,7 +2748,7 @@ START_API_FUNC
|
||||
}
|
||||
);
|
||||
assert(voice != voices_end);
|
||||
auto vidx = static_cast<ALuint>(std::distance(context->mVoices->begin(), voice));
|
||||
auto vidx = static_cast<ALuint>(std::distance(context->mVoices.data(), voice));
|
||||
voice->mPlayState.store(ALvoice::Stopped, std::memory_order_release);
|
||||
|
||||
source->PropsClean.test_and_set(std::memory_order_acquire);
|
||||
@ -3317,9 +3298,7 @@ ALsource::~ALsource()
|
||||
void UpdateAllSourceProps(ALCcontext *context)
|
||||
{
|
||||
std::lock_guard<std::mutex> _{context->mSourceLock};
|
||||
auto voices_end = context->mVoices->begin() +
|
||||
context->mVoiceCount.load(std::memory_order_relaxed);
|
||||
std::for_each(context->mVoices->begin(), voices_end,
|
||||
std::for_each(context->mVoices.begin(), context->mVoices.end(),
|
||||
[context](ALvoice &voice) -> void
|
||||
{
|
||||
ALuint sid{voice.mSourceID.load(std::memory_order_acquire)};
|
||||
|
50
alc/alc.cpp
50
alc/alc.cpp
@ -2182,8 +2182,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
vprops = next;
|
||||
}
|
||||
|
||||
auto voices = context->mVoices.get();
|
||||
auto voices_end = voices->begin() + context->mVoiceCount.load(std::memory_order_relaxed);
|
||||
if(device->NumAuxSends < old_sends)
|
||||
{
|
||||
const ALsizei num_sends{device->NumAuxSends};
|
||||
@ -2201,7 +2199,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
};
|
||||
std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
|
||||
};
|
||||
std::for_each(voices->begin(), voices_end, clear_sends);
|
||||
std::for_each(context->mVoices.begin(), context->mVoices.end(), clear_sends);
|
||||
}
|
||||
auto reset_voice = [device](ALvoice &voice) -> void
|
||||
{
|
||||
@ -2225,7 +2223,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
|
||||
init_nfc);
|
||||
}
|
||||
};
|
||||
std::for_each(voices->begin(), voices_end, reset_voice);
|
||||
std::for_each(context->mVoices.begin(), context->mVoices.end(), reset_voice);
|
||||
srclock.unlock();
|
||||
|
||||
context->mPropsClean.test_and_set(std::memory_order_release);
|
||||
@ -2378,8 +2376,7 @@ ALCcontext::~ALCcontext()
|
||||
}
|
||||
TRACE("Freed %zu voice property object%s\n", count, (count==1)?"":"s");
|
||||
|
||||
mVoices = nullptr;
|
||||
mVoiceCount.store(0, std::memory_order_relaxed);
|
||||
mVoices.clear();
|
||||
|
||||
ALlistenerProps *lprops{mListener.Params.Update.exchange(nullptr, std::memory_order_relaxed)};
|
||||
if(lprops)
|
||||
@ -2459,7 +2456,8 @@ void ALCcontext::init()
|
||||
StartEventThrd(this);
|
||||
|
||||
|
||||
allocVoices(256);
|
||||
mVoices.reserve(256);
|
||||
mVoices.resize(64);
|
||||
}
|
||||
|
||||
bool ALCcontext::deinit()
|
||||
@ -2548,44 +2546,6 @@ ContextRef GetContextRef(void)
|
||||
}
|
||||
|
||||
|
||||
void ALCcontext::allocVoices(size_t num_voices)
|
||||
{
|
||||
const ALsizei num_sends{mDevice->NumAuxSends};
|
||||
|
||||
if(mVoices && num_voices == mVoices->size())
|
||||
return;
|
||||
|
||||
using ALvoiceArray = al::FlexArray<ALvoice>;
|
||||
std::unique_ptr<ALvoiceArray> voices{ALvoiceArray::Create(num_voices)};
|
||||
|
||||
const size_t v_count{minz(mVoiceCount.load(std::memory_order_relaxed), num_voices)};
|
||||
if(mVoices)
|
||||
{
|
||||
/* Copy the old voice data to the new storage. */
|
||||
auto viter = std::move(mVoices->begin(), mVoices->begin()+v_count, voices->begin());
|
||||
|
||||
/* Clear extraneous property set sends. */
|
||||
auto clear_sends = [num_sends](ALvoice &voice) -> void
|
||||
{
|
||||
std::fill(std::begin(voice.mProps.Send)+num_sends, std::end(voice.mProps.Send),
|
||||
ALvoiceProps::SendData{});
|
||||
|
||||
std::fill(voice.mSend.begin()+num_sends, voice.mSend.end(), ALvoice::SendData{});
|
||||
auto clear_chan_sends = [num_sends](ALvoice::ChannelData &chandata) -> void
|
||||
{
|
||||
std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(),
|
||||
SendParams{});
|
||||
};
|
||||
std::for_each(voice.mChans.begin(), voice.mChans.end(), clear_chan_sends);
|
||||
};
|
||||
std::for_each(voices->begin(), viter, clear_sends);
|
||||
}
|
||||
|
||||
mVoices = std::move(voices);
|
||||
mVoiceCount.store(static_cast<ALuint>(v_count), std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
|
||||
/************************************************
|
||||
* Standard ALC functions
|
||||
************************************************/
|
||||
|
@ -127,8 +127,7 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> {
|
||||
std::atomic<ALvoiceProps*> mFreeVoiceProps{nullptr};
|
||||
std::atomic<ALeffectslotProps*> mFreeEffectslotProps{nullptr};
|
||||
|
||||
std::unique_ptr<al::FlexArray<ALvoice>> mVoices{nullptr};
|
||||
std::atomic<ALuint> mVoiceCount{0u};
|
||||
al::vector<ALvoice> mVoices;
|
||||
|
||||
using ALeffectslotArray = al::FlexArray<ALeffectslot*>;
|
||||
std::atomic<ALeffectslotArray*> mActiveAuxSlots{nullptr};
|
||||
@ -163,8 +162,6 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> {
|
||||
*/
|
||||
bool deinit();
|
||||
|
||||
void allocVoices(size_t num_voices);
|
||||
|
||||
/**
|
||||
* Defers/suspends updates for the given context's listener and sources.
|
||||
* This does *NOT* stop mixing, but rather prevents certain property
|
||||
|
@ -1348,8 +1348,7 @@ void ProcessContext(ALCcontext *ctx, const ALuint SamplesToDo)
|
||||
ASSUME(SamplesToDo > 0);
|
||||
|
||||
const ALeffectslotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire);
|
||||
const al::span<ALvoice> voices{ctx->mVoices->data(),
|
||||
ctx->mVoiceCount.load(std::memory_order_acquire)};
|
||||
const al::span<ALvoice> voices{ctx->mVoices.data(), ctx->mVoices.size()};
|
||||
|
||||
/* Process pending propery updates for objects on the context. */
|
||||
ProcessParamUpdates(ctx, auxslots, voices);
|
||||
@ -1755,9 +1754,7 @@ void aluHandleDisconnect(ALCdevice *device, const char *msg, ...)
|
||||
voice.mSourceID.store(0u, std::memory_order_relaxed);
|
||||
voice.mPlayState.store(ALvoice::Stopped, std::memory_order_release);
|
||||
};
|
||||
std::for_each(ctx->mVoices->begin(),
|
||||
ctx->mVoices->begin() + ctx->mVoiceCount.load(std::memory_order_acquire),
|
||||
stop_voice);
|
||||
std::for_each(ctx->mVoices.begin(), ctx->mVoices.end(), stop_voice);
|
||||
}
|
||||
IncrementRef(device->MixCount);
|
||||
}
|
||||
|
@ -269,6 +269,7 @@ struct ALvoice {
|
||||
|
||||
ALvoice() = default;
|
||||
ALvoice(const ALvoice&) = delete;
|
||||
ALvoice(ALvoice&& rhs) noexcept { *this = std::move(rhs); }
|
||||
~ALvoice() { delete mUpdate.exchange(nullptr, std::memory_order_acq_rel); }
|
||||
ALvoice& operator=(const ALvoice&) = delete;
|
||||
ALvoice& operator=(ALvoice&& rhs) noexcept
|
||||
|
Loading…
Reference in New Issue
Block a user